@casl/angular 7.0.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -121,7 +121,40 @@ export class LoginForm {
121
121
  }
122
122
  ```
123
123
 
124
- ## Check permissions in templates
124
+ ## Check permissions in templates using AbilityService
125
+
126
+ `AbilityService` is a service that provides `ability$` observable. This observable injects provided in DI `PureAbility` instance and emits it each time its rules are changed. This allows efficiently use permissions checks, especially in case we use `ChangeDetectionStrategy.OnPush`.
127
+
128
+ Let's first see how it can be used in any component:
129
+
130
+ ```ts
131
+ @Component({
132
+ selector: 'my-home',
133
+ template: `
134
+ <ng-container *ngIf="ability$ | async as ability">
135
+ <h1>Home Page</h1>
136
+ <button *ngIf="ability.can('create', 'Post')">Create Post</button>
137
+ </ng-container>
138
+ `
139
+ })
140
+ export class HomeComponent {
141
+ readonly ability$: Observable<AppAbility>;
142
+
143
+ constructor(abilityService: AbilityService<AppAbility>) {
144
+ this.ability$ = abilityService.ability$;
145
+ }
146
+ }
147
+ ```
148
+
149
+ It also can be safely used inside `*ngFor` and other directives. If we use `ChangeDetectionStrategy.OnPush`, it will give us additional performance improvements because `ability.can(...)` won't be called without a need.
150
+
151
+ This approach works good from performance point of view because it creates only single subscription per component (not per check as in case of `ablePure` pipe) and doesn't require our component to use `Default` or `OnPush` strategy.
152
+
153
+ **Note**: provide this service at root injector level as we need only 1 instance of it.
154
+
155
+ But let's also see how we can do permission checks using pipes and what are performance implications of that:
156
+
157
+ ## Check permissions in templates using pipe
125
158
 
126
159
  To check permissions in any template you can use `AblePipe`:
127
160
 
@@ -131,9 +164,7 @@ To check permissions in any template you can use `AblePipe`:
131
164
  </div>
132
165
  ```
133
166
 
134
- > You can read the expression in `ngIf` as "if creatable Post"
135
-
136
- ## Why pipe and not directive?
167
+ ### Why pipe and not directive?
137
168
 
138
169
  Directive cannot be used to pass values into inputs of other components. For example, we need to enable or disable a button based on user's ability to create a post. With directive we cannot do this but we can do this with pipe:
139
170
 
@@ -141,7 +172,7 @@ Directive cannot be used to pass values into inputs of other components. For exa
141
172
  <button [disabled]="!('create' | able: 'Post')">Add Post</button>
