jinaga
Version:
Data management for web and mobile applications.
143 lines • 4.66 kB
JavaScript
;
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