Skip to content

Commit

Permalink
feat(angular): adds generics to CanPipe
Browse files Browse the repository at this point in the history
Relates to #256 BREAKING CHANGES
  • Loading branch information
stalniy committed Feb 17, 2020
1 parent 4e56fda commit 68bd287
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 15 deletions.
4 changes: 2 additions & 2 deletions packages/casl-angular/spec/module.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ describe('Ability', () => {

it('updates template when `ability` is updated', () => {
fixture = createComponent(App, { post })
ability.update([{ subject: Post.name, actions: 'read' }])
ability.update([{ subject: Post.name, action: 'read' }])
fixture.detectChanges()

expect(fixture.nativeElement.textContent).to.equal('true')
})

describe('when abilities depends on object attribute', () => {
beforeEach(() => {
ability.update([{ subject: Post.name, actions: 'read', conditions: { author: 'me' } }])
ability.update([{ subject: Post.name, action: 'read', conditions: { author: 'me' } }])
fixture = createComponent(App, { post })
fixture.detectChanges()
})
Expand Down
15 changes: 9 additions & 6 deletions packages/casl-angular/src/can.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import { Pipe, ChangeDetectorRef } from '@angular/core';
import { Ability, Unsubscribe, CanArgsType } from '@casl/ability';
import { Ability, Unsubscribe, Subject } from '@casl/ability';

const noop = () => {};

// TODO: `pure` can be removed after https://github.com/angular/angular/issues/15041
@Pipe({ name: 'can', pure: false })
export class CanPipe {
export class CanPipe<A extends string, S extends Subject, C> {
protected _unsubscribeFromAbility: Unsubscribe = noop;

constructor(protected ability: Ability, protected cd: ChangeDetectorRef) {
constructor(
protected ability: Ability<A, S, C>,
protected cd: ChangeDetectorRef
) {
}

transform(subject: CanArgsType[1], action: CanArgsType[0], field?: CanArgsType[2]): boolean {
transform(subject: S, action: A, field?: string): boolean {
if (this._unsubscribeFromAbility === noop) {
this._unsubscribeFromAbility = this.ability.on('updated', () => this.cd.markForCheck());
}

return this.can(action, subject, field);
}

can(action: CanArgsType[0], subject: CanArgsType[1], field?: CanArgsType[2]) {
return this.ability.can(action, subject, field);
can(...args: Parameters<Ability<A, S, C>['can']>) {
return this.ability.can(...args);
}

ngOnDestroy() {
Expand Down
17 changes: 10 additions & 7 deletions packages/casl-angular/src/module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { NgModule, ModuleWithProviders } from '@angular/core';
import { Ability } from '@casl/ability';
import { Ability, Subject } from '@casl/ability';
import { CanPipe } from './can';

export function createAbility() {
return new Ability([]);
}

@NgModule({
declarations: [
CanPipe
Expand All @@ -15,11 +11,18 @@ export function createAbility() {
],
})
export class AbilityModule {
static forRoot(): ModuleWithProviders<AbilityModule> {
static forRoot<
Actions extends string,
Subjects extends Subject,
Conditions
>(): ModuleWithProviders<AbilityModule> {
return {
ngModule: AbilityModule,
providers: [
{ provide: Ability, useFactory: createAbility },
{
provide: Ability,
useFactory: () => new Ability<Actions, Subjects, Conditions>([])
},
]
};
}
Expand Down

0 comments on commit 68bd287

Please sign in to comment.