UNPKG

jinaga

Version:

Data management for web and mobile applications.

143 lines 4.66 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.dehydrateReference = exports.dehydrateFact = exports.hydrateFromTree = exports.hydrate = exports.lookupHash = exports.Hydration = exports.hashSymbol = exports.Dehydration = void 0; const obj_1 = require("../util/obj"); const hash_1 = require("./hash"); class Dehydration { constructor() { this.entries = []; } factRecords() { return this.entries.map(entry => entry.record); } dehydrate(fact) { const entry = this.entries.find(entry => { return entry.fact === fact; }); if (entry) { return entry.reference; } const record = this.createFactRecord(fact); const reference = { type: record.type, hash: record.hash }; if (!this.entries.find(entry => { return entry.reference.hash === reference.hash && entry.reference.type === reference.type; })) { this.entries.push({ fact, record, reference }); } return reference; } createFactRecord(fact) { let type = null; const fields = {}; const predecessors = {}; for (const field in fact) { const value = (0, obj_1.toJSON)(fact[field]); if (value === null || value === undefined) { // Skip } else if (field === 'type' && typeof (value) === 'string') { type = value; } else if (typeof (value) === 'object') { if (Array.isArray(value)) { predecessors[field] = value .filter(element => element) .map(element => this.dehydrate(element)); } else { predecessors[field] = this.dehydrate(value); } } else { fields[field] = value; } } const hash = (0, hash_1.computeHash)(fields, predecessors); if (!type) { throw new Error('Specify the type of the fact and all of its predecessors.'); } return { type, hash, predecessors, fields }; } } exports.Dehydration = Dehydration; exports.hashSymbol = typeof (Symbol) === "undefined" ? null : Symbol("hash"); class Hydration { constructor(records) { this.entries = records.map(r => { return { record: r, fact: null }; }); } hydrate(reference) { const entry = this.entries.find(r => r.record.hash === reference.hash && r.record.type === reference.type); if (!entry) { throw new Error('Referenced fact not found in tree'); } if (entry.fact) { return entry.fact; } const fields = entry.record.fields; const fact = {}; for (const field in fields) { fact[field] = fields[field]; } fact.type = entry.record.type; for (const role in entry.record.predecessors) { const value = entry.record.predecessors[role]; fact[role] = this.hydratePredecessors(value); } entry.fact = fact; if (exports.hashSymbol) { fact[exports.hashSymbol] = reference.hash; } return fact; } hydratePredecessors(references) { if (Array.isArray(references)) { return references.map(p => this.hydrate(p)); } else { return this.hydrate(references); } } } exports.Hydration = Hydration; function lookupHash(fact) { return exports.hashSymbol && fact[exports.hashSymbol]; } exports.lookupHash = lookupHash; function hydrate(record) { const fact = Object.assign(Object.assign({}, record.fields), { type: record.type }); return fact; } exports.hydrate = hydrate; function hydrateFromTree(references, records) { const hydration = new Hydration(records); return references.map(r => { try { return hydration.hydrate(r); } catch (e) { return null; } }).filter(f => f); } exports.hydrateFromTree = hydrateFromTree; function dehydrateFact(fact) { const dehydration = new Dehydration(); dehydration.dehydrate(fact); return dehydration.factRecords(); } exports.dehydrateFact = dehydrateFact; function dehydrateReference(fact) { const dehydration = new Dehydration(); return dehydration.dehydrate(fact); } exports.dehydrateReference = dehydrateReference; //# sourceMappingURL=hydrate.js.map