@blitznocode/blitz-orm 0.0.41 → 0.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js DELETED
@@ -1,1828 +0,0 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __commonJS = (cb, mod) => function __require() {
9
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
- };
11
- var __export = (target, all) => {
12
- for (var name in all)
13
- __defProp(target, name, { get: all[name], enumerable: true });
14
- };
15
- var __copyProps = (to, from, except, desc) => {
16
- if (from && typeof from === "object" || typeof from === "function") {
17
- for (let key of __getOwnPropNames(from))
18
- if (!__hasOwnProp.call(to, key) && key !== except)
19
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
- }
21
- return to;
22
- };
23
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
-
29
- // ../essentials/dist/index.js
30
- var require_dist = __commonJS({
31
- "../essentials/dist/index.js"(exports, module2) {
32
- "use strict";
33
- var __defProp2 = Object.defineProperty;
34
- var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
35
- var __getOwnPropNames2 = Object.getOwnPropertyNames;
36
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
37
- var __export2 = (target, all) => {
38
- for (var name in all)
39
- __defProp2(target, name, { get: all[name], enumerable: true });
40
- };
41
- var __copyProps2 = (to, from, except, desc) => {
42
- if (from && typeof from === "object" || typeof from === "function") {
43
- for (let key of __getOwnPropNames2(from))
44
- if (!__hasOwnProp2.call(to, key) && key !== except)
45
- __defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
46
- }
47
- return to;
48
- };
49
- var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
50
- var essentials_exports = {};
51
- __export2(essentials_exports, {
52
- oFilter: () => oFilter4,
53
- oFind: () => oFind2,
54
- oMap: () => oMap,
55
- objectFilter: () => objectFilter
56
- });
57
- module2.exports = __toCommonJS2(essentials_exports);
58
- var oFilter4 = (obj, fn) => Object.fromEntries(Object.entries(obj).filter(fn));
59
- function objectFilter(obj, fn) {
60
- return Object.fromEntries(Object.entries(obj).filter(([k, v]) => fn(k, v)));
61
- }
62
- var oMap = (obj, fn) => Object.entries(obj).map(([key, value]) => fn(key, value));
63
- var oFind2 = (obj, fn) => Object.values(Object.fromEntries(Object.entries(obj).filter(fn)))[0];
64
- }
65
- });
66
-
67
- // src/index.ts
68
- var src_exports = {};
69
- __export(src_exports, {
70
- default: () => src_default
71
- });
72
- module.exports = __toCommonJS(src_exports);
73
- var import_radash9 = require("radash");
74
- var import_typedb_client3 = require("typedb-client");
75
-
76
- // src/default.config.ts
77
- var defaultConfig = {
78
- query: {
79
- simplifiedLinks: true
80
- },
81
- mutation: {}
82
- };
83
-
84
- // src/helpers.ts
85
- var import_essentials = __toESM(require_dist());
86
- var import_immer = __toESM(require("immer"));
87
- var import_object_traversal = require("object-traversal");
88
- var import_radash = require("radash");
89
- var enrichSchema = (schema) => {
90
- const allLinkedFields = [];
91
- const withExtensionsSchema = (0, import_immer.default)(
92
- schema,
93
- (draft) => (0, import_object_traversal.traverse)(
94
- draft,
95
- ({ value, meta }) => {
96
- if (meta.depth === 2 && value.extends) {
97
- const extendedSchema = draft.entities[value.extends] || draft.relations[value.extends];
98
- value;
99
- value.idFields = extendedSchema.idFields ? (value.idFields || []).concat(extendedSchema.idFields) : value.idFields;
100
- value.dataFields = extendedSchema.dataFields ? (value.dataFields || []).concat(extendedSchema.dataFields) : value.dataFields;
101
- value.linkFields = extendedSchema.linkFields ? (value.linkFields || []).concat(extendedSchema.linkFields) : value.linkFields;
102
- if ("roles" in extendedSchema) {
103
- const val = value;
104
- const extendedRelationSchema = extendedSchema;
105
- val.roles = val.roles || {};
106
- val.roles = {
107
- ...val.roles,
108
- ...extendedRelationSchema.roles
109
- };
110
- if (Object.keys(val.roles).length === 0) {
111
- val.roles = {};
112
- }
113
- }
114
- }
115
- },
116
- { traversalType: "breadth-first" }
117
- )
118
- );
119
- (0, import_object_traversal.traverse)(schema, ({ key, value, meta }) => {
120
- if (key === "linkFields") {
121
- const getThingTypes = () => {
122
- if (!meta.nodePath) {
123
- throw new Error("No path");
124
- }
125
- const pathArray = meta.nodePath.split(".");
126
- const thingPath = pathArray[0];
127
- const thing = pathArray[1];
128
- const thingType = thingPath === "entities" ? "entity" : thingPath === "relations" ? "relation" : "";
129
- return {
130
- thing,
131
- thingType
132
- };
133
- };
134
- const thingTypes = getThingTypes();
135
- const withThing = !Array.isArray(value) ? [
136
- {
137
- ...value,
138
- ...thingTypes
139
- }
140
- ] : value.map((x) => ({ ...x, ...thingTypes }));
141
- allLinkedFields.push(...withThing);
142
- }
143
- });
144
- const enrichedSchema = (0, import_immer.default)(
145
- withExtensionsSchema,
146
- (draft) => (0, import_object_traversal.traverse)(draft, ({ value, key, meta }) => {
147
- if (meta.depth === 2 && value.idFields && !value.id) {
148
- value.name = key;
149
- const thingType = () => {
150
- if (meta.nodePath?.split(".")[0] === "entities")
151
- return "entity";
152
- if (meta.nodePath?.split(".")[0] === "relations")
153
- return "relation";
154
- throw new Error("Unsupported node attributes");
155
- };
156
- value.thingType = thingType();
157
- value.computedFields = [];
158
- if ("roles" in value) {
159
- const val = value;
160
- Object.entries(val.roles).forEach(([roleKey, role]) => {
161
- role.playedBy = allLinkedFields.filter(
162
- (x) => x.relation === key && x.plays === roleKey
163
- ) || [];
164
- });
165
- }
166
- if ("linkFields" in value && value.linkFields) {
167
- const val = value;
168
- val.linkFields?.forEach((linkField) => {
169
- if (linkField.target === "relation") {
170
- linkField.oppositeLinkFieldsPlayedBy = [
171
- {
172
- plays: linkField.path,
173
- thing: linkField.relation,
174
- thingType: "relation"
175
- }
176
- ];
177
- return;
178
- }
179
- const allOppositeLinkFields = allLinkedFields.filter(
180
- (x) => x.relation === linkField.relation && x.plays !== linkField.plays
181
- ) || [];
182
- linkField.oppositeLinkFieldsPlayedBy = allOppositeLinkFields;
183
- const { filter } = linkField;
184
- linkField.oppositeLinkFieldsPlayedBy = linkField.oppositeLinkFieldsPlayedBy.filter(
185
- (x) => x.target === "role"
186
- );
187
- if (filter && Array.isArray(filter)) {
188
- linkField.oppositeLinkFieldsPlayedBy = linkField.oppositeLinkFieldsPlayedBy.filter(
189
- (lf) => filter.some((ft) => lf.thing === ft.$role)
190
- );
191
- linkField.oppositeLinkFieldsPlayedBy = linkField.oppositeLinkFieldsPlayedBy.filter(
192
- (lf) => filter.some((ft) => lf.thing === ft.$thing)
193
- );
194
- }
195
- if (filter && !Array.isArray(filter)) {
196
- linkField.oppositeLinkFieldsPlayedBy = linkField.oppositeLinkFieldsPlayedBy.filter(
197
- (lf) => lf.$role === filter.$role
198
- );
199
- linkField.oppositeLinkFieldsPlayedBy = linkField.oppositeLinkFieldsPlayedBy.filter(
200
- (lf) => lf.thing === filter.$thing
201
- );
202
- }
203
- });
204
- }
205
- }
206
- if (typeof value === "object" && "playedBy" in value) {
207
- if ([
208
- ...new Set(
209
- value.playedBy?.map((x) => x.thing)
210
- )
211
- ].length > 1) {
212
- throw new Error(
213
- `Unsupported: roleFields can be only played by one thing. Role: ${key} path:${meta.nodePath}`
214
- );
215
- }
216
- if (value.playedBy.length === 0) {
217
- throw new Error(
218
- `Unsupported: roleFields should be played at least by one thing. Role: ${key}, path:${meta.nodePath}`
219
- );
220
- }
221
- }
222
- if (meta.depth === 4 && (value.default || value.computedValue)) {
223
- const [type, thingId] = meta.nodePath?.split(".") || [];
224
- draft[type][thingId].computedFields.push(value.path);
225
- }
226
- })
227
- );
228
- return enrichedSchema;
229
- };
230
- var getCurrentSchema = (schema, node) => {
231
- if (node.$entity) {
232
- if (!(node.$entity in schema.entities)) {
233
- throw new Error(`Missing entity '${node.$entity}' in the schema`);
234
- }
235
- return schema.entities[node.$entity];
236
- }
237
- if (node.$relation) {
238
- if (!(node.$relation in schema.relations)) {
239
- throw new Error(`Missing relation '${node.$relation}' in the schema`);
240
- }
241
- return schema.relations[node.$relation];
242
- }
243
- throw new Error(`Wrong schema or query for ${JSON.stringify(node)}`);
244
- };
245
- var getCurrentFields = (currentSchema, node) => {
246
- const availableDataFields = currentSchema.dataFields?.map((x) => x.path);
247
- const availableLinkFields = currentSchema.linkFields?.map((x) => x.path) || [];
248
- const availableRoleFields = "roles" in currentSchema ? (0, import_radash.listify)(currentSchema.roles, (k) => k) : [];
249
- const availableFields = [
250
- ...availableDataFields || [],
251
- ...availableLinkFields || [],
252
- ...availableRoleFields || []
253
- ];
254
- const reservedRootFields = [
255
- "$entity",
256
- "$op",
257
- "$id",
258
- "$tempId",
259
- "$filer",
260
- "$relation",
261
- "$parentKey",
262
- "$filter",
263
- "$fields"
264
- ];
265
- const allowedFields = [...reservedRootFields, ...availableFields];
266
- if (!node) {
267
- return {
268
- fields: availableFields,
269
- dataFields: availableDataFields,
270
- roleFields: availableRoleFields,
271
- linkFields: availableLinkFields
272
- };
273
- }
274
- const usedFields = node.$fields ? node.$fields.map((x) => {
275
- if (typeof x === "string")
276
- return x;
277
- if ("$path" in x)
278
- return x.$path;
279
- throw new Error(" Wrongly structured query");
280
- }) : (0, import_radash.listify)(node, (k) => k);
281
- const localFilterFields = !node.$filter ? [] : (0, import_radash.listify)(
282
- node.$filter,
283
- (k) => k.toString().startsWith("$") ? void 0 : k.toString()
284
- ).filter((x) => x && availableDataFields?.includes(x));
285
- const nestedFilterFields = !node.$filter ? [] : (0, import_radash.listify)(
286
- node.$filter,
287
- (k) => k.toString().startsWith("$") ? void 0 : k.toString()
288
- ).filter(
289
- (x) => x && [
290
- ...availableRoleFields || [],
291
- ...availableLinkFields || []
292
- ]?.includes(x)
293
- );
294
- const unidentifiedFields = [...usedFields, ...localFilterFields].filter(
295
- (x) => !allowedFields.includes(x)
296
- );
297
- const localFilters = !node.$filter ? {} : (0, import_essentials.oFilter)(
298
- node.$filter,
299
- ([k, _v]) => localFilterFields.includes(k)
300
- );
301
- const nestedFilters = !node.$filter ? {} : (0, import_essentials.oFilter)(
302
- node.$filter,
303
- ([k, _v]) => nestedFilterFields.includes(k)
304
- );
305
- return {
306
- fields: availableFields,
307
- dataFields: availableDataFields,
308
- roleFields: availableRoleFields,
309
- linkFields: availableLinkFields,
310
- unidentifiedFields,
311
- ...localFilterFields.length ? { localFilters } : {},
312
- ...nestedFilterFields.length ? { nestedFilters } : {}
313
- };
314
- };
315
- var getLocalFilters = (currentSchema, node) => {
316
- const thingPath = currentSchema.defaultDBConnector.path || currentSchema.name;
317
- const localFilters = node.$localFilters && (0, import_radash.listify)(node.$localFilters, (k, v) => {
318
- const currentDataField = currentSchema.dataFields?.find(
319
- (x) => x.path === k
320
- );
321
- const dbField = currentDataField?.shared ? k : `${thingPath}\xB7${k}`;
322
- return `has ${dbField} '${v}'`;
323
- });
324
- const localFiltersTql = localFilters?.length ? `, ${localFilters.join(",")}` : "";
325
- return localFiltersTql;
326
- };
327
-
328
- // src/pipeline/control/dispatchPipeline.ts
329
- var import_radash6 = require("radash");
330
-
331
- // src/pipeline/postprocess/parseTQLRes.ts
332
- var import_radash2 = require("radash");
333
- var extractEntities = (conceptMapGroups, schema) => {
334
- const bormEntities = conceptMapGroups.map((conceptMapGroup) => {
335
- const conceptMaps = [...conceptMapGroup.conceptMaps];
336
- const typeDBEntity = conceptMapGroup.owner.asThing();
337
- const thingName = typeDBEntity.type.label.name;
338
- const currentSchema = schema.entities[thingName] ? schema.entities[thingName] : schema.relations[thingName];
339
- if (!currentSchema.idFields) {
340
- throw new Error(`No idFields defined for ${thingName}`);
341
- }
342
- const thingType = schema.entities[thingName] ? "entity" : "relation";
343
- const entityAttributes = conceptMaps.map((conceptMap) => {
344
- const attribute = conceptMap.get("attribute")?.asAttribute();
345
- if (!attribute) {
346
- return [];
347
- }
348
- const nameParts = attribute.type.label.name.split("\xB7");
349
- const attributeName = nameParts[nameParts.length - 1];
350
- return [attributeName, attribute.value];
351
- });
352
- const entity = Object.fromEntries(entityAttributes);
353
- return {
354
- ...entity,
355
- [`$${thingType}`]: thingName,
356
- $id: entity[currentSchema.idFields[0]]
357
- };
358
- });
359
- return bormEntities;
360
- };
361
- var extractRelations = (conceptMapGroups, entityNames) => {
362
- const relations = conceptMapGroups.flatMap((conceptMapGroup) => {
363
- const relationsInGroup = conceptMapGroup.conceptMaps.map((conceptMap) => {
364
- const link = /* @__PURE__ */ new Map();
365
- entityNames.forEach((entityName) => {
366
- const id = conceptMap.get(`${entityName}_id`)?.asAttribute().value.toString();
367
- if (id)
368
- link.set(entityName, id);
369
- });
370
- return link;
371
- });
372
- return relationsInGroup;
373
- });
374
- return relations;
375
- };
376
- var extractRoles = (conceptMapGroups, ownerPath, rolePath) => {
377
- const roles = conceptMapGroups.flatMap((conceptMapGroup) => {
378
- const rolesInGroup = conceptMapGroup.conceptMaps.map((conceptMap) => {
379
- const ownerId = conceptMap.get(`${ownerPath}_id`)?.asAttribute().value.toString();
380
- const roleId = conceptMap.get(`${rolePath}_id`)?.asAttribute().value.toString();
381
- return {
382
- ownerId,
383
- path: rolePath,
384
- roleId
385
- };
386
- });
387
- return rolesInGroup;
388
- });
389
- return roles;
390
- };
391
- var parseTQLRes = async (req, res) => {
392
- const { schema, bqlRequest, config, tqlRequest } = req;
393
- const { rawTqlRes } = res;
394
- if (!bqlRequest) {
395
- throw new Error("BQL request not parsed");
396
- } else if (!rawTqlRes) {
397
- throw new Error("TQL query not executed");
398
- }
399
- const { query } = bqlRequest;
400
- if (!query) {
401
- if (rawTqlRes.insertions?.length === 0 && !tqlRequest?.deletions) {
402
- throw new Error(
403
- "Nothing has changed in DB, probably one of the ids specified in the mutation does not exist"
404
- );
405
- }
406
- const { mutation } = bqlRequest;
407
- if (!mutation) {
408
- throw new Error("TQL mutation not executed");
409
- }
410
- const expected = [...mutation.things, ...mutation.edges];
411
- const result = expected.map((x) => {
412
- const currentNode = rawTqlRes.insertions?.[0].get(
413
- `${x.$tempId || x.$id}`
414
- );
415
- if (x.$op === "create" || x.$op === "update" || x.$op === "link") {
416
- if (!currentNode?.asThing().iid) {
417
- throw new Error(
418
- `Thing not received on mutation: ${JSON.stringify(x)}`
419
- );
420
- }
421
- const dbIdd = currentNode?.asThing().iid;
422
- if (config.mutation?.noMetadata) {
423
- return (0, import_radash2.mapEntries)(x, (k, v) => [
424
- k.toString().startsWith("$") ? Symbol.for(k) : k,
425
- v
426
- ]);
427
- }
428
- return { $dbId: dbIdd, ...x };
429
- }
430
- if (x.$op === "delete" || x.$op === "unlink") {
431
- return x;
432
- }
433
- if (x.$op === "noop") {
434
- return void 0;
435
- }
436
- throw new Error(`Unsupported op ${x.$op}`);
437
- }).filter((x) => x);
438
- res.bqlRes = result.length > 1 ? result : result[0];
439
- return;
440
- }
441
- if (!rawTqlRes.entity) {
442
- throw new Error("TQL query not executed");
443
- }
444
- const entities = extractEntities(rawTqlRes.entity, schema);
445
- const relations = rawTqlRes.relations?.map((relation) => {
446
- const currentRelSchema = schema.relations[relation.relation];
447
- const currentRelroles = (0, import_radash2.listify)(
448
- currentRelSchema.roles,
449
- (_k, v) => {
450
- if ([...new Set(v.playedBy?.map((x) => x.thing))].length !== 1) {
451
- throw new Error(
452
- "a role can be played by two entities throws the same relation"
453
- );
454
- }
455
- if (!v.playedBy)
456
- throw new Error("Role not being played by nobody");
457
- return v.playedBy[0].thing;
458
- }
459
- );
460
- const links = extractRelations(relation.conceptMapGroups, [
461
- ...currentRelroles,
462
- currentRelSchema.name
463
- ]);
464
- return {
465
- name: relation.relation,
466
- links
467
- };
468
- });
469
- const roles = rawTqlRes.roles?.map((role) => {
470
- return {
471
- name: role.ownerPath,
472
- links: extractRoles(role.conceptMapGroups, role.ownerPath, role.path)
473
- };
474
- });
475
- const cache = res.cache || {
476
- entities: /* @__PURE__ */ new Map(),
477
- relations: /* @__PURE__ */ new Map(),
478
- roleLinks: /* @__PURE__ */ new Map()
479
- };
480
- entities.forEach((entity) => {
481
- const entityName = entity.$entity || entity.$relation;
482
- const entityId = entity.$id;
483
- const entityCache = cache.entities.get(entityName) || /* @__PURE__ */ new Map();
484
- entityCache.set(entityId, { ...entity, $show: true });
485
- cache.entities.set(entityName, entityCache);
486
- });
487
- relations?.forEach((relation) => {
488
- const relationName = relation.name;
489
- const relationCache = cache.relations.get(relationName) || [];
490
- relationCache.push(...relation.links);
491
- cache.relations.set(relationName, relationCache);
492
- relation.links.forEach((link) => {
493
- [...link.entries()].forEach(([entityName, entityId]) => {
494
- const entityCache = cache.entities.get(entityName) || /* @__PURE__ */ new Map();
495
- const getEntityThingType = () => {
496
- if (schema.entities[entityName])
497
- return "entity";
498
- if (schema.relations[entityName])
499
- return "relation";
500
- throw new Error("Entity or relation not found");
501
- };
502
- const entityThingType = getEntityThingType();
503
- const entity = {
504
- [entityThingType]: entityName,
505
- $id: entityId,
506
- ...entityCache.get(entityId)
507
- };
508
- entityCache.set(entityId, entity);
509
- cache.entities.set(entityName, entityCache);
510
- });
511
- });
512
- });
513
- roles?.forEach((role) => {
514
- const ownerSchema = schema.relations[role.name] || schema.entities[role.name];
515
- role.links.forEach((link) => {
516
- const cachedLinks = cache.roleLinks.get(link.ownerId) || {};
517
- let cachedLinkID = cachedLinks[link.path];
518
- if (cachedLinkID) {
519
- if ((0, import_radash2.isArray)(cachedLinkID)) {
520
- cachedLinkID.push(link.roleId);
521
- } else if ((0, import_radash2.isString)(cachedLinkID) && cachedLinkID !== link.roleId) {
522
- cachedLinkID = [cachedLinkID, link.roleId];
523
- }
524
- } else {
525
- cachedLinkID = link.roleId;
526
- }
527
- cachedLinks[link.path] = cachedLinkID;
528
- cache.roleLinks.set(link.ownerId, cachedLinks);
529
- ownerSchema.roles[link.path].playedBy?.forEach((roleSchema) => {
530
- const entityCache = cache.entities.get(roleSchema.thing) || /* @__PURE__ */ new Map();
531
- const entity = {
532
- $entity: roleSchema.thing,
533
- $id: link.roleId,
534
- ...entityCache.get(link.roleId)
535
- };
536
- entityCache.set(link.roleId, entity);
537
- cache.entities.set(roleSchema.thing, entityCache);
538
- });
539
- });
540
- });
541
- res.cache = cache;
542
- };
543
-
544
- // src/pipeline/postprocess/fieldsOperator.ts
545
- var import_radash3 = require("radash");
546
-
547
- // src/pipeline/postprocess/buildBQLTree.ts
548
- var import_essentials2 = __toESM(require_dist());
549
- var import_immer2 = __toESM(require("immer"));
550
- var import_object_traversal2 = require("object-traversal");
551
- var import_radash4 = require("radash");
552
- var cleanOutput = (obj, config) => (0, import_immer2.default)(
553
- obj,
554
- (draft) => (0, import_object_traversal2.traverse)(
555
- draft,
556
- ({ value }) => {
557
- if (Array.isArray(value) || !(typeof value === "object"))
558
- return;
559
- if (value.$fields) {
560
- delete value.$fields;
561
- }
562
- if (value.$filter) {
563
- delete value.$filter;
564
- }
565
- if (value.$show) {
566
- delete value.$show;
567
- }
568
- if (config.query?.noMetadata && (value.$entity || value.$relation)) {
569
- delete value.$entity;
570
- delete value.$relation;
571
- delete value.$id;
572
- }
573
- const symbols = Object.getOwnPropertySymbols(obj);
574
- symbols.forEach((symbol) => {
575
- delete value[symbol];
576
- });
577
- }
578
- )
579
- );
580
- var filterChildrenEntities = (things, ids, node, path) => things.map(([id, entity]) => {
581
- if (!ids)
582
- return null;
583
- if (!ids.includes(id))
584
- return null;
585
- if (!node.$fields)
586
- return id;
587
- if (node.$fields.includes(path))
588
- return id;
589
- const currentFieldConf = node.$fields.find(
590
- (f) => (0, import_radash4.isObject)(f) && f.$path === path
591
- );
592
- if (currentFieldConf) {
593
- const onlyMetadataEntity = {
594
- ...(0, import_essentials2.oFilter)(entity, ([k, _v]) => k.startsWith("$"))
595
- };
596
- const withFieldsEntity = currentFieldConf.$fields ? {
597
- ...onlyMetadataEntity,
598
- $fields: currentFieldConf.$fields
599
- } : onlyMetadataEntity;
600
- if (currentFieldConf.$id) {
601
- if (Array.isArray(currentFieldConf.$id)) {
602
- if (currentFieldConf.$id.includes(id))
603
- return withFieldsEntity;
604
- return null;
605
- }
606
- if (currentFieldConf.$id === id)
607
- return withFieldsEntity;
608
- }
609
- return withFieldsEntity;
610
- }
611
- return null;
612
- }).filter((x) => x);
613
- var buildBQLTree = async (req, res) => {
614
- const { bqlRequest, config, schema } = req;
615
- const { cache } = res;
616
- if (!bqlRequest) {
617
- throw new Error("BQL request not parsed");
618
- }
619
- const { query } = bqlRequest;
620
- if (!query) {
621
- res.bqlRes = cleanOutput(res.bqlRes, config);
622
- return;
623
- }
624
- if (!cache) {
625
- return;
626
- }
627
- const thingSchema = "$entity" in query ? query.$entity : query.$relation;
628
- const entityMap = cache.entities.get(thingSchema.name);
629
- if (!entityMap) {
630
- res.bqlRes = null;
631
- return;
632
- }
633
- const filterFields = (0, import_radash4.listify)(query.$filter, (x) => x);
634
- const atLeastOneUnique = filterFields.some(
635
- (x) => thingSchema.dataFields?.find((y) => y.path === x)?.validations?.unique
636
- );
637
- const monoOutput = !Array.isArray(bqlRequest.query) && (bqlRequest.query?.$id && !Array.isArray(bqlRequest.query?.$id) || atLeastOneUnique);
638
- if (Array.isArray(req.rawBqlRequest)) {
639
- throw new Error("Query arrays not implemented yet");
640
- }
641
- const rootThings = entityMap;
642
- const structuredAnswer = [...rootThings].length ? [...rootThings].map(([id, _entity]) => ({
643
- ...req.rawBqlRequest,
644
- $id: id
645
- })) : req.rawBqlRequest;
646
- const bqlTree = (0, import_immer2.default)(
647
- structuredAnswer,
648
- (draft) => (0, import_object_traversal2.traverse)(draft, ({ value: val }) => {
649
- const value = val;
650
- if (!value?.$entity && !value?.$relation)
651
- return;
652
- const thingName = "$entity" in value ? value.$entity : value.$relation;
653
- if (thingName) {
654
- const currentIds = Array.isArray(value.$id) ? value.$id : [value.$id];
655
- const currentSchema = "$relation" in value ? schema.relations[value.$relation] : schema.entities[value.$entity];
656
- const { dataFields, roleFields } = getCurrentFields(currentSchema);
657
- const currentEntities = cache.entities.get(thingName);
658
- if (!currentEntities)
659
- return;
660
- [...currentEntities].forEach(([id, entity]) => {
661
- if (currentIds.includes(id)) {
662
- const queriedDataFields = value.$fields ? value.$fields : dataFields;
663
- (0, import_radash4.listify)(entity, (k, v) => {
664
- if (k.startsWith("$"))
665
- return;
666
- if (!queriedDataFields?.includes(k))
667
- return;
668
- value[k] = v;
669
- });
670
- const links = cache.roleLinks.get(id);
671
- const flatRoleFields = value.$fields ? value.$fields.filter((x) => typeof x === "string") : roleFields;
672
- const embeddedRoleFields = value.$fields?.filter((x) => typeof x === "object")?.map((y) => y.$path) || [];
673
- Object.entries(links || {}).forEach(([rolePath, linkedIds]) => {
674
- if (![...flatRoleFields, ...embeddedRoleFields].includes(rolePath)) {
675
- return;
676
- }
677
- if (!("roles" in currentSchema))
678
- throw new Error("No roles in schema");
679
- const uniqueLinkedIds = !Array.isArray(linkedIds) ? [linkedIds] : [...new Set(linkedIds)];
680
- const { cardinality, playedBy } = currentSchema.roles[rolePath];
681
- const thingNames = [...new Set(playedBy?.map((x) => x.thing))];
682
- const children = thingNames?.flatMap((x) => {
683
- const thingEntities = cache.entities.get(x);
684
- if (!thingEntities)
685
- return [];
686
- return filterChildrenEntities(
687
- [...thingEntities],
688
- uniqueLinkedIds,
689
- value,
690
- rolePath
691
- );
692
- });
693
- if (children?.length) {
694
- if (children.length === 1 && children[0] === value.$id) {
695
- return;
696
- }
697
- if (cardinality === "ONE") {
698
- value[rolePath] = children[0];
699
- return;
700
- }
701
- value[rolePath] = children.filter(
702
- (x) => typeof x === "string" || typeof x === "object" && x?.$show
703
- );
704
- }
705
- });
706
- }
707
- });
708
- const currentLinkFields = currentSchema.linkFields;
709
- if (currentLinkFields) {
710
- currentLinkFields.forEach((linkField) => {
711
- const currentRelation = cache.relations.get(linkField.relation);
712
- const tunnel = linkField.oppositeLinkFieldsPlayedBy;
713
- if (linkField.target === "relation") {
714
- const targetRelation = tunnel[0];
715
- const targetRelationThings = cache.relations.get(
716
- linkField.relation
717
- );
718
- const matchedLinks = !targetRelationThings ? [] : [...targetRelationThings].filter((link) => {
719
- return currentIds.includes(link.get(thingName));
720
- }).map((x) => x.get(targetRelation.thing));
721
- const targetRelationEntities = cache.entities.get(
722
- targetRelation.thing
723
- );
724
- if (!targetRelationEntities)
725
- return null;
726
- const children = filterChildrenEntities(
727
- [...targetRelationEntities],
728
- matchedLinks,
729
- value,
730
- linkField.path
731
- );
732
- if (children.length) {
733
- if (children.length === 1 && children[0] === value.$id) {
734
- return null;
735
- }
736
- if (linkField.cardinality === "ONE") {
737
- value[linkField.path] = children[0];
738
- return null;
739
- }
740
- value[linkField.path] = children.filter(
741
- (x) => typeof x === "string" || typeof x === "object" && x?.$show
742
- );
743
- }
744
- return null;
745
- }
746
- if (linkField.target === "role") {
747
- const linkFieldPlayers = tunnel.flatMap((t) => {
748
- const allCurrentLinkFieldThings = cache.entities.get(t.thing);
749
- const linkedIds = currentRelation ? [...currentRelation].filter((rel) => rel.get(thingName) === currentIds[0]).map((x) => x.get(t.thing)) : [];
750
- const uniqueLinkedIds = [...new Set(linkedIds)];
751
- if (!allCurrentLinkFieldThings)
752
- return null;
753
- const children = filterChildrenEntities(
754
- [...allCurrentLinkFieldThings],
755
- uniqueLinkedIds,
756
- value,
757
- linkField.path
758
- );
759
- if (children.length) {
760
- return children.filter(
761
- (x) => typeof x === "string" || typeof x === "object" && x?.$show
762
- );
763
- }
764
- return null;
765
- }).filter((x) => x);
766
- if (linkFieldPlayers && linkFieldPlayers.length) {
767
- if (linkField.cardinality === "ONE") {
768
- value[linkField.path] = linkFieldPlayers[0];
769
- return null;
770
- }
771
- value[linkField.path] = linkFieldPlayers;
772
- }
773
- return null;
774
- }
775
- return null;
776
- });
777
- }
778
- }
779
- })
780
- );
781
- const withoutFieldFilters = cleanOutput(bqlTree, config);
782
- res.bqlRes = monoOutput ? withoutFieldFilters[0] : withoutFieldFilters;
783
- };
784
-
785
- // src/pipeline/preprocess/buildTQLQuery.ts
786
- var import_radash5 = require("radash");
787
- var buildTQLQuery = async (req) => {
788
- const { schema, bqlRequest } = req;
789
- if (!bqlRequest?.query) {
790
- throw new Error("BQL query not parsed");
791
- }
792
- const { query } = bqlRequest;
793
- const currentThingSchema = "$entity" in query ? query.$entity : query.$relation;
794
- const thingPath = currentThingSchema.defaultDBConnector.path || currentThingSchema.name;
795
- if (!currentThingSchema.idFields) {
796
- throw new Error("No id fields");
797
- }
798
- const [idField] = currentThingSchema.idFields;
799
- const idParam = `$${thingPath}_id`;
800
- let idFilter = `, has ${idField} ${idParam};`;
801
- if (query.$id) {
802
- if (Array.isArray(query.$id)) {
803
- idFilter += ` ${idParam} like "${query.$id.join("|")}";`;
804
- } else {
805
- idFilter += ` ${idParam} "${query.$id}";`;
806
- }
807
- }
808
- const localFiltersTql = getLocalFilters(currentThingSchema, query);
809
- const allRoles = "roles" in currentThingSchema ? (0, import_radash5.listify)(currentThingSchema.roles, (k, v) => ({
810
- path: k,
811
- var: `$${k}`,
812
- schema: v
813
- })) : [];
814
- const queryStr = `match $${thingPath} isa ${thingPath}, has attribute $attribute ${localFiltersTql} ${idFilter} group $${thingPath};`;
815
- const rolesObj = allRoles.map((role) => {
816
- if (!role.schema.playedBy || [...new Set(role.schema.playedBy?.map((x) => x.thing))].length !== 1) {
817
- throw new Error(
818
- "Unsupported: Role played by multiple linkfields or none"
819
- );
820
- }
821
- const roleThingName = role.schema.playedBy[0].thing;
822
- return {
823
- path: role.path,
824
- owner: thingPath,
825
- request: `match $${thingPath} (${role.path}: ${role.var} ) isa ${thingPath} ${idFilter} ${role.var} isa ${roleThingName}, has id ${role.var}_id; group $${thingPath};`
826
- };
827
- });
828
- const relations = currentThingSchema.linkFields?.flatMap((linkField) => {
829
- const entityMatch = `match $${thingPath} isa ${thingPath}${localFiltersTql} ${idFilter}`;
830
- const dirRel = linkField.target === "relation";
831
- const tarRel = linkField.relation;
832
- const relVar = `$${tarRel}`;
833
- const relationMatchStart = `${dirRel ? relVar : ""} (${linkField.plays}: $${thingPath}`;
834
- const relationMatchOpposite = linkField.oppositeLinkFieldsPlayedBy.map(
835
- (link) => !dirRel ? `${link.plays}: $${link.thing}` : null
836
- );
837
- const roles = [relationMatchStart, ...relationMatchOpposite].filter((x) => x).join(",");
838
- const relationPath = schema.relations[linkField.relation].defaultDBConnector.path || linkField.relation;
839
- const relationMatchEnd = `) isa ${relationPath};`;
840
- const relationIdFilters = linkField.oppositeLinkFieldsPlayedBy.map(
841
- (link) => `$${link.thing} isa ${link.thing}, has id $${link.thing}_id;`
842
- ).join(", ");
843
- const group = `group $${thingPath};`;
844
- const request = `${entityMatch} ${roles} ${relationMatchEnd} ${relationIdFilters} ${group}`;
845
- return { relation: relationPath, entity: thingPath, request };
846
- });
847
- req.tqlRequest = {
848
- entity: queryStr,
849
- ...rolesObj?.length ? { roles: rolesObj } : {},
850
- ...relations?.length ? { relations } : {}
851
- };
852
- };
853
-
854
- // src/pipeline/preprocess/parseBQLQuery.ts
855
- var parseBQLQuery = async (req) => {
856
- const { rawBqlRequest: rawBqlQuery, schema } = req;
857
- if (!("$entity" in rawBqlQuery) && !("$relation" in rawBqlQuery)) {
858
- throw new Error("No entity specified in query");
859
- }
860
- const currentSchema = getCurrentSchema(schema, rawBqlQuery);
861
- if (!currentSchema) {
862
- throw new Error(`Thing '${rawBqlQuery}' not found in schema`);
863
- }
864
- const { unidentifiedFields, localFilters, nestedFilters } = getCurrentFields(
865
- currentSchema,
866
- rawBqlQuery
867
- );
868
- if (unidentifiedFields && unidentifiedFields.length > 0) {
869
- throw new Error(
870
- `Unknown fields: [${unidentifiedFields.join(",")}] in ${JSON.stringify(
871
- rawBqlQuery
872
- )}`
873
- );
874
- }
875
- req.bqlRequest = {
876
- query: {
877
- ...req.rawBqlRequest,
878
- ...currentSchema.thingType === "entity" ? { $entity: currentSchema } : {},
879
- ...currentSchema.thingType === "relation" ? { $relation: currentSchema } : {},
880
- ...localFilters ? { $localFilters: localFilters } : {},
881
- ...nestedFilters ? { $nestedFilters: nestedFilters } : {}
882
- }
883
- };
884
- };
885
-
886
- // src/pipeline/transaction/runTQLQuery.ts
887
- var import_typedb_client = require("typedb-client");
888
- var runTQLQuery = async (req, res) => {
889
- const { dbHandles, bqlRequest, tqlRequest, config } = req;
890
- if (!bqlRequest) {
891
- throw new Error("BQL request not parsed");
892
- }
893
- if (!tqlRequest) {
894
- throw new Error("TQL request not built");
895
- }
896
- if (!tqlRequest.entity) {
897
- throw new Error("BQL request error, no entities");
898
- }
899
- const { query } = bqlRequest;
900
- if (!query) {
901
- throw new Error("BQL request is not a query");
902
- }
903
- const singleHandlerV0 = config.dbConnectors[0].id;
904
- const session = dbHandles.typeDB.get(singleHandlerV0)?.session;
905
- if (!session?.isOpen()) {
906
- throw new Error("Session is closed");
907
- }
908
- const transaction = await session.transaction(import_typedb_client.TransactionType.READ);
909
- if (!transaction) {
910
- throw new Error("Can't create transaction");
911
- }
912
- const entityStream = transaction.query.matchGroup(tqlRequest.entity);
913
- const rolesStreams = tqlRequest.roles?.map((role) => ({
914
- ...role,
915
- stream: transaction.query.matchGroup(role.request)
916
- }));
917
- const relationStreams = tqlRequest.relations?.map((relation) => ({
918
- ...relation,
919
- stream: transaction.query.matchGroup(relation.request)
920
- }));
921
- const entityConceptMapGroups = await entityStream.collect();
922
- const rolesConceptMapGroups = await Promise.all(
923
- rolesStreams?.map(async (role) => ({
924
- path: role.path,
925
- ownerPath: role.owner,
926
- conceptMapGroups: await role.stream.collect()
927
- })) || []
928
- );
929
- const relationConceptMapGroups = await Promise.all(
930
- relationStreams?.map(async (relation) => ({
931
- relation: relation.relation,
932
- entity: relation.entity,
933
- conceptMapGroups: await relation.stream.collect()
934
- })) || []
935
- );
936
- await transaction.close();
937
- res.rawTqlRes = {
938
- entity: entityConceptMapGroups,
939
- ...rolesConceptMapGroups?.length && { roles: rolesConceptMapGroups },
940
- ...relationConceptMapGroups?.length && {
941
- relations: relationConceptMapGroups
942
- }
943
- };
944
- };
945
-
946
- // src/pipeline/control/dispatchPipeline.ts
947
- var dispatchPipeline = async (req, res) => {
948
- const { bqlRequest, schema } = req;
949
- const { cache } = res;
950
- if (!bqlRequest) {
951
- throw new Error("BQL request not parsed");
952
- }
953
- if (!cache) {
954
- throw new Error("Cache not initialized");
955
- }
956
- const { query } = bqlRequest;
957
- if (!query) {
958
- return;
959
- }
960
- const { $fields } = query;
961
- if (!("$entity" in query) && !("$relation" in query)) {
962
- throw new Error("Node attributes not supported");
963
- }
964
- const $thing = "$entity" in query ? query.$entity : query.$relation;
965
- if (!$fields || !Array.isArray($fields)) {
966
- return;
967
- }
968
- const expandedLinkAndRoleFields = $fields.filter(
969
- (f) => typeof f !== "string" && f.$path
970
- );
971
- const nestedThingsByLF = $thing.linkFields?.filter(
972
- (linkField) => expandedLinkAndRoleFields.findIndex(
973
- (expanded) => expanded.$path === linkField.path
974
- ) !== -1
975
- ).flatMap((linkField) => linkField.oppositeLinkFieldsPlayedBy) || [];
976
- const nestedThingsByRF = "roles" in $thing ? (0, import_radash6.listify)($thing.roles, (k, v) => {
977
- if (expandedLinkAndRoleFields.findIndex(
978
- (expanded) => expanded.$path === k
979
- ) !== -1) {
980
- return v;
981
- }
982
- return null;
983
- }).flatMap((role) => role?.playedBy).filter((x) => x) : [];
984
- const nestedThings = [...nestedThingsByLF, ...nestedThingsByRF];
985
- const nextOps = nestedThings?.map((linkField) => {
986
- if (!linkField)
987
- return null;
988
- const { thing } = linkField;
989
- const result = cache.entities.get(thing);
990
- const resultIds = [...result?.keys() || []];
991
- const currentSchema = schema.entities[thing] ? { ...schema.entities[thing], thingType: "entity" } : { ...schema.relations[thing], thingType: "relation" };
992
- const $FieldsObj = $fields.find(
993
- (x) => typeof x === "object" && x.$path === linkField.plays
994
- );
995
- const localIdsTemp = $FieldsObj?.$id;
996
- const localIds = !localIdsTemp ? [] : Array.isArray(localIdsTemp) ? localIdsTemp : [localIdsTemp];
997
- const localFilters = $FieldsObj?.$filter;
998
- const commonIds = !localIds.length ? resultIds : localIds.filter((id) => resultIds.includes(id));
999
- const newBqlRequest = {
1000
- query: {
1001
- $id: commonIds,
1002
- $fields: $FieldsObj?.$fields,
1003
- ...currentSchema.thingType === "entity" ? { $entity: currentSchema } : {},
1004
- ...currentSchema.thingType === "relation" ? { $relation: currentSchema } : {},
1005
- ...localFilters ? { $localFilters: localFilters } : {}
1006
- }
1007
- };
1008
- return {
1009
- req: {
1010
- ...req,
1011
- bqlRequest: newBqlRequest
1012
- },
1013
- res,
1014
- pipeline: [buildTQLQuery, runTQLQuery, parseTQLRes, dispatchPipeline]
1015
- };
1016
- }).filter((x) => x);
1017
- if (nextOps?.length) {
1018
- return nextOps;
1019
- }
1020
- };
1021
-
1022
- // src/pipeline/preprocess/buildTQLMutation.ts
1023
- var import_radash7 = require("radash");
1024
- var buildTQLMutation = async (req) => {
1025
- const { bqlRequest, schema } = req;
1026
- if (!bqlRequest) {
1027
- throw new Error("BQL request not parsed");
1028
- }
1029
- const { mutation } = bqlRequest;
1030
- if (!mutation) {
1031
- throw new Error("BQL request is not a mutation");
1032
- }
1033
- const nodeToTypeQL = (node) => {
1034
- const op = node.$op;
1035
- const id = node.$tempId || node.$id;
1036
- const currentSchema = getCurrentSchema(schema, node);
1037
- const thingDbPath = currentSchema.defaultDBConnector?.path || node.$entity || node.$relation;
1038
- const { idFields } = currentSchema;
1039
- if (!idFields)
1040
- throw new Error("no idFields");
1041
- const idField = idFields[0];
1042
- const attributes = (0, import_radash7.listify)(node, (k, v) => {
1043
- if (k.startsWith("$") || k === idField || !v)
1044
- return "";
1045
- const currentDataField = currentSchema.dataFields?.find(
1046
- (x) => x.path === k
1047
- );
1048
- const fieldDbPath = currentDataField?.path;
1049
- if (!fieldDbPath) {
1050
- return ``;
1051
- }
1052
- const dbField = currentDataField.shared ? fieldDbPath : `${thingDbPath}\xB7${fieldDbPath}`;
1053
- if (["TEXT", "ID", "EMAIL"].includes(currentDataField.contentType)) {
1054
- return `has ${dbField} '${v}'`;
1055
- }
1056
- if (["NUMBER"].includes(currentDataField.contentType)) {
1057
- return `has ${dbField} ${v}`;
1058
- }
1059
- if (currentDataField.contentType === "DATE") {
1060
- if (Number.isNaN(v.valueOf())) {
1061
- throw new Error("Invalid format, Nan Date");
1062
- }
1063
- if (v instanceof Date) {
1064
- return `has ${dbField} ${v.toISOString().replace("Z", "")}`;
1065
- }
1066
- return `has ${dbField} ${new Date(v).toISOString().replace("Z", "")}`;
1067
- }
1068
- throw new Error(
1069
- `Unsupported contentType ${currentDataField.contentType}`
1070
- );
1071
- }).filter((x) => x);
1072
- const attributesVar = `$${id}-atts`;
1073
- const matchAttributes = (0, import_radash7.listify)(node, (k, v) => {
1074
- if (k.startsWith("$") || k === idField || !v)
1075
- return "";
1076
- const currentDataField = currentSchema.dataFields?.find(
1077
- (x) => x.path === k
1078
- );
1079
- const fieldDbPath = currentDataField?.path;
1080
- if (!fieldDbPath) {
1081
- return ``;
1082
- }
1083
- const dbField = currentDataField.shared ? fieldDbPath : `${thingDbPath}\xB7${fieldDbPath}`;
1084
- return `{${attributesVar} isa ${dbField};}`;
1085
- }).filter((x) => x);
1086
- const idFieldValue = node[idField] || node.$id;
1087
- const idDataField = currentSchema.dataFields?.find(
1088
- (x) => x.path === idField
1089
- );
1090
- const idDefaultValue = node.$op === "create" ? idDataField?.default?.value() : null;
1091
- const idValue = idFieldValue || idDefaultValue;
1092
- const idAttributes = idValue ? [`has ${idField} '${idValue}'`] : [];
1093
- const allAttributes = [...idAttributes, ...attributes].filter((x) => x).join(",");
1094
- const getDeletionMatch = () => {
1095
- if (node.$tempId)
1096
- return "";
1097
- if (op === "delete" || op === "unlink" || op === "noop") {
1098
- return `$${id} isa ${[thingDbPath, ...idAttributes].filter((x) => x).join(",")};`;
1099
- }
1100
- if (op === "update") {
1101
- if (!matchAttributes.length)
1102
- throw new Error("update without attributes");
1103
- return `$${id} isa ${thingDbPath}, ${idAttributes[0]}, has ${attributesVar};
1104
- ${matchAttributes.join(" or ")};
1105
- `;
1106
- }
1107
- return "";
1108
- };
1109
- const getInsertionMatch = () => {
1110
- if (node.$tempId)
1111
- return "";
1112
- if (op === "update" || op === "link" || op === "noop") {
1113
- return `$${id} isa ${[thingDbPath, ...idAttributes].filter((x) => x).join(",")};`;
1114
- }
1115
- return "";
1116
- };
1117
- if (node.$entity || node.$relation) {
1118
- return {
1119
- op,
1120
- deletionMatch: getDeletionMatch(),
1121
- insertionMatch: getInsertionMatch(),
1122
- insertion: op === "create" ? `$${id} isa ${[thingDbPath, allAttributes].filter((x) => x).join(",")};` : op === "update" && attributes.length ? `$${id} ${attributes.join(",")};` : "",
1123
- deletion: op === "delete" ? `$${id} isa ${thingDbPath};` : op === "update" && matchAttributes.length ? `$${id} has ${attributesVar};` : ""
1124
- };
1125
- }
1126
- throw new Error("in attributes");
1127
- };
1128
- const edgeToTypeQL = (node) => {
1129
- const op = node.$op;
1130
- const id = node.$tempId || node.$id;
1131
- const currentSchema = getCurrentSchema(schema, node);
1132
- const relationDbPath = currentSchema.defaultDBConnector?.path || node.$relation;
1133
- const roleFields = "roles" in currentSchema ? (0, import_radash7.listify)(currentSchema.roles, (k) => k) : [];
1134
- const roleDbPaths = node.$relation && "roles" in currentSchema && (0, import_radash7.mapEntries)(currentSchema.roles, (k, v) => [k, v.dbConnector?.path || k]);
1135
- const fromRoleFields = (0, import_radash7.listify)(node, (k, v) => {
1136
- if (!roleFields.includes(k))
1137
- return null;
1138
- if (!("roles" in currentSchema)) {
1139
- throw new Error("This should have roles! ");
1140
- }
1141
- const roleDbPath = roleDbPaths[k];
1142
- if (Array.isArray(v)) {
1143
- return v.map((x) => ({ path: roleDbPath, id: x }));
1144
- }
1145
- return { path: roleDbPath, id: v };
1146
- }).filter((x) => x).flat();
1147
- const fromRoleFieldsTql = fromRoleFields.map(
1148
- (x) => x ? `${x.path}: $${x.id}` : ""
1149
- );
1150
- const roles = fromRoleFields.length > 0 ? `( ${fromRoleFieldsTql.join(" , ")} )` : "";
1151
- const relationTql = !roles ? "" : `$${id} ${roles} ${node[Symbol.for("edgeType")] === "linkField" ? `isa ${relationDbPath}` : ""}`;
1152
- const getInsertions = () => {
1153
- if (!relationTql)
1154
- return "";
1155
- if (op === "link")
1156
- return `${relationTql};`;
1157
- if (op === "create")
1158
- return `${relationTql}, has id '${id}';`;
1159
- return "";
1160
- };
1161
- const getDeletions = () => {
1162
- if (!relationTql)
1163
- return "";
1164
- if (op === "unlink")
1165
- return `${relationTql};`;
1166
- return "";
1167
- };
1168
- return {
1169
- deletionMatch: "",
1170
- insertionMatch: "",
1171
- deletion: getDeletions(),
1172
- insertion: getInsertions(),
1173
- op: ""
1174
- };
1175
- };
1176
- const toTypeQL = (nodes, mode) => {
1177
- const typeQL = mode === "edges" ? edgeToTypeQL : nodeToTypeQL;
1178
- if (Array.isArray(nodes)) {
1179
- return nodes.map((x) => {
1180
- const { insertionMatch: insertionMatch2, deletionMatch: deletionMatch2, insertion: insertion2, deletion: deletion2 } = typeQL(x);
1181
- return (0, import_radash7.shake)(
1182
- { insertionMatch: insertionMatch2, deletionMatch: deletionMatch2, insertion: insertion2, deletion: deletion2 },
1183
- (z) => !z
1184
- );
1185
- }).filter((y) => y);
1186
- }
1187
- const { insertionMatch, deletionMatch, insertion, deletion } = typeQL(nodes);
1188
- return (0, import_radash7.shake)(
1189
- { insertionMatch, deletionMatch, insertion, deletion },
1190
- (z) => !z
1191
- );
1192
- };
1193
- const nodeOperations = toTypeQL(mutation.things);
1194
- const arrayNodeOperations = Array.isArray(nodeOperations) ? nodeOperations : [nodeOperations];
1195
- const edgeOperations = toTypeQL(mutation.edges, "edges");
1196
- const arrayEdgeOperations = Array.isArray(edgeOperations) ? edgeOperations : [edgeOperations];
1197
- const allOperations = [...arrayNodeOperations, ...arrayEdgeOperations];
1198
- const tqlRequest = (0, import_radash7.shake)(
1199
- {
1200
- insertionMatches: allOperations.map((x) => x.insertionMatch).join(" ").trim(),
1201
- deletionMatches: allOperations.map((x) => x.deletionMatch).join(" ").trim(),
1202
- insertions: allOperations.map((x) => x.insertion).join(" ").trim(),
1203
- deletions: allOperations.map((x) => x.deletion).join(" ").trim()
1204
- },
1205
- (x) => !x
1206
- );
1207
- req.tqlRequest = tqlRequest;
1208
- };
1209
-
1210
- // src/pipeline/preprocess/parseBQLMutation.ts
1211
- var import_essentials3 = __toESM(require_dist());
1212
- var import_immer3 = __toESM(require("immer"));
1213
- var import_object_traversal3 = require("object-traversal");
1214
- var import_radash8 = require("radash");
1215
- var import_uuid = require("uuid");
1216
- var parseBQLMutation = async (req) => {
1217
- const { rawBqlRequest, schema } = req;
1218
- const stringToObjects = (blocks) => {
1219
- return (0, import_immer3.default)(
1220
- blocks,
1221
- (draft) => (0, import_object_traversal3.traverse)(draft, ({ value: val, meta }) => {
1222
- if ((0, import_radash8.isObject)(val)) {
1223
- if (val.$arrayOp) {
1224
- throw new Error("Array op not supported yet");
1225
- }
1226
- const value = val;
1227
- const currentSchema = getCurrentSchema(schema, val);
1228
- if (!currentSchema) {
1229
- throw new Error(
1230
- `Schema not found for ${val.$entity || val.$relation}`
1231
- );
1232
- }
1233
- value[Symbol.for("thingType")] = currentSchema.thingType;
1234
- value[Symbol.for("schema")] = currentSchema;
1235
- value[Symbol.for("dbId")] = currentSchema.defaultDBConnector.id;
1236
- const { linkFields, roleFields } = getCurrentFields(currentSchema);
1237
- const currentPath = meta.nodePath;
1238
- [
1239
- ...linkFields.map((x) => ({ fieldType: "linkField", path: x })),
1240
- ...roleFields.map((x) => ({ fieldType: "roleField", path: x }))
1241
- ]?.forEach((currentField) => {
1242
- const currentLinkFieldSchema = currentSchema.linkFields?.find(
1243
- (x) => x.path === currentField.path
1244
- );
1245
- const currentValue = value[currentField.path];
1246
- if (currentValue === void 0)
1247
- return;
1248
- const currentRoleFieldSchema = "roles" in currentSchema ? (0, import_essentials3.oFind)(
1249
- currentSchema.roles,
1250
- ([k]) => k === currentField.path
1251
- ) : null;
1252
- const currentFieldSchema = currentLinkFieldSchema || currentRoleFieldSchema;
1253
- if (currentRoleFieldSchema && [...new Set(currentRoleFieldSchema.playedBy?.map((x) => x.thing))].length !== 1) {
1254
- throw new Error(
1255
- `Field: ${currentField.path} - If a role can be played by multiple things, you must specify the thing in the mutation: ${JSON.stringify(
1256
- currentRoleFieldSchema.playedBy
1257
- )}. Schema: ${JSON.stringify(currentFieldSchema)}`
1258
- );
1259
- }
1260
- const currentEdgeSchema = currentRoleFieldSchema?.playedBy ? currentRoleFieldSchema?.playedBy[0] : currentLinkFieldSchema;
1261
- const getCurrentRelation = () => {
1262
- if (currentFieldSchema && "relation" in currentFieldSchema && currentEdgeSchema?.relation === value.$relation) {
1263
- return "$self";
1264
- }
1265
- if (currentEdgeSchema?.relation) {
1266
- return currentEdgeSchema?.relation;
1267
- }
1268
- return "$self";
1269
- };
1270
- const relation = getCurrentRelation();
1271
- const relationSchema = relation === "$self" ? currentSchema : schema.relations[relation];
1272
- const currentFieldRole = (0, import_essentials3.oFind)(
1273
- relationSchema.roles,
1274
- ([k, _v]) => k === currentField.path
1275
- );
1276
- if (currentFieldRole?.playedBy.length === 0)
1277
- throw new Error(
1278
- `unused role: ${currentPath}.${currentField.path}`
1279
- );
1280
- if (!currentFieldSchema) {
1281
- throw new Error(`Field ${currentField.path} not found in schema`);
1282
- }
1283
- const oppositeFields = currentLinkFieldSchema?.oppositeLinkFieldsPlayedBy || currentRoleFieldSchema?.playedBy;
1284
- if (!oppositeFields) {
1285
- throw new Error(
1286
- `No opposite fields found for ${JSON.stringify(
1287
- currentFieldSchema
1288
- )}`
1289
- );
1290
- }
1291
- if ([...new Set(oppositeFields?.map((x) => x.thing))].length > 1)
1292
- throw new Error(
1293
- `Field: ${currentField.path} - If a role can be played by multiple things, you must specify the thing in the mutation: ${JSON.stringify(
1294
- oppositeFields
1295
- )}. Schema: ${JSON.stringify(currentFieldSchema)}`
1296
- );
1297
- if (currentValue === null) {
1298
- value[currentField.path] = { $op: "unlink" };
1299
- }
1300
- if (currentFieldSchema.cardinality === "ONE" && Array.isArray(currentValue)) {
1301
- throw new Error(
1302
- `Can't have an array in a cardinality === ONE link field`
1303
- );
1304
- }
1305
- if (currentValue.$entity || currentValue.$relation)
1306
- return;
1307
- const childrenLinkField = oppositeFields[0];
1308
- const childrenThingObj = {
1309
- [`$${childrenLinkField.thingType}`]: childrenLinkField.thing,
1310
- [Symbol.for("relation")]: relation,
1311
- [Symbol.for("edgeType")]: "plays" in currentFieldSchema ? "linkField" : "roleField",
1312
- [Symbol.for("parent")]: {
1313
- path: currentPath,
1314
- id: value.$id || value.$tempId,
1315
- links: oppositeFields
1316
- },
1317
- [Symbol.for("role")]: childrenLinkField.plays,
1318
- [Symbol.for("oppositeRole")]: "plays" in currentFieldSchema ? currentFieldSchema.plays : void 0
1319
- };
1320
- if ((0, import_radash8.isObject)(currentValue)) {
1321
- if (currentSchema.thingType === "relation" && currentValue.$tempId) {
1322
- value[currentField.path] = currentValue.$tempId;
1323
- } else {
1324
- value[currentField.path] = {
1325
- ...childrenThingObj,
1326
- ...currentValue
1327
- };
1328
- }
1329
- }
1330
- if (Array.isArray(currentValue) && currentValue.every((x) => (0, import_radash8.isObject)(x))) {
1331
- value[currentField.path] = currentValue.map((y) => ({
1332
- ...childrenThingObj,
1333
- ...y
1334
- }));
1335
- }
1336
- if (typeof currentValue === "string") {
1337
- value[currentField.path] = {
1338
- ...childrenThingObj,
1339
- $op: "link",
1340
- $id: currentValue
1341
- };
1342
- }
1343
- if (Array.isArray(currentValue) && currentValue.every((x) => typeof x === "string")) {
1344
- value[currentField.path] = currentValue.map((y) => ({
1345
- ...childrenThingObj,
1346
- $op: "link",
1347
- $id: y
1348
- }));
1349
- }
1350
- });
1351
- const nodePathArray = meta.nodePath?.split(".");
1352
- const notRoot = nodePathArray?.filter((x) => Number.isNaN(parseInt(x, 10))).join(".");
1353
- if (!notRoot && !value.$entity && !value.$relation) {
1354
- throw new Error("Root things must specify $entity or $relation");
1355
- }
1356
- if (!notRoot) {
1357
- }
1358
- }
1359
- })
1360
- );
1361
- };
1362
- const withObjects = stringToObjects(rawBqlRequest);
1363
- const fillBlocks = (blocks) => {
1364
- return (0, import_immer3.default)(
1365
- blocks,
1366
- (draft) => (0, import_object_traversal3.traverse)(
1367
- draft,
1368
- ({ parent, key, value: val, meta }) => {
1369
- if ((0, import_radash8.isObject)(val)) {
1370
- if (Object.keys(val).length === 0) {
1371
- throw new Error("Empty object!");
1372
- }
1373
- const value = val;
1374
- const nodePathArray = meta.nodePath?.split(".");
1375
- const notRoot = nodePathArray?.filter((x) => Number.isNaN(parseInt(x, 10))).join(".");
1376
- const currentSchema = getCurrentSchema(schema, value);
1377
- const { unidentifiedFields, dataFields, roleFields, linkFields } = getCurrentFields(currentSchema, value);
1378
- const hasUpdatedDataFields = Object.keys(value).some(
1379
- (x) => dataFields?.includes(x)
1380
- );
1381
- const hasUpdatedChildren = Object.keys(value).some(
1382
- (x) => [...roleFields, ...linkFields]?.includes(x)
1383
- );
1384
- const getOp = () => {
1385
- if (value.$op)
1386
- return value.$op;
1387
- if ((value.$id || value.$filter) && hasUpdatedDataFields)
1388
- return "update";
1389
- if ((value.$id || value.$filter) && notRoot && !hasUpdatedDataFields && !hasUpdatedChildren)
1390
- return "link";
1391
- if (!value.$filter && !value.$id)
1392
- return "create";
1393
- if ((value.$id || value.$filter) && !hasUpdatedDataFields && hasUpdatedChildren)
1394
- return "noop";
1395
- throw new Error("Wrong op");
1396
- };
1397
- if (!value.$op)
1398
- value.$op = getOp();
1399
- if (!parent)
1400
- value.$parentKey = "";
1401
- if (!(value.$id || value.$tempId || value.$filter) && ["delete", "link", "update", "unlink"].includes(value.$op)) {
1402
- throw new Error(
1403
- "Targeted operations (update, delete, link & unlink) require an $id or a $filter"
1404
- );
1405
- }
1406
- if (typeof parent === "object") {
1407
- const ArParent = Array.isArray(parent);
1408
- if (ArParent)
1409
- value[Symbol.for("index")] = key;
1410
- value[Symbol.for("path")] = meta.nodePath;
1411
- value[Symbol.for("isRoot")] = !notRoot;
1412
- value[Symbol.for("depth")] = notRoot?.split(".").length;
1413
- }
1414
- if (!value.$entity && !value.$relation) {
1415
- throw new Error(
1416
- `Node ${JSON.stringify(value)} without $entity/$relation`
1417
- );
1418
- }
1419
- const { idFields, computedFields } = currentSchema;
1420
- if (!idFields)
1421
- throw new Error("No idFields found");
1422
- const idField = idFields[0];
1423
- if (value[idField] && !value.$id) {
1424
- value.$id = value[idField];
1425
- }
1426
- const filledFields = (0, import_radash8.listify)(
1427
- value,
1428
- (attKey, v) => v ? attKey : void 0
1429
- );
1430
- const missingComputedFields = computedFields.filter(
1431
- (x) => !filledFields.includes(x)
1432
- );
1433
- missingComputedFields.forEach((fieldPath) => {
1434
- const currentFieldDef = currentSchema.dataFields?.find(
1435
- (x) => x.path === fieldPath
1436
- );
1437
- const currentLinkDef = currentSchema.linkFields?.find(
1438
- (x) => x.path === fieldPath
1439
- );
1440
- const currentLinkedDef = currentLinkDef?.oppositeLinkFieldsPlayedBy[0];
1441
- const currentRoleDef = "roles" in currentSchema ? (0, import_essentials3.oFind)(
1442
- currentSchema.roles,
1443
- ([k, _v]) => k === fieldPath
1444
- ) : void 0;
1445
- const currentDef = currentFieldDef || currentLinkedDef || currentRoleDef;
1446
- if (!currentDef) {
1447
- throw new Error(`no field Def for ${fieldPath}`);
1448
- }
1449
- if (fieldPath === idField && value.$op === "create" && !value[fieldPath]) {
1450
- const defaultValue = "default" in currentDef ? currentDef.default?.value() : void 0;
1451
- if (!defaultValue) {
1452
- throw new Error(`No default value for ${fieldPath}`);
1453
- }
1454
- value[fieldPath] = defaultValue;
1455
- value.$id = defaultValue;
1456
- }
1457
- });
1458
- if (unidentifiedFields.length > 0) {
1459
- throw new Error(
1460
- `Unknown fields: [${unidentifiedFields.join(
1461
- ","
1462
- )}] in ${JSON.stringify(value)}`
1463
- );
1464
- }
1465
- }
1466
- }
1467
- )
1468
- );
1469
- };
1470
- const filledBQLMutation = fillBlocks(withObjects);
1471
- const listNodes = (blocks) => {
1472
- const nodes = [];
1473
- const edges = [];
1474
- const listOp = ({ value }) => {
1475
- if (value.$entity || value.$relation) {
1476
- if (!value.$id && !["link", "unlink"].includes(value.$op)) {
1477
- throw new Error(
1478
- "An id must be specified either in the mutation or has tu have a default value in the schema"
1479
- );
1480
- }
1481
- const currentThingSchema = getCurrentSchema(schema, value);
1482
- const { dataFields: dataFieldPaths, roleFields: roleFieldPaths } = getCurrentFields(currentThingSchema);
1483
- const dataObj = {
1484
- ...value.$entity && { $entity: value.$entity },
1485
- ...value.$relation && { $relation: value.$relation },
1486
- ...value.$id && { $id: value.$id },
1487
- ...value.$tempId && { $tempId: value.$tempId },
1488
- ...(0, import_radash8.shake)((0, import_radash8.pick)(value, dataFieldPaths || [""])),
1489
- $op: value.$op,
1490
- [Symbol.for("dbId")]: currentThingSchema.defaultDBConnector.id,
1491
- [Symbol.for("isRoot")]: value[Symbol.for("isRoot")]
1492
- };
1493
- if (value.$op === "create" || value.$op === "update" || value.$op === "delete") {
1494
- nodes.push(dataObj);
1495
- } else {
1496
- nodes.push({ ...dataObj, $op: "noop" });
1497
- }
1498
- if (value[Symbol.for("relation")] && value[Symbol.for("edgeType")] === "linkField") {
1499
- if (value.$op === "link" || value.$op === "unlink") {
1500
- if (value.$id || value.$filter) {
1501
- if (value.$tempId) {
1502
- throw new Error(
1503
- "can't specify a existing and a new element at once. Use an id/filter or a tempId"
1504
- );
1505
- }
1506
- nodes.push({ ...value, $op: "noop" });
1507
- }
1508
- }
1509
- const ownRelation = value[Symbol.for("relation")] === value.$relation;
1510
- if (ownRelation && !(value.$id || value.$tempId)) {
1511
- throw new Error("No id or tempId found for complex link");
1512
- }
1513
- const linkTempId = ownRelation ? value.$id || value.$tempId : (0, import_uuid.v4)();
1514
- const parentMeta = value[Symbol.for("parent")];
1515
- const parentPath = parentMeta.path;
1516
- const parentNode = !parentPath ? blocks : (0, import_object_traversal3.getNodeByPath)(blocks, parentPath);
1517
- const parentId = parentNode.$id || parentNode.$tempId;
1518
- if (!parentId)
1519
- throw new Error("No parent id found");
1520
- if (value[Symbol.for("relation")] === "$self")
1521
- return;
1522
- const getLinkObjOp = () => {
1523
- if (value.$op === "unlink" || value.$op === "delete") {
1524
- if (ownRelation)
1525
- return "unlink";
1526
- return "delete";
1527
- }
1528
- if (value.$op === "link" || value.$op === "create") {
1529
- if (ownRelation)
1530
- return "link";
1531
- return "create";
1532
- }
1533
- return "noop";
1534
- };
1535
- const linkObj = {
1536
- $relation: value[Symbol.for("relation")],
1537
- $op: getLinkObjOp(),
1538
- ...value.$op === "unlink" ? { $tempId: linkTempId } : { $id: linkTempId },
1539
- [value[Symbol.for("role")]]: value.$tempId || value.$id,
1540
- [value[Symbol.for("oppositeRole")]]: parentId,
1541
- [Symbol.for("isRoot")]: false,
1542
- [Symbol.for("dbId")]: schema.relations[value[Symbol.for("relation")]].defaultDBConnector.id,
1543
- [Symbol.for("edgeType")]: "linkField"
1544
- };
1545
- edges.push(linkObj);
1546
- }
1547
- if (value.$relation) {
1548
- const val = value;
1549
- if (!val.$id && !["link", "unlink"].includes(value.$op)) {
1550
- throw new Error(
1551
- "An id must be specified either in the mutation or has tu have a default value in the schema"
1552
- );
1553
- }
1554
- const rolesObjFiltered = (0, import_essentials3.oFilter)(
1555
- val,
1556
- ([k, _v]) => roleFieldPaths.includes(k)
1557
- );
1558
- const rolesObjOnlyIds = (0, import_radash8.mapEntries)(rolesObjFiltered, (k, v) => {
1559
- return [k, v.$id || v];
1560
- });
1561
- const objWithMetaDataOnly = (0, import_essentials3.oFilter)(val, ([k, _v]) => {
1562
- return k.startsWith("$") || k.startsWith("Symbol");
1563
- });
1564
- if (Object.keys(rolesObjFiltered).filter((x) => !x.startsWith("$")).length > 0) {
1565
- if (val.$op === "create" || val.$op === "delete") {
1566
- const getEdgeOp = () => {
1567
- if (val.$op === "create")
1568
- return "link";
1569
- if (val.$op === "delete")
1570
- return "unlink";
1571
- throw new Error("Unsupported parent of edge op");
1572
- };
1573
- edges.push({
1574
- ...objWithMetaDataOnly,
1575
- $relation: val.$relation,
1576
- $op: getEdgeOp(),
1577
- ...rolesObjOnlyIds,
1578
- [Symbol.for("dbId")]: currentThingSchema.defaultDBConnector.id,
1579
- [Symbol.for("info")]: "coming from created or deleted relation"
1580
- });
1581
- return;
1582
- }
1583
- if (val.$op === "noop") {
1584
- const rolesWithLinks = (0, import_essentials3.oFilter)(
1585
- rolesObjOnlyIds,
1586
- ([_k, v]) => v.some(
1587
- (x) => x.$op === "link" || x.$op === "create"
1588
- )
1589
- );
1590
- const rolesWithLinksFiltered = (0, import_radash8.mapEntries)(
1591
- rolesWithLinks,
1592
- (k, v) => [
1593
- k,
1594
- v.filter(
1595
- (x) => x.$op === "link" || x.$op === "create"
1596
- ).map((y) => y.$id)
1597
- ]
1598
- );
1599
- const rolesWithUnlinks = (0, import_essentials3.oFilter)(
1600
- rolesObjOnlyIds,
1601
- ([_k, v]) => v.some(
1602
- (x) => x.$op === "unlink" || x.$op === "delete"
1603
- )
1604
- );
1605
- const rolesWithUnlinksFiltered = (0, import_radash8.mapEntries)(
1606
- rolesWithUnlinks,
1607
- (k, v) => [
1608
- k,
1609
- v.filter(
1610
- (x) => x.$op === "unlink" || x.$op === "delete"
1611
- ).map((y) => y.$id)
1612
- ]
1613
- );
1614
- const rolesWithReplaces = {};
1615
- [
1616
- { op: "link", obj: rolesWithLinksFiltered },
1617
- { op: "unlink", obj: rolesWithUnlinksFiltered },
1618
- { op: "replace", obj: rolesWithReplaces }
1619
- ].forEach((x) => {
1620
- if (Object.keys(x.obj).length) {
1621
- edges.push({
1622
- ...objWithMetaDataOnly,
1623
- $relation: val.$relation,
1624
- $op: x.op,
1625
- ...x.obj,
1626
- [Symbol.for("dbId")]: currentThingSchema.defaultDBConnector.id,
1627
- [Symbol.for("info")]: "updating roleFields"
1628
- });
1629
- }
1630
- });
1631
- }
1632
- }
1633
- }
1634
- }
1635
- };
1636
- (0, import_object_traversal3.traverse)(blocks, listOp);
1637
- return [nodes, edges];
1638
- };
1639
- const [parsedThings, parsedEdges] = listNodes(filledBQLMutation);
1640
- const mergedEdges = parsedEdges.reduce((acc, curr) => {
1641
- const existingEdge = acc.find(
1642
- (r) => r.$id === curr.$id && r.$relation === curr.$relation
1643
- );
1644
- if (existingEdge) {
1645
- const newRelation = {
1646
- ...existingEdge,
1647
- ...curr
1648
- };
1649
- const newAcc = acc.filter(
1650
- (r) => r.$id !== curr.$id || r.$relation !== curr.$relation
1651
- );
1652
- return [...newAcc, newRelation];
1653
- }
1654
- return [...acc, curr];
1655
- }, []);
1656
- req.bqlRequest = {
1657
- mutation: {
1658
- things: parsedThings,
1659
- edges: mergedEdges
1660
- }
1661
- };
1662
- };
1663
-
1664
- // src/pipeline/transaction/runTQLMutation.ts
1665
- var import_typedb_client2 = require("typedb-client");
1666
- var runTQLMutation = async (req, res) => {
1667
- const { dbHandles, tqlRequest, bqlRequest, config } = req;
1668
- if (!tqlRequest) {
1669
- throw new Error("TQL request not built");
1670
- }
1671
- if (!(tqlRequest.deletions && tqlRequest.deletionMatches || tqlRequest.insertions)) {
1672
- throw new Error("TQL request error, no things");
1673
- }
1674
- if (!bqlRequest?.mutation) {
1675
- throw new Error("BQL mutation not parsed");
1676
- }
1677
- const singleHandlerV0 = config.dbConnectors[0].id;
1678
- const session = dbHandles.typeDB.get(singleHandlerV0)?.session;
1679
- if (!session?.isOpen()) {
1680
- throw new Error("Session is closed");
1681
- }
1682
- const mutateTransaction = await session.transaction(import_typedb_client2.TransactionType.WRITE);
1683
- if (!mutateTransaction) {
1684
- throw new Error("Can't create transaction");
1685
- }
1686
- const tqlDeletion = tqlRequest.deletionMatches && tqlRequest.deletions && `match ${tqlRequest.deletionMatches} delete ${tqlRequest.deletions}`;
1687
- const tqlInsertion = tqlRequest.insertions && `${tqlRequest.insertionMatches ? `match ${tqlRequest.insertionMatches}` : ""} insert ${tqlRequest.insertions}`;
1688
- if (tqlDeletion)
1689
- mutateTransaction.query.delete(tqlDeletion);
1690
- const insertionsStream = tqlInsertion && mutateTransaction.query.insert(tqlInsertion);
1691
- const insertionsRes = insertionsStream ? await insertionsStream.collect() : void 0;
1692
- await mutateTransaction.commit();
1693
- await mutateTransaction.close();
1694
- res.rawTqlRes = { insertions: insertionsRes };
1695
- };
1696
-
1697
- // src/pipeline/pipeline.ts
1698
- var Pipelines = {
1699
- query: [
1700
- parseBQLQuery,
1701
- buildTQLQuery,
1702
- runTQLQuery,
1703
- parseTQLRes,
1704
- dispatchPipeline
1705
- ],
1706
- mutation: [parseBQLMutation, buildTQLMutation, runTQLMutation, parseTQLRes]
1707
- };
1708
- var finalPipeline = [buildBQLTree];
1709
- var runPipeline = async (pipeline, req, res = {}, root = true) => {
1710
- for (const operation of pipeline) {
1711
- const next = await operation(req, res);
1712
- if (next && Array.isArray(next)) {
1713
- for (const nextPipeline of next) {
1714
- await runPipeline(
1715
- nextPipeline.pipeline,
1716
- nextPipeline.req,
1717
- nextPipeline.res,
1718
- false
1719
- );
1720
- }
1721
- }
1722
- }
1723
- if (root) {
1724
- await runPipeline(finalPipeline, req, res, false);
1725
- return res.bqlRes;
1726
- }
1727
- };
1728
- var queryPipeline = (bqlRequest, bormConfig, bormSchema, dbHandles) => runPipeline(
1729
- Pipelines.query,
1730
- {
1731
- config: bormConfig,
1732
- schema: bormSchema,
1733
- rawBqlRequest: bqlRequest,
1734
- dbHandles
1735
- },
1736
- {}
1737
- );
1738
- var mutationPipeline = (bqlRequest, bormConfig, bormSchema, dbHandles) => runPipeline(
1739
- Pipelines.mutation,
1740
- {
1741
- config: bormConfig,
1742
- schema: bormSchema,
1743
- rawBqlRequest: bqlRequest,
1744
- dbHandles
1745
- },
1746
- {}
1747
- );
1748
-
1749
- // src/index.ts
1750
- var BormClient = class {
1751
- schema;
1752
- config;
1753
- dbHandles;
1754
- constructor({ schema, config }) {
1755
- this.schema = schema;
1756
- this.config = config;
1757
- }
1758
- init = async () => {
1759
- const dbHandles = { typeDB: /* @__PURE__ */ new Map() };
1760
- const enrichedSchema = enrichSchema(this.schema);
1761
- await Promise.all(
1762
- this.config.dbConnectors.map(async (dbc) => {
1763
- if (dbc.provider === "typeDB" && dbc.dbName) {
1764
- const [clientErr, client] = await (0, import_radash9.tryit)(import_typedb_client3.TypeDB.coreClient)(dbc.url);
1765
- if (clientErr) {
1766
- const message = `[BORM:${dbc.provider}:${dbc.dbName}] ${clientErr.message ?? "Can't create TypeDB Client"}`;
1767
- throw new Error(message);
1768
- }
1769
- try {
1770
- const session = await client.session(dbc.dbName, import_typedb_client3.SessionType.DATA);
1771
- dbHandles.typeDB.set(dbc.id, { client, session });
1772
- } catch (sessionErr) {
1773
- const message = `[BORM:${dbc.provider}:${dbc.dbName}] ${(sessionErr.messageTemplate?._messageBody() || sessionErr.message) ?? "Can't create TypeDB Session"}`;
1774
- throw new Error(message);
1775
- }
1776
- }
1777
- })
1778
- );
1779
- this.schema = enrichedSchema;
1780
- this.dbHandles = dbHandles;
1781
- };
1782
- #enforceConnection = async () => {
1783
- if (!this.dbHandles) {
1784
- await this.init();
1785
- if (!this.dbHandles) {
1786
- throw new Error("Can't init BormClient");
1787
- }
1788
- }
1789
- };
1790
- introspect = async () => {
1791
- await this.#enforceConnection();
1792
- return this.schema;
1793
- };
1794
- query = async (query, queryConfig) => {
1795
- await this.#enforceConnection();
1796
- const qConfig = {
1797
- ...this.config,
1798
- query: { ...defaultConfig.query, ...this.config.query, ...queryConfig }
1799
- };
1800
- return queryPipeline(query, qConfig, this.schema, this.dbHandles);
1801
- };
1802
- mutate = async (mutation, mutationConfig) => {
1803
- await this.#enforceConnection();
1804
- const mConfig = {
1805
- ...this.config,
1806
- mutation: {
1807
- ...defaultConfig.mutation,
1808
- ...this.config.mutation,
1809
- ...mutationConfig
1810
- }
1811
- };
1812
- return mutationPipeline(mutation, mConfig, this.schema, this.dbHandles);
1813
- };
1814
- close = async () => {
1815
- if (!this.dbHandles) {
1816
- return;
1817
- }
1818
- this.dbHandles.typeDB.forEach(async ({ client, session }) => {
1819
- console.log("Closing session");
1820
- await session.close();
1821
- console.log("Closing client");
1822
- await client.close();
1823
- });
1824
- };
1825
- };
1826
- var src_default = BormClient;
1827
- // Annotate the CommonJS export names for ESM import in node:
1828
- 0 && (module.exports = {});