@getanthill/datastore
Version:
Event-Sourced Datastore
146 lines • 5.13 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateEntity = exports.processExplanationPlan = exports.deepCoerce = exports.deepCoerceProp = exports.mapValuesDeep = exports.mergeWithReplacedArrays = exports.getDateNow = exports.getDate = exports.random = exports.unique = void 0;
const node_assert_1 = __importDefault(require("node:assert"));
const node_crypto_1 = __importDefault(require("node:crypto"));
const node_util_1 = __importDefault(require("node:util"));
const lodash_1 = __importDefault(require("lodash"));
function unique(value, index, self) {
return self.indexOf(value) === index;
}
exports.unique = unique;
function random() {
return node_crypto_1.default.getRandomValues(new Uint8Array(1))[0] / 256;
}
exports.random = random;
function getDate(str) {
return !!str || str === 0 ? new Date(str) : new Date();
}
exports.getDate = getDate;
function getDateNow() {
return Date.now();
}
exports.getDateNow = getDateNow;
function mergeWithReplacedArrays(_srcValue, objValue) {
return Array.isArray(objValue) ? objValue : undefined;
}
exports.mergeWithReplacedArrays = mergeWithReplacedArrays;
function mapValuesDeep(obj, handler = (v) => v) {
Object.keys(obj).forEach((key) => {
obj[key] = handler(obj[key], key);
if (typeof obj[key] === 'object' && obj[key] !== null) {
obj[key] = mapValuesDeep(obj[key], handler);
}
});
return obj;
}
exports.mapValuesDeep = mapValuesDeep;
function deepCoerceProp(obj, schema, fn, path, name) {
const prop = obj[name];
const _path = [...path, name];
const _schema = lodash_1.default.get(schema.properties, name, schema);
const { type, format } = _schema;
if (type === 'array') {
obj[name] = deepCoerce(prop, _schema.items || {}, fn, _path);
return;
}
if (typeof prop === 'object' && prop !== null) {
obj[name] = deepCoerce(prop, _schema, fn, _path);
return;
}
if (type === 'integer') {
const _value = parseInt(obj[name], 10);
if (isNaN(_value) === false) {
obj[name] = _value;
}
return;
}
if (type === 'number') {
const _value = parseFloat(obj[name]);
if (isNaN(_value) === false) {
obj[name] = _value;
}
return;
}
if (type === 'boolean') {
obj[name] = Boolean(JSON.parse(obj[name]));
return;
}
if ((format === 'date' || format === 'date-time') &&
(typeof obj[name] === 'string' || typeof obj[name] === 'number')) {
obj[name] = new Date(obj[name]);
return;
}
obj[name] = fn(prop, _schema, _path);
}
exports.deepCoerceProp = deepCoerceProp;
/**
* Deep coerce object against its JSON Schema
*
* @param {object} obj The object to freeze
* @returns {object} The freezed object
*/
function deepCoerce(obj, schema, fn = (v) => v, path = []) {
if (Object.isFrozen(obj)) {
return obj;
}
let propNames = Object.getOwnPropertyNames(obj);
if (Array.isArray(obj)) {
propNames = propNames.filter((p) => p !== 'length');
}
for (const name of propNames) {
deepCoerceProp(obj, schema, fn, path, name);
}
return obj;
}
exports.deepCoerce = deepCoerce;
function processExplanationPlan(raw) {
const winningPlan = lodash_1.default.get(raw, 'queryPlanner.winningPlan');
const executionStats = lodash_1.default.get(raw, 'executionStats');
return {
stage: winningPlan?.inputStage?.stage ?? winningPlan?.stage,
executation_time_ms: executionStats?.executionTimeMillis,
index_name: winningPlan?.inputStage?.indexName,
keys_examined: executionStats?.totalKeysExamined,
docs_examined: executionStats?.totalDocsExamined,
winning_plan: winningPlan,
raw,
};
}
exports.processExplanationPlan = processExplanationPlan;
function validateEntity(validator, entity, schema, throwOnInvalidEvent = true) {
const schemaId = `entity`;
let validate = validator.getSchema(schemaId);
if (!validate) {
validator.addSchema(schema, schemaId);
validate = validator.getSchema(schemaId);
}
const isValid = validate(entity);
if (isValid === false && throwOnInvalidEvent === true) {
const assertionErrorPayload = {
message: 'State schema validation error',
expected: null,
actual: node_util_1.default.inspect({
schema,
entity,
errors: validate.errors,
}, false, null, false),
};
const err = new node_assert_1.default.AssertionError(assertionErrorPayload);
// @ts-ignore
err.details = validate.errors;
// @ts-ignore
err.details.push({
entity,
});
// @ts-ignore
err.entity = entity;
throw err;
}
return isValid;
}
exports.validateEntity = validateEntity;
//# sourceMappingURL=index.js.map