@data-client/normalizr
Version:
Normalizes and denormalizes JSON according to schema for Redux and Flux applications
68 lines (66 loc) • 8.16 kB
JavaScript
import { UNDEF } from '../denormalize/UNDEF.js';
/** Maps a (ordered) list of dependencies to a value.
*
* Useful as a memoization cache for flat/normalized stores.
*
* All dependencies are only weakly referenced, allowing automatic garbage collection
* when any dependencies are no longer used.
*/
export default class WeakDependencyMap {
constructor() {
this.next = new WeakMap();
this.nextPath = undefined;
}
get(entity, getDependency) {
let curLink = this.next.get(entity);
if (!curLink) return EMPTY;
while (curLink.nextPath) {
var _getDependency;
// we cannot perform lookups with `undefined`, so we use a special object to represent undefined
const nextDependency = (_getDependency = getDependency(curLink.nextPath)) != null ? _getDependency : UNDEF;
curLink = curLink.next.get(nextDependency);
if (!curLink) return EMPTY;
}
// curLink exists, but has no path - so must have a value
return [curLink.value, curLink.journey];
}
set(dependencies, value) {
if (dependencies.length < 1) throw new KeySize();
let curLink = this;
for (const {
path,
entity
} of dependencies) {
let nextLink = curLink.next.get(entity);
if (!nextLink) {
nextLink = new Link();
// void members are represented as a symbol so we can lookup
curLink.next.set(entity != null ? entity : UNDEF, nextLink);
}
curLink.nextPath = path;
curLink = nextLink;
}
// in case there used to be more
curLink.nextPath = undefined;
curLink.value = value;
// we could recompute this on get, but it would have a cost and we optimize for `get`
curLink.journey = dependencies.map(dep => dep.path);
}
}
const EMPTY = [undefined, undefined];
/** Link in a chain */
class Link {
constructor() {
this.next = new WeakMap();
this.nextPath = undefined;
this.value = undefined;
this.journey = [];
}
}
class KeySize extends Error {
constructor(...args) {
super(...args);
this.message = 'Keys must include at least one member';
}
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJVTkRFRiIsIldlYWtEZXBlbmRlbmN5TWFwIiwiY29uc3RydWN0b3IiLCJuZXh0IiwiV2Vha01hcCIsIm5leHRQYXRoIiwidW5kZWZpbmVkIiwiZ2V0IiwiZW50aXR5IiwiZ2V0RGVwZW5kZW5jeSIsImN1ckxpbmsiLCJFTVBUWSIsIl9nZXREZXBlbmRlbmN5IiwibmV4dERlcGVuZGVuY3kiLCJ2YWx1ZSIsImpvdXJuZXkiLCJzZXQiLCJkZXBlbmRlbmNpZXMiLCJsZW5ndGgiLCJLZXlTaXplIiwicGF0aCIsIm5leHRMaW5rIiwiTGluayIsIm1hcCIsImRlcCIsIkVycm9yIiwiYXJncyIsIm1lc3NhZ2UiXSwic291cmNlcyI6WyIuLi8uLi9zcmMvbWVtby9XZWFrRGVwZW5kZW5jeU1hcC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBVTkRFRiB9IGZyb20gJy4uL2Rlbm9ybWFsaXplL1VOREVGLmpzJztcblxuLyoqIE1hcHMgYSAob3JkZXJlZCkgbGlzdCBvZiBkZXBlbmRlbmNpZXMgdG8gYSB2YWx1ZS5cbiAqXG4gKiBVc2VmdWwgYXMgYSBtZW1vaXphdGlvbiBjYWNoZSBmb3IgZmxhdC9ub3JtYWxpemVkIHN0b3Jlcy5cbiAqXG4gKiBBbGwgZGVwZW5kZW5jaWVzIGFyZSBvbmx5IHdlYWtseSByZWZlcmVuY2VkLCBhbGxvd2luZyBhdXRvbWF0aWMgZ2FyYmFnZSBjb2xsZWN0aW9uXG4gKiB3aGVuIGFueSBkZXBlbmRlbmNpZXMgYXJlIG5vIGxvbmdlciB1c2VkLlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBXZWFrRGVwZW5kZW5jeU1hcDxcbiAgUGF0aCxcbiAgSyBleHRlbmRzIG9iamVjdCA9IG9iamVjdCxcbiAgViA9IGFueSxcbj4ge1xuICBwcml2YXRlIHJlYWRvbmx5IG5leHQgPSBuZXcgV2Vha01hcDxLLCBMaW5rPFBhdGgsIEssIFY+PigpO1xuICBwcml2YXRlIG5leHRQYXRoOiBQYXRoIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuXG4gIGdldChlbnRpdHk6IEssIGdldERlcGVuZGVuY3k6IEdldERlcGVuZGVuY3k8UGF0aCwgSyB8IHN5bWJvbD4pIHtcbiAgICBsZXQgY3VyTGluayA9IHRoaXMubmV4dC5nZXQoZW50aXR5KTtcbiAgICBpZiAoIWN1ckxpbmspIHJldHVybiBFTVBUWTtcbiAgICB3aGlsZSAoY3VyTGluay5uZXh0UGF0aCkge1xuICAgICAgLy8gd2UgY2Fubm90IHBlcmZvcm0gbG9va3VwcyB3aXRoIGB1bmRlZmluZWRgLCBzbyB3ZSB1c2UgYSBzcGVjaWFsIG9iamVjdCB0byByZXByZXNlbnQgdW5kZWZpbmVkXG4gICAgICBjb25zdCBuZXh0RGVwZW5kZW5jeSA9IGdldERlcGVuZGVuY3koY3VyTGluay5uZXh0UGF0aCkgPz8gVU5ERUY7XG4gICAgICBjdXJMaW5rID0gY3VyTGluay5uZXh0LmdldChuZXh0RGVwZW5kZW5jeSBhcyBhbnkpO1xuICAgICAgaWYgKCFjdXJMaW5rKSByZXR1cm4gRU1QVFk7XG4gICAgfVxuICAgIC8vIGN1ckxpbmsgZXhpc3RzLCBidXQgaGFzIG5vIHBhdGggLSBzbyBtdXN0IGhhdmUgYSB2YWx1ZVxuICAgIHJldHVybiBbY3VyTGluay52YWx1ZSwgY3VyTGluay5qb3VybmV5XSBhcyByZWFkb25seSBbViwgUGF0aFtdXTtcbiAgfVxuXG4gIHNldChkZXBlbmRlbmNpZXM6IERlcDxQYXRoLCBLPltdLCB2YWx1ZTogVikge1xuICAgIGlmIChkZXBlbmRlbmNpZXMubGVuZ3RoIDwgMSkgdGhyb3cgbmV3IEtleVNpemUoKTtcbiAgICBsZXQgY3VyTGluazogTGluazxQYXRoLCBLLCBWPiA9IHRoaXMgYXMgYW55O1xuICAgIGZvciAoY29uc3QgeyBwYXRoLCBlbnRpdHkgfSBvZiBkZXBlbmRlbmNpZXMpIHtcbiAgICAgIGxldCBuZXh0TGluayA9IGN1ckxpbmsubmV4dC5nZXQoZW50aXR5IGFzIEspO1xuICAgICAgaWYgKCFuZXh0TGluaykge1xuICAgICAgICBuZXh0TGluayA9IG5ldyBMaW5rPFBhdGgsIEssIFY+KCk7XG4gICAgICAgIC8vIHZvaWQgbWVtYmVycyBhcmUgcmVwcmVzZW50ZWQgYXMgYSBzeW1ib2wgc28gd2UgY2FuIGxvb2t1cFxuICAgICAgICBjdXJMaW5rLm5leHQuc2V0KGVudGl0eSA/PyBVTkRFRiwgbmV4dExpbmspO1xuICAgICAgfVxuICAgICAgY3VyTGluay5uZXh0UGF0aCA9IHBhdGg7XG4gICAgICBjdXJMaW5rID0gbmV4dExpbms7XG4gICAgfVxuICAgIC8vIGluIGNhc2UgdGhlcmUgdXNlZCB0byBiZSBtb3JlXG4gICAgY3VyTGluay5uZXh0UGF0aCA9IHVuZGVmaW5lZDtcbiAgICBjdXJMaW5rLnZhbHVlID0gdmFsdWU7XG4gICAgLy8gd2UgY291bGQgcmVjb21wdXRlIHRoaXMgb24gZ2V0LCBidXQgaXQgd291bGQgaGF2ZSBhIGNvc3QgYW5kIHdlIG9wdGltaXplIGZvciBgZ2V0YFxuICAgIGN1ckxpbmsuam91cm5leSA9IGRlcGVuZGVuY2llcy5tYXAoZGVwID0+IGRlcC5wYXRoKTtcbiAgfVxufVxuXG5leHBvcnQgdHlwZSBHZXREZXBlbmRlbmN5PFBhdGgsIEsgPSBvYmplY3QgfCBzeW1ib2w+ID0gKFxuICBsb29rdXA6IFBhdGgsXG4pID0+IEsgfCB1bmRlZmluZWQ7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVwPFBhdGgsIEsgPSBvYmplY3Q+IHtcbiAgcGF0aDogUGF0aDtcbiAgZW50aXR5OiBLIHwgdW5kZWZpbmVkO1xufVxuXG5jb25zdCBFTVBUWSA9IFt1bmRlZmluZWQsIHVuZGVmaW5lZF0gYXMgY29uc3Q7XG5cbi8qKiBMaW5rIGluIGEgY2hhaW4gKi9cbmNsYXNzIExpbms8UGF0aCwgSyBleHRlbmRzIG9iamVjdCwgVj4ge1xuICBuZXh0ID0gbmV3IFdlYWtNYXA8SywgTGluazxQYXRoLCBLLCBWPj4oKTtcbiAgbmV4dFBhdGg6IFBhdGggfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gIHZhbHVlOiBWIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICBqb3VybmV5OiBQYXRoW10gPSBbXTtcbn1cblxuY2xhc3MgS2V5U2l6ZSBleHRlbmRzIEVycm9yIHtcbiAgbWVzc2FnZSA9ICdLZXlzIG11c3QgaW5jbHVkZSBhdCBsZWFzdCBvbmUgbWVtYmVyJztcbn1cbiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsS0FBSyxRQUFRLHlCQUF5Qjs7QUFFL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE1BQU1DLGlCQUFpQixDQUlwQztFQUFBQyxZQUFBO0lBQUEsS0FDaUJDLElBQUksR0FBRyxJQUFJQyxPQUFPLENBQXNCLENBQUM7SUFBQSxLQUNsREMsUUFBUSxHQUFxQkMsU0FBUztFQUFBO0VBRTlDQyxHQUFHQSxDQUFDQyxNQUFTLEVBQUVDLGFBQThDLEVBQUU7SUFDN0QsSUFBSUMsT0FBTyxHQUFHLElBQUksQ0FBQ1AsSUFBSSxDQUFDSSxHQUFHLENBQUNDLE1BQU0sQ0FBQztJQUNuQyxJQUFJLENBQUNFLE9BQU8sRUFBRSxPQUFPQyxLQUFLO0lBQzFCLE9BQU9ELE9BQU8sQ0FBQ0wsUUFBUSxFQUFFO01BQUEsSUFBQU8sY0FBQTtNQUN2QjtNQUNBLE1BQU1DLGNBQWMsSUFBQUQsY0FBQSxHQUFHSCxhQUFhLENBQUNDLE9BQU8sQ0FBQ0wsUUFBUSxDQUFDLFlBQUFPLGNBQUEsR0FBSVosS0FBSztNQUMvRFUsT0FBTyxHQUFHQSxPQUFPLENBQUNQLElBQUksQ0FBQ0ksR0FBRyxDQUFDTSxjQUFxQixDQUFDO01BQ2pELElBQUksQ0FBQ0gsT0FBTyxFQUFFLE9BQU9DLEtBQUs7SUFDNUI7SUFDQTtJQUNBLE9BQU8sQ0FBQ0QsT0FBTyxDQUFDSSxLQUFLLEVBQUVKLE9BQU8sQ0FBQ0ssT0FBTyxDQUFDO0VBQ3pDO0VBRUFDLEdBQUdBLENBQUNDLFlBQTRCLEVBQUVILEtBQVEsRUFBRTtJQUMxQyxJQUFJRyxZQUFZLENBQUNDLE1BQU0sR0FBRyxDQUFDLEVBQUUsTUFBTSxJQUFJQyxPQUFPLENBQUMsQ0FBQztJQUNoRCxJQUFJVCxPQUF5QixHQUFHLElBQVc7SUFDM0MsS0FBSyxNQUFNO01BQUVVLElBQUk7TUFBRVo7SUFBTyxDQUFDLElBQUlTLFlBQVksRUFBRTtNQUMzQyxJQUFJSSxRQUFRLEdBQUdYLE9BQU8sQ0FBQ1AsSUFBSSxDQUFDSSxHQUFHLENBQUNDLE1BQVcsQ0FBQztNQUM1QyxJQUFJLENBQUNhLFFBQVEsRUFBRTtRQUNiQSxRQUFRLEdBQUcsSUFBSUMsSUFBSSxDQUFhLENBQUM7UUFDakM7UUFDQVosT0FBTyxDQUFDUCxJQUFJLENBQUNhLEdBQUcsQ0FBQ1IsTUFBTSxXQUFOQSxNQUFNLEdBQUlSLEtBQUssRUFBRXFCLFFBQVEsQ0FBQztNQUM3QztNQUNBWCxPQUFPLENBQUNMLFFBQVEsR0FBR2UsSUFBSTtNQUN2QlYsT0FBTyxHQUFHVyxRQUFRO0lBQ3BCO0lBQ0E7SUFDQVgsT0FBTyxDQUFDTCxRQUFRLEdBQUdDLFNBQVM7SUFDNUJJLE9BQU8sQ0FBQ0ksS0FBSyxHQUFHQSxLQUFLO0lBQ3JCO0lBQ0FKLE9BQU8sQ0FBQ0ssT0FBTyxHQUFHRSxZQUFZLENBQUNNLEdBQUcsQ0FBQ0MsR0FBRyxJQUFJQSxHQUFHLENBQUNKLElBQUksQ0FBQztFQUNyRDtBQUNGO0FBV0EsTUFBTVQsS0FBSyxHQUFHLENBQUNMLFNBQVMsRUFBRUEsU0FBUyxDQUFVOztBQUU3QztBQUNBLE1BQU1nQixJQUFJLENBQTRCO0VBQUFwQixZQUFBO0lBQUEsS0FDcENDLElBQUksR0FBRyxJQUFJQyxPQUFPLENBQXNCLENBQUM7SUFBQSxLQUN6Q0MsUUFBUSxHQUFxQkMsU0FBUztJQUFBLEtBQ3RDUSxLQUFLLEdBQWtCUixTQUFTO0lBQUEsS0FDaENTLE9BQU8sR0FBVyxFQUFFO0VBQUE7QUFDdEI7QUFFQSxNQUFNSSxPQUFPLFNBQVNNLEtBQUssQ0FBQztFQUFBdkIsWUFBQSxHQUFBd0IsSUFBQTtJQUFBLFNBQUFBLElBQUE7SUFBQSxLQUMxQkMsT0FBTyxHQUFHLHVDQUF1QztFQUFBO0FBQ25EIiwiaWdub3JlTGlzdCI6W119