Changelog History
Page 1
-
v5.1.0-next.9 Changes
September 28, 20205.1.0-next.9 (2020-09-28)
๐ Performance Improvements
-
v5.1.0-next.8 Changes
September 26, 20205.1.0-next.8 (2020-09-26)
๐ Performance Improvements
- rule: ensures conditions/field matcher created only when we have object/field to check (110a69d)
-
v5.1.0-next.7 Changes
September 25, 20205.1.0-next.7 (2020-09-25)
๐ Performance Improvements
- events: moves out side-effect from
LinkedItem
constructor (3657c7f)
- events: moves out side-effect from
-
v5.1.0-next.6 Changes
September 25, 20205.1.0-next.6 (2020-09-25)
๐ Performance Improvements
- events: handles event removal in space efficient way (71246e2)
-
v5.1.0-next.5 Changes
September 23, 20205.1.0-next.5 (2020-09-23)
๐ Bug Fixes
-
v5.1.0-next.4 Changes
August 28, 20205.1.0-next.4 (2020-08-28)
๐ Performance Improvements
- ability: replaces object for storing index with ES6 Map (d1fa117)
-
v5.1.0-next.3 Changes
August 28, 20205.1.0-next.3 (2020-08-28)
๐ Performance Improvements
- ability: creates conditions and field matcher lazily (4ae7799)
-
v5.1.0-next.2 Changes
August 27, 20205.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
defineAbility
to 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
AbilityBuilder
is now madatory. This allows to infer generic parameters from it and makes AbilityType that is built to be explicit.๐ builder:
can
andcannot
methods ofAbilityBuilder
now 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: stringlastName: stringage: numberaddress: {street: stringcity: 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 fieldsage: { $gt: 18 }})
After
โ๏ธ Because provided keys in the example above doesn't exist on
Person
interface, 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: stringlastName: stringage: numberaddress: {street: stringcity: 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 }})
-
v5.1.0-next.12 Changes
November 18, 20205.1.0-next.12 (2020-11-18)
๐ Bug Fixes
- ability: replaces getters with functions to ensure terser properly minifies them (386ecb6)
- extra: makes
permittedFieldsOf
to iterate from the end of array (81e6409)
๐จ Code Refactoring
- extra: makes
fieldsFrom
option to be mandatory forpermittedFieldsOf
[skip release] (df29b0d) - types: restricts which utility types are exported by library (e98618f)
โช Reverts
- ๐ builder: reverts back
AbilityBuilder
generic parameter (aa7b45f)
๐ฅ BREAKING CHANGES
types: types
AliasesMap
,TaggedInterface
,AbilityTupleType
,ToAbilityTypes
,AnyObject
are no longer exported by the libraryextra: makes
fieldsFrom
option to be mandatory forpermittedFieldsO f
. This reduces confusion around whypermittedFieldsOf
returns empty array when user can manage entity fields. So, now this logic is just explicit and clearBefore
import { defineAbility } from '@casl/ability';import { permittedFieldsOf } from '@casl/ability/extra';const ability = defineAbility((can) =\> {can('read', 'Article');});const fields = permittedFieldsOf(ability, 'read', 'Article'); // []
After
import { defineAbility } from '@casl/ability';import { permittedFieldsOf } from '@casl/ability/extra';const ability = defineAbility((can) =\> {can('read', 'Article');});const ARTICLE\_FIELDS = ['id', 'title', 'description'];const fields = permittedFieldsOf(ability, 'read', 'Article', {fieldsFrom: rule =\> rule.fields || ARTICLE\_FIELDS}); // ['id', 'title', 'description']
-
v5.1.0-next.11 Changes
October 17, 20205.1.0-next.11 (2020-10-17)
๐ Bug Fixes
- README: removes explanation duplicated from intro guide (6315aa7)
๐จ Code Refactoring
- ruleIndex:
detectSubjectType
option is now responsible only for detecting subject type from objects [skip release] (ebeaadc)
๐ฅ BREAKING CHANGES
ruleIndex: string and class (or function constructor) are the only possible subject types for now.
detectSubjectType
is now responsible only for detecting subject type from objectBefore
When providing subject type it was important to handle cases when passed in argument is a string or function. As an alternative it was possible to call built-in
detectSubjectType
which could catch this cases:import { Ability } from '@casl/ability';const ability = new Ability([], {detectSubjectType(object) {if (object && typeof object === 'object') {return object.\_\_typename;}return detectSubjectType(object);});
After
There is no need to handle subject type values in
detectSubjectType
function anymore. It's now handled internally:import { Ability } from '@casl/ability';const ability = new Ability([], {detectSubjectType: object =\> object.\_\_typename});
Also it's important to note that if you want it's no longer possible to use classes and strings as subject types interchangably together as it was before. Now, if you want to use classes, you should use them everywhere:
Before
import { defineAbility } from '@casl/ability';class Post {}const ability = defineAbility((can) =\> {can('read', Post);can('update', 'Post');});ability.can('read', 'Post') // trueability.can('read', Post) // trueability.can('update', Post) // true
After
import { defineAbility } from '@casl/ability';class Post {}const ability = defineAbility((can) =\> {can('read', Post);can('update', 'Post');});ability.can('read', 'Post') // false, 'Post' and Post are considered different nowability.can('read', Post) // trueability.can('update', Post) // false