@casl/ability@5.1.0-next.2
Pre-release5.1.0-next.2 (2020-08-27)
Features
- builder: improves typings for AbilityBuilder [skip release] (ebd4d17), closes #379
- builder: improves typings of
AbilityBuilder['can']andAbilityBuilder['cannot']methods [skip release] (98ffbfc), closes #333
Performance Improvements
- events: utilizes LinkedList for storing event handlers (e2fd265)
- rules: improves merging logic of rules of subject and
manage all(6f8a13a)
BREAKING CHANGES
-
builder: changes main generic parameter to be a class instead of instance and makes
defineAbilityto accept options as the 2nd argument.Before
import { AbilityBuilder, defineAbility, Ability } from '@casl/ability'; const resolveAction = (action: string) => {/* custom implementation */ }; const ability = defineAbility({ resolveAction }, (can) => can('read', 'Item')); const builder = new AbilityBuilder<Ability>(Ability);
After
import { AbilityBuilder, defineAbility, Ability } from '@casl/ability'; const resolveAction = (action: string) => {/* custom implementation */ }; const ability = defineAbility((can) => can('read', 'Item'), { resolveAction }); const builder = new AbilityBuilder(Ability); // first argument is now mandatory!
The 1st parameter to
AbilityBuilderis now madatory. This allows to infer generic parameters from it and makes AbilityType that is built to be explicit. -
builder:
canandcannotmethods ofAbilityBuildernow restricts what fields and operators can be used inside conditions (i.e.,MongoQuery). Also these methods now suggests object fields based on passed instanceBefore
import { AbilityBuilder, Ability, AbilityClass } from '@casl/ability'; interface Person { kind: 'Person' firstName: string lastName: string age: number address: { street: string city: string } } type AppAbility = Ability<['read', Person | Person['kind']]>; cons AppAbility = Ability as AbilityClass<AppAbility>; cons { can } = new AbilityBuilder(AppAbility); can('read', 'Person', { 'address.street': 'Somewhere in the world', fistName: 'John' // unintentional typo }); can('read', 'Person', ['fistName', 'lastName'], { // no intellisense for fields age: { $gt: 18 } })
After
Because provided keys in the example above doesn't exist on
Personinterface, TypeScript throws an error. So, we are safe from typos! But what about dot notation? It's also supported but in more typesafe way:import { AbilityBuilder, Ability, AbilityClass } from '@casl/ability'; interface Person { kind: 'Person' firstName: string lastName: string age: number address: { street: string city: string } } type AppAbility = Ability<['read', Person | Person['kind']]>; cons AppAbility = Ability as AbilityClass<AppAbility>; cons { can } = new AbilityBuilder(AppAbility); interface PersonQuery extends Person { 'address.street': Person['address']['street'] 'address.city': Person['address']['city'] } can<PersonQuery>('read', 'Person', { 'address.street': 'Somewhere in the world', fistName: 'John' // unintentional typo }); can<PersonQuery>('read', 'Person', ['firstName', 'lastName'], { age: { $gt: 18 } })
Intellisense and type checking for fields is also implemented! To be able to use wildcards in fields just add additional generic parameter:
can<PersonQuery, 'address.*'>('read', 'Person', ['firstName', 'address.*'], { age: { $gt: 18 } })