UNPKG

@getanthill/datastore

Version:

Event-Sourced Datastore

174 lines 6.72 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = getGraph; exports.getEntitiesFromGraph = getEntitiesFromGraph; const DEFAULT_FIELDS = { id: 'id', group: 'group', nodes: 'nodes', edges: 'edges', source: 'source', target: 'target', value: 'value', key: 'key', entity_id_suffix: '_id', entity_type_suffix: '_type', correlation_field: 'correlation_field', }; function addNode(fields, id, group) { return { [fields.id]: id, [fields.group]: group, }; } function addEdge(fields, source, target, value, key, correlationField) { return { [fields.source]: source, [fields.target]: target, [fields.value]: value, [fields.key]: key, [fields.correlation_field]: correlationField, }; } function getFieldsFromOptions(options) { return { ...DEFAULT_FIELDS, ...options === null || options === void 0 ? void 0 : options.fields, }; } function addEdgesFromDiscovery(models, graph, modelName, key, modelNames = [], options) { const fields = getFieldsFromOptions(options); modelNames.forEach((l) => { if (!models.hasModel(l)) { return; } const linkedModel = models.getModel(l); graph[fields.edges].push(addEdge(fields, modelName, l, 1, key, linkedModel.getCorrelationField())); }); } function addEdgeWithoutLink(models, graph, modelName, key, options) { const fields = getFieldsFromOptions(options); if (key.endsWith(fields.entity_id_suffix)) { const target = key .replace(fields.entity_id_suffix, 's') .replace(/ss$/, 's'); if (!models.hasModel(target) || target === modelName) { return; } graph[fields.edges].push(addEdge(fields, modelName, target, 1, key, models.getModel(target).getCorrelationField())); } } function addEdgesFromEntityTypeLink(models, graph, modelName, key, modelNames = [], options) { const fields = getFieldsFromOptions(options); modelNames.forEach((l) => graph[fields.edges].push(addEdge(fields, modelName, l, 1, key, models.getModel(l).getCorrelationField()))); } function addEdgesFromProperties(models, graph, modelName, options) { var _a, _b, _c, _d; const fields = getFieldsFromOptions(options); const model = models.getModel(modelName); const schema = model.getOriginalSchema(); const properties = (_b = (_a = schema === null || schema === void 0 ? void 0 : schema.model) === null || _a === void 0 ? void 0 : _a.properties) !== null && _b !== void 0 ? _b : {}; const links = (_d = (_c = model.getModelConfig()) === null || _c === void 0 ? void 0 : _c.links) !== null && _d !== void 0 ? _d : []; for (const key in properties) { /* @ts-ignore */ const link = links[key]; const entityKey = key.replace(fields.entity_id_suffix, ''); const entityTypeKey = `${entityKey}${fields.entity_type_suffix}`; /** * Discovery process */ if (options.mustDiscover !== false && properties[entityTypeKey]) { addEdgesFromDiscovery(models, graph, modelName, key, properties[entityTypeKey].enum, options); continue; } /** * group_id -> groups * account_id -> accounts */ if (!link) { addEdgeWithoutLink(models, graph, modelName, key, options); continue; } if (properties[link]) { addEdgesFromEntityTypeLink(models, graph, modelName, key, properties[link].enum, options); continue; } if (!models.hasModel(link)) { continue; } graph[fields.edges].push(addEdge(fields, modelName, link, 1, key, models.getModel(link).getCorrelationField())); } } function getGraph(models, options = {}) { const fields = getFieldsFromOptions(options); const graph = { [fields.nodes]: [], [fields.edges]: [], }; for (const modelName of models.MODELS.keys()) { if (models.isInternalModel(modelName) === true) { continue; } graph[fields.nodes].push(addNode(fields, modelName, graph[fields.nodes].length)); addEdgesFromProperties(models, graph, modelName, options); } return graph; } function getEntityId(modelName, correlationId) { return `${modelName}:${correlationId}`; } async function getEntitiesFromGraph(services, modelName, query, options = {}, entities = new Map()) { var _a, _b, _c, _d; if ((Array.isArray(options.models) && !options.models.includes(modelName)) || !services.models) { return entities; } const graph = (_a = options.graph) !== null && _a !== void 0 ? _a : getGraph(services.models); const Model = services.models.getModel(modelName); const correlationField = Model.getCorrelationField(); const entityIds = new Set(); const cursor = await Model.find(services.mongodb, { ...query, [Model.getIsArchivedProperty()]: { $in: [null, false, true], }, }, { projection: { _id: 0, ...(options.withCorrelationFieldOnly === true ? { [correlationField]: 1, } : {}), }, }); while (await cursor.hasNext()) { let entity = await cursor.next(); const entityId = getEntityId(modelName, entity[correlationField]); if (entities.has(entityId)) { continue; } if ('handler' in options && options.handler) { entity = await options.handler(services, Model, entity); } entityIds.add(entity[correlationField]); entities.set(entityId, entity); } // Descendant nodes const childrenModels = (_b = graph === null || graph === void 0 ? void 0 : graph.edges) === null || _b === void 0 ? void 0 : _b.filter((edge) => edge.target === modelName); for (const childModel of childrenModels) { const sourceModel = services.models.getModel(childModel.source); const link = (_d = (_c = sourceModel.getModelConfig()) === null || _c === void 0 ? void 0 : _c.links) === null || _d === void 0 ? void 0 : _d[childModel.key]; const childQuery = { [childModel.key]: { $in: Array.from(entityIds.values()), }, }; if (sourceModel.getSchema().model.properties[link]) { childQuery[link] = childModel.target; } await getEntitiesFromGraph(services, childModel.source, childQuery, { ...options, graph }, entities); } return entities; } //# sourceMappingURL=graph.js.map