142
173
  ```
143
174
 
144
- ## Performance considerations
175
+ ### Performance considerations
145
176
 
146
177
  There are 2 pipes in `@casl/angular`:
147
178
 
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Pipe, Inject, NgModule } from '@angular/core';
2
+ import { Pipe, Inject, NgModule, Injectable } from '@angular/core';
3
3
  import { PureAbility } from '@casl/ability';
4
4
  import { Observable } from 'rxjs';
5
5
 
@@ -83,5 +83,23 @@ var AbilityModule = /** @class */ (function () {
83
83
  AblePurePipe], exports: [AblePipe,
84
84
  AblePurePipe] }); })();
85
85
 
86
- export { AbilityModule, AblePipe, AblePurePipe };
86
+ var AbilityService = /** @class */ (function () {
87
+ function AbilityService(ability) {
88
+ this.ability$ = new Observable(function (observer) {
89
+ observer.next(ability);
90
+ return ability.on('updated', function () { return observer.next(ability); });
91
+ });
92
+ }
93
+ AbilityService.ɵfac = function AbilityService_Factory(t) { return new (t || AbilityService)(i0.ɵɵinject(PureAbility)); };
94
+ AbilityService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: AbilityService, factory: AbilityService.ɵfac });
95
+ return AbilityService;
96
+ }());
97
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AbilityService, [{
98
+ type: Injectable
99
+ }], function () { return [{ type: undefined, decorators: [{
100
+ type: Inject,
101
+ args: [PureAbility]
102
+ }] }]; }, null); })();
103
+
104
+ export { AbilityModule, AbilityService, AblePipe, AblePurePipe };
87
105
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/pipes.ts","../../src/AbilityModule.ts"],"sourcesContent":["import { Pipe, Inject, PipeTransform } from '@angular/core';\nimport { PureAbility, Unsubscribe, AnyAbility } from '@casl/ability';\nimport { Observable } from 'rxjs';\n\n@Pipe({ name: 'able', pure: false })\nexport class AblePipe<T extends AnyAbility> implements PipeTransform {\n protected _unsubscribeFromAbility?: Unsubscribe;\n private _ability: T;\n\n constructor(@Inject(PureAbility) ability: T) {\n this._ability = ability;\n }\n\n transform(...args: Parameters<T['can']>): boolean {\n return this._ability.can(...args);\n }\n}\n\n@Pipe({ name: 'ablePure' })\nexport class AblePurePipe<T extends AnyAbility> implements PipeTransform {\n private _ability: T;\n\n constructor(@Inject(PureAbility) ability: T) {\n this._ability = ability;\n }\n\n // TODO: `Observable` can be removed after https://github.com/angular/angular/issues/15041\n transform(...args: Parameters<T['can']>): Observable<boolean> {\n return new Observable((s) => {\n const emit = () => s.next(this._ability.can(...args));\n emit();\n return this._ability.on('updated', emit);\n });\n }\n}\n","import { NgModule } from '@angular/core';\nimport { AblePipe, AblePurePipe } from './pipes';\n\n@NgModule({\n declarations: [\n AblePipe,\n AblePurePipe,\n ],\n exports: [\n AblePipe,\n AblePurePipe,\n ],\n})\nexport class AbilityModule {\n}\n"],"names":[],"mappings":";;;;;;IASE,kBAAiC,OAAU;QACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;KACzB;IAED,4BAAS,GAAT;;QAAU,cAA6B;aAA7B,UAA6B,EAA7B,qBAA6B,EAA7B,IAA6B;YAA7B,yBAA6B;;QACrC,OAAO,CAAA,KAAA,IAAI,CAAC,QAAQ,EAAC,GAAG,WAAI,IAAI,EAAE;KACnC;oEAVU,QAAQ,uBAIC,WAAW;yEAJpB,QAAQ;mBALrB;CAIA,IAYC;uFAXY,QAAQ;cADpB,IAAI;eAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE;;sBAKpB,MAAM;uBAAC,WAAW;;;IAa/B,sBAAiC,OAAU;QACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;KACzB;;IAGD,gCAAS,GAAT;QAAA,iBAMC;QANS,cAA6B;aAA7B,UAA6B,EAA7B,qBAA6B,EAA7B,IAA6B;YAA7B,yBAA6B;;QACrC,OAAO,IAAI,UAAU,CAAC,UAAC,CAAC;YACtB,IAAM,IAAI,GAAG;;gBAAM,OAAA,CAAC,CAAC,IAAI,CAAC,CAAA,KAAA,KAAI,CAAC,QAAQ,EAAC,GAAG,WAAI,IAAI,EAAE;aAAA,CAAC;YACtD,IAAI,EAAE,CAAC;YACP,OAAO,KAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;SAC1C,CAAC,CAAC;KACJ;4EAdU,YAAY,uBAGH,WAAW;iFAHpB,YAAY;uBAnBzB;CAkBA,IAgBC;uFAfY,YAAY;cADxB,IAAI;eAAC,EAAE,IAAI,EAAE,UAAU,EAAE;;sBAIX,MAAM;uBAAC,WAAW;;;;ICnBjC;KAWC;8EADY,aAAa;mEAAb,aAAa;;wBAb1B;CAGA,IAWC;uFADY,aAAa;cAVzB,QAAQ;eAAC;gBACR,YAAY,EAAE;oBACZ,QAAQ;oBACR,YAAY;iBACb;gBACD,OAAO,EAAE;oBACP,QAAQ;oBACR,YAAY;iBACb;aACF;;wFACY,aAAa,mBARtB,QAAQ;QACR,YAAY,aAGZ,QAAQ;QACR,YAAY;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/pipes.ts","../../src/AbilityModule.ts","../../src/AbilityService.ts"],"sourcesContent":["import { Pipe, Inject, PipeTransform } from '@angular/core';\nimport { PureAbility, AnyAbility } from '@casl/ability';\nimport { Observable } from 'rxjs';\n\n@Pipe({ name: 'able', pure: false })\nexport class AblePipe<T extends AnyAbility> implements PipeTransform {\n private _ability: T;\n\n constructor(@Inject(PureAbility) ability: T) {\n this._ability = ability;\n }\n\n transform(...args: Parameters<T['can']>): boolean {\n return this._ability.can(...args);\n }\n}\n\n@Pipe({ name: 'ablePure' })\nexport class AblePurePipe<T extends AnyAbility> implements PipeTransform {\n private _ability: T;\n\n constructor(@Inject(PureAbility) ability: T) {\n this._ability = ability;\n }\n\n // TODO: `Observable` can be removed after https://github.com/angular/angular/issues/15041\n transform(...args: Parameters<T['can']>): Observable<boolean> {\n return new Observable((s) => {\n const emit = () => s.next(this._ability.can(...args));\n emit();\n return this._ability.on('updated', emit);\n });\n }\n}\n","import { NgModule } from '@angular/core';\nimport { AblePipe, AblePurePipe } from './pipes';\n\n@NgModule({\n declarations: [\n AblePipe,\n AblePurePipe,\n ],\n exports: [\n AblePipe,\n AblePurePipe,\n ],\n})\nexport class AbilityModule {\n}\n","import { Inject, Injectable } from '@angular/core';\nimport { PureAbility, AnyAbility } from '@casl/ability';\nimport { Observable } from 'rxjs';\n\n@Injectable()\nexport class AbilityService<T extends AnyAbility> {\n readonly ability$: Observable<T>;\n\n constructor(@Inject(PureAbility) ability: T) {\n this.ability$ = new Observable((observer) => {\n observer.next(ability);\n return ability.on('updated', () => observer.next(ability));\n });\n }\n}\n"],"names":[],"mappings":";;;;;;IAQE,kBAAiC,OAAU;QACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;KACzB;IAED,4BAAS,GAAT;;QAAU,cAA6B;aAA7B,UAA6B,EAA7B,qBAA6B,EAA7B,IAA6B;YAA7B,yBAA6B;;QACrC,OAAO,CAAA,KAAA,IAAI,CAAC,QAAQ,EAAC,GAAG,WAAI,IAAI,EAAE;KACnC;oEATU,QAAQ,uBAGC,WAAW;yEAHpB,QAAQ;mBALrB;CAIA,IAWC;uFAVY,QAAQ;cADpB,IAAI;eAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE;;sBAIpB,MAAM;uBAAC,WAAW;;;IAa/B,sBAAiC,OAAU;QACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;KACzB;;IAGD,gCAAS,GAAT;QAAA,iBAMC;QANS,cAA6B;aAA7B,UAA6B,EAA7B,qBAA6B,EAA7B,IAA6B;YAA7B,yBAA6B;;QACrC,OAAO,IAAI,UAAU,CAAC,UAAC,CAAC;YACtB,IAAM,IAAI,GAAG;;gBAAM,OAAA,CAAC,CAAC,IAAI,CAAC,CAAA,KAAA,KAAI,CAAC,QAAQ,EAAC,GAAG,WAAI,IAAI,EAAE;aAAA,CAAC;YACtD,IAAI,EAAE,CAAC;YACP,OAAO,KAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;SAC1C,CAAC,CAAC;KACJ;4EAdU,YAAY,uBAGH,WAAW;iFAHpB,YAAY;uBAlBzB;CAiBA,IAgBC;uFAfY,YAAY;cADxB,IAAI;eAAC,EAAE,IAAI,EAAE,UAAU,EAAE;;sBAIX,MAAM;uBAAC,WAAW;;;;IClBjC;KAWC;8EADY,aAAa;mEAAb,aAAa;;wBAb1B;CAGA,IAWC;uFADY,aAAa;cAVzB,QAAQ;eAAC;gBACR,YAAY,EAAE;oBACZ,QAAQ;oBACR,YAAY;iBACb;gBACD,OAAO,EAAE;oBACP,QAAQ;oBACR,YAAY;iBACb;aACF;;wFACY,aAAa,mBARtB,QAAQ;QACR,YAAY,aAGZ,QAAQ;QACR,YAAY;;;ICFd,wBAAiC,OAAU;QACzC,IAAI,CAAC,QAAQ,GAAG,IAAI,UAAU,CAAC,UAAC,QAAQ;YACtC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,OAAO,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,cAAM,OAAA,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAA,CAAC,CAAC;SAC5D,CAAC,CAAC;KACJ;gFARU,cAAc,cAGL,WAAW;wEAHpB,cAAc,WAAd,cAAc;yBAL3B;CAIA,IAUC;uFATY,cAAc;cAD1B,UAAU;;sBAII,MAAM;uBAAC,WAAW;;;;;"}
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Pipe, Inject, NgModule } from '@angular/core';
2
+ import { Pipe, Inject, NgModule, Injectable } from '@angular/core';
3
3
  import { PureAbility } from '@casl/ability';
4
4
  import { Observable } from 'rxjs';
5
5
 
@@ -65,5 +65,22 @@ AbilityModule.ɵinj = /*@__PURE__*/ i0.ɵɵdefineInjector({});
65
65
  AblePurePipe], exports: [AblePipe,
66
66
  AblePurePipe] }); })();
67
67
 
68
- export { AbilityModule, AblePipe, AblePurePipe };
68
+ class AbilityService {
69
+ constructor(ability) {
70
+ this.ability$ = new Observable((observer) => {
71
+ observer.next(ability);
72
+ return ability.on('updated', () => observer.next(ability));
73
+ });
74
+ }
75
+ }
76
+ AbilityService.ɵfac = function AbilityService_Factory(t) { return new (t || AbilityService)(i0.ɵɵinject(PureAbility)); };
77
+ AbilityService.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: AbilityService, factory: AbilityService.ɵfac });
78
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(AbilityService, [{
79
+ type: Injectable
80
+ }], function () { return [{ type: undefined, decorators: [{
81
+ type: Inject,
82
+ args: [PureAbility]
83
+ }] }]; }, null); })();
84
+
85
+ export { AbilityModule, AbilityService, AblePipe, AblePurePipe };
69
86
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../src/pipes.ts","../../src/AbilityModule.ts"],"sourcesContent":["import { Pipe, Inject, PipeTransform } from '@angular/core';\nimport { PureAbility, Unsubscribe, AnyAbility } from '@casl/ability';\nimport { Observable } from 'rxjs';\n\n@Pipe({ name: 'able', pure: false })\nexport class AblePipe<T extends AnyAbility> implements PipeTransform {\n protected _unsubscribeFromAbility?: Unsubscribe;\n private _ability: T;\n\n constructor(@Inject(PureAbility) ability: T) {\n this._ability = ability;\n }\n\n transform(...args: Parameters<T['can']>): boolean {\n return this._ability.can(...args);\n }\n}\n\n@Pipe({ name: 'ablePure' })\nexport class AblePurePipe<T extends AnyAbility> implements PipeTransform {\n private _ability: T;\n\n constructor(@Inject(PureAbility) ability: T) {\n this._ability = ability;\n }\n\n // TODO: `Observable` can be removed after https://github.com/angular/angular/issues/15041\n transform(...args: Parameters<T['can']>): Observable<boolean> {\n return new Observable((s) => {\n const emit = () => s.next(this._ability.can(...args));\n emit();\n return this._ability.on('updated', emit);\n });\n }\n}\n","import { NgModule } from '@angular/core';\nimport { AblePipe, AblePurePipe } from './pipes';\n\n@NgModule({\n declarations: [\n AblePipe,\n AblePurePipe,\n ],\n exports: [\n AblePipe,\n AblePurePipe,\n ],\n})\nexport class AbilityModule {\n}\n"],"names":[],"mappings":";;;;;MAKa,QAAQ;IAInB,YAAiC,OAAU;QACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;KACzB;IAED,SAAS,CAAC,GAAG,IAA0B;QACrC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;KACnC;;gEAVU,QAAQ,uBAIC,WAAW;qEAJpB,QAAQ;uFAAR,QAAQ;cADpB,IAAI;eAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE;;sBAKpB,MAAM;uBAAC,WAAW;;MAUpB,YAAY;IAGvB,YAAiC,OAAU;QACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;KACzB;;IAGD,SAAS,CAAC,GAAG,IAA0B;QACrC,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC;YACtB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;YACtD,IAAI,EAAE,CAAC;YACP,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;SAC1C,CAAC,CAAC;KACJ;;wEAdU,YAAY,uBAGH,WAAW;6EAHpB,YAAY;uFAAZ,YAAY;cADxB,IAAI;eAAC,EAAE,IAAI,EAAE,UAAU,EAAE;;sBAIX,MAAM;uBAAC,WAAW;;;MCTpB,aAAa;;0EAAb,aAAa;+DAAb,aAAa;;uFAAb,aAAa;cAVzB,QAAQ;eAAC;gBACR,YAAY,EAAE;oBACZ,QAAQ;oBACR,YAAY;iBACb;gBACD,OAAO,EAAE;oBACP,QAAQ;oBACR,YAAY;iBACb;aACF;;wFACY,aAAa,mBARtB,QAAQ;QACR,YAAY,aAGZ,QAAQ;QACR,YAAY;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":["../../src/pipes.ts","../../src/AbilityModule.ts","../../src/AbilityService.ts"],"sourcesContent":["import { Pipe, Inject, PipeTransform } from '@angular/core';\nimport { PureAbility, AnyAbility } from '@casl/ability';\nimport { Observable } from 'rxjs';\n\n@Pipe({ name: 'able', pure: false })\nexport class AblePipe<T extends AnyAbility> implements PipeTransform {\n private _ability: T;\n\n constructor(@Inject(PureAbility) ability: T) {\n this._ability = ability;\n }\n\n transform(...args: Parameters<T['can']>): boolean {\n return this._ability.can(...args);\n }\n}\n\n@Pipe({ name: 'ablePure' })\nexport class AblePurePipe<T extends AnyAbility> implements PipeTransform {\n private _ability: T;\n\n constructor(@Inject(PureAbility) ability: T) {\n this._ability = ability;\n }\n\n // TODO: `Observable` can be removed after https://github.com/angular/angular/issues/15041\n transform(...args: Parameters<T['can']>): Observable<boolean> {\n return new Observable((s) => {\n const emit = () => s.next(this._ability.can(...args));\n emit();\n return this._ability.on('updated', emit);\n });\n }\n}\n","import { NgModule } from '@angular/core';\nimport { AblePipe, AblePurePipe } from './pipes';\n\n@NgModule({\n declarations: [\n AblePipe,\n AblePurePipe,\n ],\n exports: [\n AblePipe,\n AblePurePipe,\n ],\n})\nexport class AbilityModule {\n}\n","import { Inject, Injectable } from '@angular/core';\nimport { PureAbility, AnyAbility } from '@casl/ability';\nimport { Observable } from 'rxjs';\n\n@Injectable()\nexport class AbilityService<T extends AnyAbility> {\n readonly ability$: Observable<T>;\n\n constructor(@Inject(PureAbility) ability: T) {\n this.ability$ = new Observable((observer) => {\n observer.next(ability);\n return ability.on('updated', () => observer.next(ability));\n });\n }\n}\n"],"names":[],"mappings":";;;;;MAKa,QAAQ;IAGnB,YAAiC,OAAU;QACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;KACzB;IAED,SAAS,CAAC,GAAG,IAA0B;QACrC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;KACnC;;gEATU,QAAQ,uBAGC,WAAW;qEAHpB,QAAQ;uFAAR,QAAQ;cADpB,IAAI;eAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE;;sBAIpB,MAAM;uBAAC,WAAW;;MAUpB,YAAY;IAGvB,YAAiC,OAAU;QACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;KACzB;;IAGD,SAAS,CAAC,GAAG,IAA0B;QACrC,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC;YACtB,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;YACtD,IAAI,EAAE,CAAC;YACP,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;SAC1C,CAAC,CAAC;KACJ;;wEAdU,YAAY,uBAGH,WAAW;6EAHpB,YAAY;uFAAZ,YAAY;cADxB,IAAI;eAAC,EAAE,IAAI,EAAE,UAAU,EAAE;;sBAIX,MAAM;uBAAC,WAAW;;;MCRpB,aAAa;;0EAAb,aAAa;+DAAb,aAAa;;uFAAb,aAAa;cAVzB,QAAQ;eAAC;gBACR,YAAY,EAAE;oBACZ,QAAQ;oBACR,YAAY;iBACb;gBACD,OAAO,EAAE;oBACP,QAAQ;oBACR,YAAY;iBACb;aACF;;wFACY,aAAa,mBARtB,QAAQ;QACR,YAAY,aAGZ,QAAQ;QACR,YAAY;;MCLH,cAAc;IAGzB,YAAiC,OAAU;QACzC,IAAI,CAAC,QAAQ,GAAG,IAAI,UAAU,CAAC,CAAC,QAAQ;YACtC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,OAAO,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;SAC5D,CAAC,CAAC;KACJ;;4EARU,cAAc,cAGL,WAAW;oEAHpB,cAAc,WAAd,cAAc;uFAAd,cAAc;cAD1B,UAAU;;sBAII,MAAM;uBAAC,WAAW;;;;;"}
@@ -0,0 +1,9 @@
1
+ import { AnyAbility } from '@casl/ability';
2
+ import { Observable } from 'rxjs';
3
+ import * as i0 from "@angular/core";
4
+ export declare class AbilityService<T extends AnyAbility> {
5
+ readonly ability$: Observable<T>;
6
+ constructor(ability: T);
7
+ static ɵfac: i0.ɵɵFactoryDeclaration<AbilityService<any>, never>;
8
+ static ɵprov: i0.ɵɵInjectableDeclaration<AbilityService<any>>;
9
+ }
@@ -1,9 +1,8 @@
1
1
  import { PipeTransform } from '@angular/core';
2
- import { Unsubscribe, AnyAbility } from '@casl/ability';
2
+ import { AnyAbility } from '@casl/ability';
3
3
  import { Observable } from 'rxjs';
4
4
  import * as i0 from "@angular/core";
5
5
  export declare class AblePipe<T extends AnyAbility> implements PipeTransform {
6
- protected _unsubscribeFromAbility?: Unsubscribe;
7
6
  private _ability;
8
7
  constructor(ability: T);
9
8
  transform(...args: Parameters<T['can']>): boolean;
@@ -1,2 +1,3 @@
1
1
  export * from './pipes';
2
2
  export * from './AbilityModule';
3
+ export * from './AbilityService';
package/dist/umd/index.js CHANGED
@@ -106,7 +106,26 @@
106
106
  AblePurePipe], exports: [AblePipe,
107
107
  AblePurePipe] }); })();
108
108
 
109
+ var AbilityService = /** @class */ (function () {
110
+ function AbilityService(ability) {
111
+ this.ability$ = new rxjs.Observable(function (observer) {
112
+ observer.next(ability);
113
+ return ability.on('updated', function () { return observer.next(ability); });
114
+ });
115
+ }
116
+ AbilityService.ɵfac = function AbilityService_Factory(t) { return new (t || AbilityService)(i0__namespace.ɵɵinject(ability.PureAbility)); };
117
+ AbilityService.ɵprov = /*@__PURE__*/ i0__namespace.ɵɵdefineInjectable({ token: AbilityService, factory: AbilityService.ɵfac });
118
+ return AbilityService;
119
+ }());
120
+ (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0__namespace.ɵsetClassMetadata(AbilityService, [{
121
+ type: i0.Injectable
122
+ }], function () { return [{ type: undefined, decorators: [{
123
+ type: i0.Inject,
124
+ args: [ability.PureAbility]
125
+ }] }]; }, null); })();
126
+
109
127
  exports.AbilityModule = AbilityModule;
128
+ exports.AbilityService = AbilityService;
110
129
  exports.AblePipe = AblePipe;
111
130
  exports.AblePurePipe = AblePurePipe;
112
131
 
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/pipes.ts","../../src/AbilityModule.ts"],"sourcesContent":["import { Pipe, Inject, PipeTransform } from '@angular/core';\nimport { PureAbility, Unsubscribe, AnyAbility } from '@casl/ability';\nimport { Observable } from 'rxjs';\n\n@Pipe({ name: 'able', pure: false })\nexport class AblePipe<T extends AnyAbility> implements PipeTransform {\n protected _unsubscribeFromAbility?: Unsubscribe;\n private _ability: T;\n\n constructor(@Inject(PureAbility) ability: T) {\n this._ability = ability;\n }\n\n transform(...args: Parameters<T['can']>): boolean {\n return this._ability.can(...args);\n }\n}\n\n@Pipe({ name: 'ablePure' })\nexport class AblePurePipe<T extends AnyAbility> implements PipeTransform {\n private _ability: T;\n\n constructor(@Inject(PureAbility) ability: T) {\n this._ability = ability;\n }\n\n // TODO: `Observable` can be removed after https://github.com/angular/angular/issues/15041\n transform(...args: Parameters<T['can']>): Observable<boolean> {\n return new Observable((s) => {\n const emit = () => s.next(this._ability.can(...args));\n emit();\n return this._ability.on('updated', emit);\n });\n }\n}\n","import { NgModule } from '@angular/core';\nimport { AblePipe, AblePurePipe } from './pipes';\n\n@NgModule({\n declarations: [\n AblePipe,\n AblePurePipe,\n ],\n exports: [\n AblePipe,\n AblePurePipe,\n ],\n})\nexport class AbilityModule {\n}\n"],"names":["PureAbility","Pipe","Inject","Observable","NgModule"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;QASE,kBAAiC,OAAU;YACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;SACzB;QAED,4BAAS,GAAT;;YAAU,cAA6B;iBAA7B,UAA6B,EAA7B,qBAA6B,EAA7B,IAA6B;gBAA7B,yBAA6B;;YACrC,OAAO,CAAA,KAAA,IAAI,CAAC,QAAQ,EAAC,GAAG,WAAI,IAAI,EAAE;SACnC;wEAVU,QAAQ,kCAICA,mBAAW;wFAJpB,QAAQ;uBALrB;KAIA,IAYC;sGAXY,QAAQ;kBADpBC,OAAI;mBAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE;;0BAKpBC,SAAM;2BAACF,mBAAW;;;QAa/B,sBAAiC,OAAU;YACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;SACzB;;QAGD,gCAAS,GAAT;YAAA,iBAMC;YANS,cAA6B;iBAA7B,UAA6B,EAA7B,qBAA6B,EAA7B,IAA6B;gBAA7B,yBAA6B;;YACrC,OAAO,IAAIG,eAAU,CAAC,UAAC,CAAC;gBACtB,IAAM,IAAI,GAAG;;oBAAM,OAAA,CAAC,CAAC,IAAI,CAAC,CAAA,KAAA,KAAI,CAAC,QAAQ,EAAC,GAAG,WAAI,IAAI,EAAE;iBAAA,CAAC;gBACtD,IAAI,EAAE,CAAC;gBACP,OAAO,KAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;aAC1C,CAAC,CAAC;SACJ;gFAdU,YAAY,kCAGHH,mBAAW;gGAHpB,YAAY;2BAnBzB;KAkBA,IAgBC;sGAfY,YAAY;kBADxBC,OAAI;mBAAC,EAAE,IAAI,EAAE,UAAU,EAAE;;0BAIXC,SAAM;2BAACF,mBAAW;;;;QCnBjC;SAWC;kFADY,aAAa;kFAAb,aAAa;;4BAb1B;KAGA,IAWC;sGADY,aAAa;kBAVzBI,WAAQ;mBAAC;oBACR,YAAY,EAAE;wBACZ,QAAQ;wBACR,YAAY;qBACb;oBACD,OAAO,EAAE;wBACP,QAAQ;wBACR,YAAY;qBACb;iBACF;;uGACY,aAAa,mBARtB,QAAQ;YACR,YAAY,aAGZ,QAAQ;YACR,YAAY;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/pipes.ts","../../src/AbilityModule.ts","../../src/AbilityService.ts"],"sourcesContent":["import { Pipe, Inject, PipeTransform } from '@angular/core';\nimport { PureAbility, AnyAbility } from '@casl/ability';\nimport { Observable } from 'rxjs';\n\n@Pipe({ name: 'able', pure: false })\nexport class AblePipe<T extends AnyAbility> implements PipeTransform {\n private _ability: T;\n\n constructor(@Inject(PureAbility) ability: T) {\n this._ability = ability;\n }\n\n transform(...args: Parameters<T['can']>): boolean {\n return this._ability.can(...args);\n }\n}\n\n@Pipe({ name: 'ablePure' })\nexport class AblePurePipe<T extends AnyAbility> implements PipeTransform {\n private _ability: T;\n\n constructor(@Inject(PureAbility) ability: T) {\n this._ability = ability;\n }\n\n // TODO: `Observable` can be removed after https://github.com/angular/angular/issues/15041\n transform(...args: Parameters<T['can']>): Observable<boolean> {\n return new Observable((s) => {\n const emit = () => s.next(this._ability.can(...args));\n emit();\n return this._ability.on('updated', emit);\n });\n }\n}\n","import { NgModule } from '@angular/core';\nimport { AblePipe, AblePurePipe } from './pipes';\n\n@NgModule({\n declarations: [\n AblePipe,\n AblePurePipe,\n ],\n exports: [\n AblePipe,\n AblePurePipe,\n ],\n})\nexport class AbilityModule {\n}\n","import { Inject, Injectable } from '@angular/core';\nimport { PureAbility, AnyAbility } from '@casl/ability';\nimport { Observable } from 'rxjs';\n\n@Injectable()\nexport class AbilityService<T extends AnyAbility> {\n readonly ability$: Observable<T>;\n\n constructor(@Inject(PureAbility) ability: T) {\n this.ability$ = new Observable((observer) => {\n observer.next(ability);\n return ability.on('updated', () => observer.next(ability));\n });\n }\n}\n"],"names":["PureAbility","Pipe","Inject","Observable","NgModule","Injectable"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAQE,kBAAiC,OAAU;YACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;SACzB;QAED,4BAAS,GAAT;;YAAU,cAA6B;iBAA7B,UAA6B,EAA7B,qBAA6B,EAA7B,IAA6B;gBAA7B,yBAA6B;;YACrC,OAAO,CAAA,KAAA,IAAI,CAAC,QAAQ,EAAC,GAAG,WAAI,IAAI,EAAE;SACnC;wEATU,QAAQ,kCAGCA,mBAAW;wFAHpB,QAAQ;uBALrB;KAIA,IAWC;sGAVY,QAAQ;kBADpBC,OAAI;mBAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE;;0BAIpBC,SAAM;2BAACF,mBAAW;;;QAa/B,sBAAiC,OAAU;YACzC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;SACzB;;QAGD,gCAAS,GAAT;YAAA,iBAMC;YANS,cAA6B;iBAA7B,UAA6B,EAA7B,qBAA6B,EAA7B,IAA6B;gBAA7B,yBAA6B;;YACrC,OAAO,IAAIG,eAAU,CAAC,UAAC,CAAC;gBACtB,IAAM,IAAI,GAAG;;oBAAM,OAAA,CAAC,CAAC,IAAI,CAAC,CAAA,KAAA,KAAI,CAAC,QAAQ,EAAC,GAAG,WAAI,IAAI,EAAE;iBAAA,CAAC;gBACtD,IAAI,EAAE,CAAC;gBACP,OAAO,KAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;aAC1C,CAAC,CAAC;SACJ;gFAdU,YAAY,kCAGHH,mBAAW;gGAHpB,YAAY;2BAlBzB;KAiBA,IAgBC;sGAfY,YAAY;kBADxBC,OAAI;mBAAC,EAAE,IAAI,EAAE,UAAU,EAAE;;0BAIXC,SAAM;2BAACF,mBAAW;;;;QClBjC;SAWC;kFADY,aAAa;kFAAb,aAAa;;4BAb1B;KAGA,IAWC;sGADY,aAAa;kBAVzBI,WAAQ;mBAAC;oBACR,YAAY,EAAE;wBACZ,QAAQ;wBACR,YAAY;qBACb;oBACD,OAAO,EAAE;wBACP,QAAQ;wBACR,YAAY;qBACb;iBACF;;uGACY,aAAa,mBARtB,QAAQ;YACR,YAAY,aAGZ,QAAQ;YACR,YAAY;;;QCFd,wBAAiC,OAAU;YACzC,IAAI,CAAC,QAAQ,GAAG,IAAID,eAAU,CAAC,UAAC,QAAQ;gBACtC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACvB,OAAO,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,cAAM,OAAA,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAA,CAAC,CAAC;aAC5D,CAAC,CAAC;SACJ;oFARU,cAAc,yBAGLH,mBAAW;uFAHpB,cAAc,WAAd,cAAc;6BAL3B;KAIA,IAUC;sGATY,cAAc;kBAD1BK,aAAU;;0BAIIH,SAAM;2BAACF,mBAAW;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@casl/angular",
3
- "version": "7.0.0",
3
+ "version": "8.0.0",
4
4
  "description": "Angular module for CASL which makes it easy to add permissions in any Angular app",
5
5
  "main": "dist/umd/index.js",
6
6
  "module": "dist/es5m/index.js",
@@ -46,28 +46,28 @@
46
46
  "author": "Sergii Stotskyi <sergiy.stotskiy@gmail.com>",
47
47
  "license": "MIT",
48
48
  "peerDependencies": {
49
- "@angular/core": "^13.0.0",
50
- "@casl/ability": "^3.0.0 || ^4.0.0 || ^5.1.0",
49
+ "@angular/core": "^14.0.0",
50
+ "@casl/ability": "^3.0.0 || ^4.0.0 || ^5.1.0 || ^6.0.0",
51
51
  "rxjs": "^7.5.5",
52
52
  "tslib": "^2.0.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@abraham/reflection": "^0.8.0",
56
- "@angular/common": "^13.0.0",
57
- "@angular/compiler": "^13.0.0",
58
- "@angular/compiler-cli": "^13.0.0",
59
- "@angular/core": "^13.0.0",
60
- "@angular/platform-browser": "^13.0.0",
61
- "@angular/platform-browser-dynamic": "^13.0.0",
62
- "@angular-devkit/build-angular": "^13.0.0",
63
- "jest": "^27.0.0",
64
- "@casl/ability": "^5.1.0",
55
+ "@abraham/reflection": "^0.10.0",
56
+ "@angular/common": "^14.0.0",
57
+ "@angular/compiler": "^14.0.0",
58
+ "@angular/compiler-cli": "^14.0.0",
59
+ "@angular/core": "^14.0.0",
60
+ "@angular/platform-browser": "^14.0.0",
61
+ "@angular/platform-browser-dynamic": "^14.0.0",
62
+ "@angular-devkit/build-angular": "^14.0.0",
63
+ "jest": "^28.0.0",
64
+ "@casl/ability": "^6.0.0",
65
65
  "@casl/dx": "workspace:^1.0.0",
66
- "@types/jest": "^27.4.7",
67
- "jest-preset-angular": "^11.0.0",
66
+ "@types/jest": "^28.0.0",
67
+ "jest-preset-angular": "^12.0.0",
68
68
  "rxjs": "^7.5.5",
69
69
  "tslib": "^2.0.0",
70
- "typescript": "~4.4.4",
70
+ "typescript": "~4.7.4",
71
71
  "zone.js": "~0.11.4"
72
72
  },
73
73
  "files": [