117 lines
15 KiB
JavaScript
117 lines
15 KiB
JavaScript
"use strict";
|
|||
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||
|
|
exports.optionalCmp = exports.numberCmp = exports.stringCmp = exports.ref = exports.isEntityCollection = exports.calculatedIndex = exports.fieldIndex = exports.entityCollection = void 0;
|
||
|
|
const sorted_map_1 = require("./sorted-map");
|
||
|
|
function entityCollection() {
|
||
|
|
const entities = new Map();
|
||
|
|
const _indexes = {};
|
||
|
|
function add(x) {
|
||
|
|
entities.set(x.$id, x);
|
||
|
|
for (const index of Object.values(_indexes)) {
|
||
|
|
// FIXME: why can't we type this?
|
||
|
|
index.add(x);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return {
|
||
|
|
type: 'entities',
|
||
|
|
entities,
|
||
|
|
indexes: _indexes,
|
||
|
|
add,
|
||
|
|
dehydrate: () => ({
|
||
|
|
type: 'entities',
|
||
|
|
entities: Array.from(validatePlainObjects(entities).values()),
|
||
|
|
}),
|
||
|
|
hydrateFrom: (x) => {
|
||
|
|
entities.clear();
|
||
|
|
for (const e of Object.values(x.entities)) {
|
||
|
|
add(e);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
index(indexes) {
|
||
|
|
// This limitation exists purely because I couldn't type it otherwise.
|
||
|
|
// Declaring a return type of `EntityCollection<A, I | II>` would make a lot
|
||
|
|
// of our other type inspection code stop working (the union is hard to pick
|
||
|
|
// apart). Since adding indexes in multiple goes is not really a use case,
|
||
|
|
// the simpler solution is just to type it as if we replaced all indexes
|
||
|
|
// and add a runtime check to make sure the types aren't lying.
|
||
|
|
if (Object.keys(_indexes).length > 0) {
|
||
|
|
throw new Error('You may only call .index() once on a new collection');
|
||
|
|
}
|
||
|
|
Object.assign(_indexes, indexes);
|
||
|
|
return this;
|
||
|
|
},
|
||
|
|
};
|
||
|
|
}
|
||
|
|
exports.entityCollection = entityCollection;
|
||
|
|
/**
|
||
|
|
* An index that uses the value of an entity's field
|
||
|
|
*/
|
||
|
|
function fieldIndex(propName, comparator) {
|
||
|
|
return calculatedIndex((x) => x[propName], comparator);
|
||
|
|
}
|
||
|
|
exports.fieldIndex = fieldIndex;
|
||
|
|
/**
|
||
|
|
* An index that is calculated based on a function applied to an entity
|
||
|
|
*/
|
||
|
|
function calculatedIndex(fn, comparator) {
|
||
|
|
const index = [];
|
||
|
|
return {
|
||
|
|
add: (x) => sorted_map_1.sortedMap.add(index, comparator, fn(x), x.$id),
|
||
|
|
lookups: {
|
||
|
|
equals: (value) => sorted_map_1.sortedMap.findAll(index, comparator, value),
|
||
|
|
},
|
||
|
|
index,
|
||
|
|
};
|
||
|
|
}
|
||
|
|
exports.calculatedIndex = calculatedIndex;
|
||
|
|
function isEntityCollection(x) {
|
||
|
|
return typeof x === 'object' && !!x && x.type === 'entities';
|
||
|
|
}
|
||
|
|
exports.isEntityCollection = isEntityCollection;
|
||
|
|
function validatePlainObjects(xs) {
|
||
|
|
for (const x of xs.values()) {
|
||
|
|
if (x.constructor !== Object) {
|
||
|
|
throw new Error(`Entities should be plain-text objects, got instance of ${x.constructor}`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return xs;
|
||
|
|
}
|
||
|
|
function ref(x) {
|
||
|
|
return typeof x === 'string' ? { $ref: x } : { $ref: x.$id };
|
||
|
|
}
|
||
|
|
exports.ref = ref;
|
||
|
|
/**
|
||
|
|
* Determines whether two strings are equivalent in the current or specified locale.
|
||
|
|
*/
|
||
|
|
function stringCmp(a, b) {
|
||
|
|
return a.localeCompare(b);
|
||
|
|
}
|
||
|
|
exports.stringCmp = stringCmp;
|
||
|
|
/**
|
||
|
|
* Determines whether two numbers are equivalent.
|
||
|
|
*/
|
||
|
|
function numberCmp(a, b) {
|
||
|
|
return a - b;
|
||
|
|
}
|
||
|
|
exports.numberCmp = numberCmp;
|
||
|
|
/**
|
||
|
|
* Creates a comparator to determine equivalent of two values, using a given comparator, but allows values to be optional.
|
||
|
|
*
|
||
|
|
* @param frontOrder If `true`, returns so that undefined values are ordered at the front. If `false`, undefined values are ordered at the back.
|
||
|
|
*/
|
||
|
|
function optionalCmp(cmp, frontOrder = true) {
|
||
|
|
return (a, b) => {
|
||
|
|
if (a == undefined && b != undefined) {
|
||
|
|
return frontOrder ? -1 : 1;
|
||
|
|
}
|
||
|
|
if (a != undefined && b == undefined) {
|
||
|
|
return frontOrder ? 1 : -1;
|
||
|
|
}
|
||
|
|
if (a == undefined && b == undefined) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
return cmp(a, b);
|
||
|
|
};
|
||
|
|
}
|
||
|
|
exports.optionalCmp = optionalCmp;
|
||
|
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2VudGl0eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2Q0FBeUQ7QUE0RXpELFNBQWdCLGdCQUFnQjtJQUM5QixNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsRUFBYSxDQUFDO0lBQ3RDLE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQztJQUVwQixTQUFTLEdBQUcsQ0FBQyxDQUFJO1FBQ2YsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3ZCLEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRTtZQUMzQyxpQ0FBaUM7WUFDaEMsS0FBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUN2QjtJQUNILENBQUM7SUFFRCxPQUFPO1FBQ0wsSUFBSSxFQUFFLFVBQVU7UUFDaEIsUUFBUTtRQUNSLE9BQU8sRUFBRSxRQUFlO1FBQ3hCLEdBQUc7UUFDSCxTQUFTLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUNoQixJQUFJLEVBQUUsVUFBVTtZQUNoQixRQUFRLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztTQUM5RCxDQUFDO1FBQ0YsV0FBVyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDakIsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQ2pCLEtBQUssTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUU7Z0JBQ3pDLEdBQUcsQ0FBQyxDQUFRLENBQUMsQ0FBQzthQUNmO1FBQ0gsQ0FBQztRQUNELEtBQUssQ0FBQyxPQUFPO1lBQ1gsc0VBQXNFO1lBQ3RFLDRFQUE0RTtZQUM1RSw0RUFBNEU7WUFDNUUsMEVBQTBFO1lBQzFFLHdFQUF3RTtZQUN4RSwrREFBK0Q7WUFDL0QsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7Z0JBQ3BDLE1BQU0sSUFBSSxLQUFLLENBQUMscURBQXFELENBQUMsQ0FBQzthQUN4RTtZQUNELE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ2pDLE9BQU8sSUFBVyxDQUFDO1FBQ3JCLENBQUM7S0FDRixDQUFDO0FBQ0osQ0FBQztBQXpDRCw0Q0F5Q0M7QUFFRDs7R0FFRztBQUNILFNBQWdCLFVBQVUsQ0FDeEIsUUFBVyxFQUNYLFVBQXNDO0lBRXRDLE9BQU8sZUFBZSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7QUFDekQsQ0FBQztBQUxELGdDQUtDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixlQUFlLENBQXNCLEVBQWUsRUFBRSxVQUFtQztJQUN2RyxNQUFNLEtBQUssR0FBOEIsRUFBRSxDQUFDO0lBQzVDLE9BQU87UUFDTCxHQUFHLEVBQUUsQ0FBQyxDQUFJLEVBQUUsRUFBRSxDQUFDLHNCQUFTLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUM7UUFDN0QsT0FBTyxFQUFFO1lBQ1AsTUFBTSxFQUFFLENBQUMsS0FBUSxFQUFFLEVBQUUsQ0FBQyxzQkFBUyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsVUFBVSxFQUFFLEtBQUssQ0FBQztTQUMzRDtRQUNSLEtBQUs7S0FDTixDQUFDO0FBQ0osQ0FBQztBQVRELDBDQVNDO0FBRUQsU0FBZ0Isa0JBQWtCLENBQUMsQ0FBVTtJQUMzQyxPQUFPLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFLLENBQVMsQ0FBQyxJQUFJLEtBQUssVUFBVSxDQUFDO0FBQ3hFLENBQUM7QUFGRCxnREFFQztBQUVELFNBQVMsb0JBQW9CLENBQW1CLEVBQWtCO0lBQ2hFLEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFO1FBQzNCLElBQUksQ0FBQyxDQUFDLFdBQVcsS0FBSyxNQUFNLEVBQUU7WUFDNUIsTUFBTSxJQUFJLEtBQUssQ0FBQywwREFBMEQsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUM7U0FDNUY7S0FDRjtJQUNELE9BQU8sRUFBRSxDQUFDO0FBQ1osQ0FBQztBQU1ELFNBQWdCLEdBQUcsQ0FBbUIsQ0FBYTtJQUNqRCxPQUFPLE9BQU8sQ0FBQyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUMvRCxDQUFDO0FBRkQsa0JBRUM7QUFFRDs7R0FFRztBQUNILFNBQWdCLFNBQVMsQ0FBQyxDQUFTLEVBQUUsQ0FBUztJQUM1QyxPQUFPLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDNUIsQ0FBQztBQUZELDhCQUVDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixTQUFTLENBQUMsQ0FBUyxFQUFFLENBQVM7SUFDNUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ2YsQ0FBQztBQUZELDhCQUVDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQWdCLFdBQVcsQ0FBSSxHQUEyQixFQUFFLFVBQVUsR0FBRyxJQUFJO0lBQzNFLE9BQU8sQ0FBQyxDQUFnQixFQUFFLENBQWdCLEVBQUUsRUFBRTtRQUM1QyxJQUFJLENBQUMsSUFBSSxTQUFTLElBQUksQ0FBQyxJQUFJLFNBQVMsRUFBRTtZQUNwQyxPQUFPLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUM1QjtRQUNELElBQUksQ0FBQyxJQUFJLFNBQVMsSUFBSSxDQUFDLElBQUksU0FBUyxFQUFFO1lBQ3BDLE9BQU8sVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQzVCO1FBQ0QsSUFBSSxDQUFDLElBQUksU0FBUyxJQUFJLENBQUMsSUFBSSxTQUFTLEVBQUU7WUFDcEMsT0FBTyxDQUFDLENBQUM7U0FDVjtRQUVELE9BQU8sR0FBRyxDQUFDLENBQUUsRUFBRSxDQUFFLENBQUMsQ0FBQztJQUNyQixDQUFDLENBQUM7QUFDSixDQUFDO0FBZEQsa0NBY0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBzb3J0ZWRNYXAsIFNvcnRlZE11bHRpTWFwIH0gZnJvbSAnLi9zb3J0ZWQtbWFwJztcblxuZXhwb3J0IGludGVyZ
|