babel-plugin-check-data-access v4.0.8
babel-plugin-check-data-access
A babel plugin enabling automatic access-checks and convenient modification of immutable objects.
obj.a.b[2]
→deepAccess.get(obj, ["a", "b", 2])
set(obj.a.b, "value")
→obj = deepAccess.set(obj, ["a","b"], "value")
Transformation 1: Checking object access
obj.a.b
will be transformed into a function call like deepAcc.get(obj, ["a", "b"])
, which will throw an error if the property path obj → a → b is not found, if an array index is out of bounds and so on. deepAcc
is an injected function-suite, the plugin ensures that the import doesn't collide.
More examples in the test-case: proxyMemberAccess_spec.js
Note: This will also throw on statements like if (obj.a.b) {…}
if a.b
isn't defined. You can use if (exists(obj.a.b)) {…}
, which is semantically cleaner than the usage of truthy values.
Transformation 2: Enabling special functions:
- Getters:
get
,exists
,collect
,select
- Setters:
set
,del
,replace
,create
,update
,toggle
,push
,patch
These allow to work on deep structures. Setters copy object if needed, the original object won't be touched. Substructures will be reused as often as possible.
create(x.a.b, 2)
will become x = deepAcc.create(x, ["a", "b"], 2)
. If x.a.b
exists the function will throw an error, otherwise it will be set to 2
.
Note: The immutability approach implies that working on members of this
is not possible since it can't be reassigned (e.g. this = deepAcc.set(this.a, 2)
is not valid syntax).
Note: To avoid confusion, the plugin will throw an error if one of the special functions is already defined in your code.
Functionality of deepAccess
:
This allows functions inside brackets to search through nested structures, enabling statements like this:
/* $ is the variable, I have my redux state in */
/* collect into array */
let soldProducts = collect(
$.consumers[idx => idx === selectedConsumer] /* select idx in consumers array */
.invoices[() => true] /* all invoices of that consumer */
.products[() => true] /* all products inside those invoices */
); /* --> array of products */
/* selects member, throws if not exactly one is found */
let firstSoldProduct = select(
$.consumers[idx => idx === selectedConsumer]
.invoices[0]
.products[0]
);
The other functions are:
get($.consumers) /* throws if 'consumers' is not found in '$' or '$' is not an object */
get($.consumers, []) /* get 'consumers' and return empty array if not found */
exists($.consumers) /* --> true/false */
create($.consumers, []) /* create: throws if member exists */
set($.consumers, []) /* set: replace if member exists */
replace($.consumers, []) /* replace: throws if member does not exist */
del($.consumers[0]) /* deletes first item in $.consumer */
toggle($.selected, idx) /* delete if idx exists in $.selected, set it otherwise */
/* updates name of first consumer by running it through a function */
update($.consumers[0].name, name => name.toUpperCase())
/* pushes newConsumer to $.consumers, throws if it's not array or doesn't exist */
push($.consumers, newConsumer)
/* patch: add/replaces properties
sets name of first consumer to newName
throws if last consumer does not exist or is not an object */
patch($.consumers[0], {
name: newName,
});
Spec: deepAccess_spec.js
Usage / Options
Put this in your .babelrc
:
plugins: [
["check-data-access", {
disableAccessChecks: false,
disableSpecialFunctions: false,
/* or just disable just some special functions */
disableSpecialFunctions: ["create"]
}]
]
Caveats
- Access by providing functions currently only works for
collect
andselect
. Setting, deleting and updating multiple values will be added in the future. patch
doesn't apply recursively.
Changelog
v4.0.8
updated dependenciesv4.0.7
updated .publishrcv4.0.6
moved testing from mocha and chai to tapev4.0.5
updated README and keywordsv4.0.4
updated dependencies and whitelistes files inpackage.json
v4.0.3
performance improvements and don't throw if accessing string properties on arraysv4.0.0
removed access with negative array indices. It's too easy to introduce bugs and it would change behaviour when disable the access-checks for production.v3.0.1
fixed a wrong warning about 'get' being bound.v3.0.0
reverted the previous change. Immutable objects are much more useful than the disadvantage of not being able to use setters onthis
.v2.0.0
special functions don't copy and assign, but work on objects directly.
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago
8 years ago