proxy-pants
v0.9.0
Published
Secured and reliable Proxy based utilities for more or less common tasks
Downloads
99
Maintainers
Readme
proxy-pants
Social Media Photo by lan deng on Unsplash
Secured and reliable Proxy based utilities for more or less common tasks:
- accessor to trap one or more accessors for any object
- applier & caller to trap any borrowed callback/utility without needing to use
.call
or.apply
to pass the context - bound to bind one or more methods all at once
- bread & crumbs to track operations through paths (i.e.
a.b.c.d
) and namespaces - cache to compute once any accessed property through a proxied, and secured, map
- chain to trap once all inherited descriptors down the prototypal chain and automatically ensure the right accessor or method
- dsm to virtually trap
dataset
/*set
accessors as DOMStringMap like references per each element. Please note this utility is not secured - extender to extend any object through weakly referenced behaviors, providing a new way to deal with state machines too, through the following features:
- methods are always the same bound reference
- properties are defined per extender and never directly attached to the source
- accessors are also defined per each extender
- multiple extenders calls to the same source preserve previous state, and any source can pass through multiple extenders without ever conflicting
- fetch to shortcut
fetch(url).json
and other methods as direct accessors, defaulting tovoid
when the response is not ok - own to destructure only own properties
- secure to ensure local classes cannot be patched at runtime down their prototypal chain
- watcher the good old Object.prototype.watch and unwatch methods to simplify selective reactive state handling
- weak-cache same as cache but the returned reference is weakly retained
- weak-proxy same as Proxy but it's register to the finalization registry so that if the
handler
contains acollected(target)
callback, that will be invoked once the proxy reference is gone
accessor
Trap one or more accessors for any object.
// import {accessor} from 'proxy-pants/accessor';
import {accessor} from 'proxy-pants';
const {textContent} = accessor(document.body);
// get the current body text
textContent();
// set the new one
textContent('proxy pants!');
applier & caller
Trap any borrowed callback/utility without needing to use .call
or .apply
to pass the context.
// import {applier, caller} from 'proxy-pants/function';
import {applier, caller} from 'proxy-pants';
const {hasOwnProperty, toString} = caller(Object.prototype);
// true
hasOwnProperty({any: 'object'}, 'any');
// [object Null]
toString(null);
const {fromCharCode} = applier(String);
const charCodes = (...args) => fromCharCode(null, args);
// <=>
charCodes(60, 61, 62);
bound
Bind one or more methods all at once.
// import {bound} from 'proxy-pants/bound';
import {bound} from 'proxy-pants';
const map = new Map;
const {get, set, has} = bound(map);
// false
has('some');
// the map
set('some', 'value');
// true
has('some');
// 'value'
get('some');
bread & crumbs
Track operations through paths (i.e. a.b.c.d
) and namespaces.
// import {bread, crumbs} from 'proxy-pants/breadcrumbs';
import {bread, crumbs} from 'proxy-pants';
const namespace = {
some: 'value',
method(...args) {
return this.some + args.length;
},
Class: class {}
};
const facade = crumbs({
apply(path, args) {
return bread(namespace, path)(...args);
},
construct(path, args) {
const Class = bread(namespace, path);
return new Class;
},
get(path, key) {
return bread(namespace, path)[key];
},
has(path, key) {
return key in bread(namespace, path);
},
set(path, key, value) {
bread(namespace, path)[key] = value;
return true;
},
// alias for deleteProperty(path, key) {}
delete(path, key) {
return delete bread(namespace, path)[key];
}
});
facade.some; // value
facade.method(1, 2, 3); // some3
new facade.Class; // [object Namespace]
'some' in facade; // true
facade.test = 'ok';
facade.test; // ok
delete facade.test; // true
cache
A secured Map
wrapper to retrieve any property once, through the given callback.
// import {cache} from 'proxy-pants/cache';
import {cache} from 'proxy-pants';
const uids = cache((name) => (name + Math.random()));
uids.a; // "a0.23456787654"
uids.b; // "b0.87654334567"
uids.a === uids.a; // true
'a' in uids; // true
delete uids.a; // true
'a' in uids; // false
chain
Trap once all inherited descriptors down the prototypal chain and automatically ensure the right accessor or method.
// import {chain} from 'proxy-pants/chain';
import {chain} from 'proxy-pants';
const asNode = chain(Node);
const asElement = chain(Element);
asNode(document.createTextNode('accessor')).data;
asElement(document.body).querySelector('method');
dsm
Virtually trap dataset
/ *set
accessors as DOMStringMap like references per each element.
// import {dsm} from 'proxy-pants/dsm';
import {dsm} from 'proxy-pants';
const {ngset: ng, vset: v} = dsm(element);
// set ng-value attribute
ng.value = 123;
// remove ng-some-thing attribute
delete ng.someThing;
// logs v-if attribute, if any
console.log(v.if);
extender
Extend any object through weakly referenced behaviors, providing a new way to deal with state machines too, through the following features:
- methods are always the same bound reference
- properties are defined per extender and never directly attached to the source
- accessors are also defined per each extender
- multiple extenders calls to the same source preserve previous state, and any source can pass through multiple extenders without ever conflicting
// import {extender} from 'proxy-pants/extender';
import {extender} from 'proxy-pants';
const Magic = extender({
// properties are per extender and weakly related
isMagic: true,
// accessors context is the original source/target
get magic() {
// this === source
return Magic(this).isMagic;
},
// methods are always same bound method reference (except init)
hasMagic() {
// this === source
return $(this).magic;
},
// a special method that helps setting up any reference once
// bear in mind Magic(ref).init() won't be defined as own method
init() {
// this is implicitly invoked only the first time Magic(this) is used
}
});
// it can be simplified per module as ...
const $ = Magic;
const source = {};
const target = Magic(source);
target.isMagic; // true
target.magic; // true
target.hasMagic(); // true
// introspection
Magic.extends(source); // true
Magic.extends(target); // true
fetch
Shortcut for fetch(url).json
or any other Response method as direct accessor.
import {fetch} from 'proxy-pants';
const data = await fetch(restAIP).json!.data;
const text = await fetch(page).text || '';
own
Destructure only own properties.
// import {own} from 'proxy-pants/own';
import {own} from 'proxy-pants';
const created = Object.create(
{inherited: true},
{prop: {value: true}}
);
const {inherited, prop} = own(created);
console.assert(!inherited);
console.assert(prop);
secure
Ensure local classes cannot be patched at runtime down their prototypal chain.
// import {secure} from 'proxy-pants/secure';
import {secure} from 'proxy-pants';
const {
Map,
WekMap
} = secure(globalThis);
// both instances now can be used without
// possible issues down the prototypal chain
const map = new Map;
const wm = new WeakMap;
watcher
The good old Object.prototype.watch and unwatch methods to simplify selective reactive state handling.
// import {watcher} from 'proxy-pants/watcher';
import {watcher} from 'proxy-pants';
const watched = watcher({a: {b: 1}});
watched.watch('c', function (prop, oldVal, newVal) {
prop; // 'c'
oldVal; // undefined
newVal; // 2
this.unwatch(prop); // this is the proxied target
});
watched.c = 2;
watched.a.watch('b', console.log);
watched.a.b = 3; // will log
weak-cache
A secured WeakValue wrapper to retrieve any property once, through the given callback, and reteain the result weakly.
// import {wcache} from 'proxy-pants/wcache';
import {wcache} from 'proxy-pants';
// the value has to be an object/reference
const uids = wcache((name) => new String((name + Math.random())));
uids.a; // new String("a0.23456787654")
uids.b; // new String("b0.87654334567")
uids.a === uids.a; // true
'a' in uids; // true
delete uids.a; // true
'a' in uids; // false
weak-proxy
Same proxy constructor but with automatic registration that will invoke a collected(target)
callback once that happens.
// import {WeakProxy} from 'proxy-pants/weak-proxy';
import {WeakProxy} from 'proxy-pants';
let ref = new WeakProxy(globalThis, {
collected(ref) {
console.assert(ref === globalThis);
}
});
// whenever `ref` is collected
ref = null;
// the assertion in the `collected` handler will be true