UNPKG

immutable-class

Version:

A template for creating immutable classes

165 lines (164 loc) 5.62 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NamedArray = exports.Diff = void 0; const equality_1 = require("../equality/equality"); const keyed_array_1 = require("../keyed-array/keyed-array"); const simple_array_1 = require("../simple-array/simple-array"); function getName(thing) { return thing.name; } function noop() { } class Diff { static inflateFromJS(Class, diffJS, context) { let before; let after; if (diffJS.before) before = Class.fromJS(diffJS.before, context); if (diffJS.after) after = Class.fromJS(diffJS.after, context); return new Diff(before, after); } static inflateFromJSs(Class, diffJSs, context) { if (!Array.isArray(diffJSs)) throw new Error('diffs must be an array'); return diffJSs.map(diffJS => Diff.inflateFromJS(Class, diffJS, context)); } constructor(before, after) { Object.defineProperty(this, "before", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "after", { enumerable: true, configurable: true, writable: true, value: void 0 }); if (!before && !after) throw new Error('must have either a before or an after'); if (before && after && before.name !== after.name) throw new Error('before and after name must match'); this.before = before; this.after = after; } toJS() { const js = {}; if (this.before) js.before = this.before; if (this.after) js.after = this.after; return js; } toJSON() { return this.toJS(); } getAction() { if (this.before) { return this.after ? 'update' : 'delete'; } else { return 'create'; } } getName() { const { before, after } = this; if (before) return before.name; if (after) return after.name; throw new Error(`Invalid diff, no before or after`); } } exports.Diff = Diff; const KEYED_ARRAY = keyed_array_1.KeyedArray.withKey('name'); class NamedArray { static isValid(array) { return KEYED_ARRAY.isValid(array); } static checkValid(array, what, where) { return KEYED_ARRAY.checkValid(array, what, where); } static get(array, name) { return KEYED_ARRAY.get(array, name); } static toRecord(array) { return KEYED_ARRAY.toRecord(array); } static containsByName(array, name) { return simple_array_1.SimpleArray.contains(array, x => x.name === name); } static findByNameCI(array, name) { const lowerName = name.toLowerCase(); return simple_array_1.SimpleArray.find(array, x => x.name.toLowerCase() === lowerName); } static findByName(array, name) { return NamedArray.get(array, name); } static findIndexByName(array, name) { return simple_array_1.SimpleArray.findIndex(array, x => x.name === name); } static overrideByName(things, thingOverride) { return KEYED_ARRAY.overrideByKey(things, thingOverride); } static overridesByName(things, thingOverrides) { return KEYED_ARRAY.overridesByKey(things, thingOverrides); } static dedupe(things) { return KEYED_ARRAY.dedupe(things); } static deleteByName(array, name) { return KEYED_ARRAY.deleteByKey(array, name); } static synchronize(oldThings, newThings, updatedOptions) { const key = updatedOptions.key || getName; const equals = updatedOptions.equals || equality_1.immutableEqual; const onEnter = updatedOptions.onEnter || noop; const onUpdate = updatedOptions.onUpdate || noop; const onExit = updatedOptions.onExit || noop; const initialByKey = Object.create(null); for (let i = 0; i < oldThings.length; i++) { const initialThing = oldThings[i]; const initialThingKey = key(initialThing); if (initialByKey[initialThingKey]) throw new Error(`duplicate key '${initialThingKey}'`); initialByKey[initialThingKey] = initialThing; } for (let j = 0; j < newThings.length; j++) { const newThing = newThings[j]; const newThingKey = key(newThing); const oldThing = initialByKey[newThingKey]; if (oldThing) { if (!equals(newThing, oldThing)) { onUpdate(newThing, oldThing); } delete initialByKey[newThingKey]; } else { onEnter(newThing); } } for (const k in initialByKey) { if (!initialByKey[k]) continue; onExit(initialByKey[k]); } } static computeDiffs(oldThings, newThings) { const dataCubeDiffs = []; NamedArray.synchronize(oldThings, newThings, { onExit: oldDataCube => { dataCubeDiffs.push(new Diff(oldDataCube, undefined)); }, onUpdate: (newDataCube, oldDataCube) => { dataCubeDiffs.push(new Diff(oldDataCube, newDataCube)); }, onEnter: newDataCube => { dataCubeDiffs.push(new Diff(undefined, newDataCube)); }, }); return dataCubeDiffs; } } exports.NamedArray = NamedArray;