industrial-model 0.1.0

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 ADDED
@@ -0,0 +1,738 @@
1
+ // src/cognite/adapter.ts
2
+ function createCogniteAdapter(client) {
3
+ return new CogniteSdkAdapter(client);
4
+ }
5
+ var CogniteSdkAdapter = class {
6
+ constructor(client) {
7
+ this.client = client;
8
+ }
9
+ async retrieveDataModels(ids, options) {
10
+ const response = await this.client.dataModels.retrieve(ids, options);
11
+ return {
12
+ items: response.items.map((item) => ({
13
+ createdTime: item.createdTime,
14
+ views: item.views ?? []
15
+ }))
16
+ };
17
+ }
18
+ async queryInstances(request) {
19
+ const response = await this.client.instances.query(
20
+ request
21
+ );
22
+ return {
23
+ items: response.items,
24
+ nextCursor: response.nextCursor
25
+ };
26
+ }
27
+ };
28
+
29
+ // src/constants.ts
30
+ var NESTED_SEP = "|";
31
+ var EDGE_MARKER = "<EdgeMarker>";
32
+ var MAX_LIMIT = 1e4;
33
+ var DEFAULT_LIMIT = 1e3;
34
+ var MAX_DEPENDENCY_DEPTH = 3;
35
+
36
+ // src/mappers/utils.ts
37
+ var NODE_PROPERTIES = /* @__PURE__ */ new Set([
38
+ "externalId",
39
+ "space",
40
+ "createdTime",
41
+ "deletedTime",
42
+ "lastUpdatedTime"
43
+ ]);
44
+ function getPropertyRef(property, view, instanceType = "node") {
45
+ if (NODE_PROPERTIES.has(property)) return [instanceType, property];
46
+ return [view.space, `${view.externalId}/${view.version}`, property];
47
+ }
48
+ function toViewReference(view) {
49
+ return { type: "view", space: view.space, externalId: view.externalId, version: view.version };
50
+ }
51
+ function isViewPropertyDefinition(p) {
52
+ return "container" in p;
53
+ }
54
+ function isReverseDirectRelation(p) {
55
+ return "through" in p;
56
+ }
57
+ function isEdgeConnection(p) {
58
+ return !isViewPropertyDefinition(p) && !isReverseDirectRelation(p) && "source" in p;
59
+ }
60
+ function getDirectRelationSource(p) {
61
+ const type = p.type;
62
+ if (type.type === "direct" && type.source) return type.source;
63
+ return void 0;
64
+ }
65
+ function isDirectRelationWithSource(p) {
66
+ if (!isViewPropertyDefinition(p)) return false;
67
+ return getDirectRelationSource(p) !== void 0;
68
+ }
69
+ function isListDirectRelation(p) {
70
+ return p.type.list === true;
71
+ }
72
+ function buildSelect(source, properties) {
73
+ if (properties.length === 0) return {};
74
+ return { sources: [{ source, properties }] };
75
+ }
76
+
77
+ // src/mappers/filter-mapper.ts
78
+ var LEAF_OPS = /* @__PURE__ */ new Set([
79
+ "eq",
80
+ "in",
81
+ "gt",
82
+ "gte",
83
+ "lt",
84
+ "lte",
85
+ "exists",
86
+ "prefix",
87
+ "containsAny",
88
+ "containsAll"
89
+ ]);
90
+ function isLeafFilter(value) {
91
+ return Object.keys(value).some((k) => LEAF_OPS.has(k));
92
+ }
93
+ var FilterMapper = class {
94
+ constructor(viewMapper) {
95
+ this.viewMapper = viewMapper;
96
+ }
97
+ async map(input, rootView) {
98
+ const result = [];
99
+ for (const [key, value] of Object.entries(input)) {
100
+ if (value == null) continue;
101
+ if (key === "AND") {
102
+ const clauses = Array.isArray(value) ? value : [value];
103
+ const inner = await Promise.all(clauses.map((c) => this.whereInputToSingle(c, rootView)));
104
+ result.push({ and: inner });
105
+ } else if (key === "OR") {
106
+ const clauses = value;
107
+ const branches = await Promise.all(
108
+ clauses.map((c) => this.whereInputToSingle(c, rootView))
109
+ );
110
+ result.push({ or: branches });
111
+ } else if (key === "NOT") {
112
+ const clauses = Array.isArray(value) ? value : [value];
113
+ const [firstClause, ...restClauses] = clauses;
114
+ const combined = restClauses.length === 0 && firstClause !== void 0 ? firstClause : { AND: clauses };
115
+ result.push({ not: await this.whereInputToSingle(combined, rootView) });
116
+ } else {
117
+ const filterValue = value;
118
+ const property = getPropertyRef(key, rootView);
119
+ if (isLeafFilter(filterValue)) {
120
+ result.push(...this.leafToFilterDefs(property, filterValue));
121
+ } else {
122
+ const targetView = await this.getNestedTargetView(key, rootView);
123
+ const innerFilter = await this.whereInputToSingle(filterValue, targetView);
124
+ result.push({ nested: { scope: property, filter: innerFilter } });
125
+ }
126
+ }
127
+ }
128
+ return result;
129
+ }
130
+ async whereInputToSingle(input, rootView) {
131
+ const filters = await this.map(input, rootView);
132
+ const [firstFilter, ...restFilters] = filters;
133
+ if (restFilters.length === 0 && firstFilter !== void 0) {
134
+ return firstFilter;
135
+ }
136
+ return { and: filters };
137
+ }
138
+ leafToFilterDefs(property, filter) {
139
+ const result = [];
140
+ if ("eq" in filter && filter.eq !== void 0) {
141
+ result.push({
142
+ equals: { property, value: this.coerceValue(filter.eq) }
143
+ });
144
+ }
145
+ if ("in" in filter && filter.in !== void 0) {
146
+ result.push({
147
+ in: { property, values: this.coerceValue(filter.in) }
148
+ });
149
+ }
150
+ if ("gt" in filter && filter.gt !== void 0) {
151
+ result.push({ range: { property, gt: this.coerceValue(filter.gt) } });
152
+ }
153
+ if ("gte" in filter && filter.gte !== void 0) {
154
+ result.push({ range: { property, gte: this.coerceValue(filter.gte) } });
155
+ }
156
+ if ("lt" in filter && filter.lt !== void 0) {
157
+ result.push({ range: { property, lt: this.coerceValue(filter.lt) } });
158
+ }
159
+ if ("lte" in filter && filter.lte !== void 0) {
160
+ result.push({ range: { property, lte: this.coerceValue(filter.lte) } });
161
+ }
162
+ if ("exists" in filter) {
163
+ if (filter.exists === true) {
164
+ result.push({ exists: { property } });
165
+ } else if (filter.exists === false) {
166
+ result.push({ not: { exists: { property } } });
167
+ }
168
+ }
169
+ if ("prefix" in filter && filter.prefix !== void 0) {
170
+ result.push({ prefix: { property, value: this.coerceValue(filter.prefix) } });
171
+ }
172
+ if ("containsAll" in filter && filter.containsAll !== void 0) {
173
+ result.push({
174
+ containsAll: {
175
+ property,
176
+ values: this.coerceValue(filter.containsAll)
177
+ }
178
+ });
179
+ }
180
+ if ("containsAny" in filter && filter.containsAny !== void 0) {
181
+ result.push({
182
+ containsAny: {
183
+ property,
184
+ values: this.coerceValue(filter.containsAny)
185
+ }
186
+ });
187
+ }
188
+ return result;
189
+ }
190
+ async getNestedTargetView(property, rootView) {
191
+ const viewProp = rootView.properties[property];
192
+ if (!viewProp || !isViewPropertyDefinition(viewProp)) {
193
+ throw new Error(`Property "${property}" is not a mapped property`);
194
+ }
195
+ const source = getDirectRelationSource(viewProp);
196
+ if (!source) throw new Error(`Property "${property}" has no relation source`);
197
+ return this.viewMapper.getView(source.externalId);
198
+ }
199
+ coerceValue(value) {
200
+ if (value instanceof Date) return value.toISOString();
201
+ if (Array.isArray(value)) return value.map((v) => this.coerceValue(v));
202
+ return value;
203
+ }
204
+ };
205
+
206
+ // src/mappers/sort-mapper.ts
207
+ var SortMapper = class {
208
+ map(sortClauses, rootView) {
209
+ return Object.entries(sortClauses).map(([property, direction]) => ({
210
+ property: getPropertyRef(property, rootView),
211
+ direction,
212
+ nullsFirst: this.isNullsFirst(property, rootView, direction)
213
+ }));
214
+ }
215
+ isNullsFirst(property, view, direction) {
216
+ const prop = view.properties[property];
217
+ if (prop && isDirectRelationWithSource(prop)) {
218
+ return direction === "ascending";
219
+ }
220
+ return direction === "descending";
221
+ }
222
+ };
223
+
224
+ // src/mappers/query-mapper.ts
225
+ var QueryMapper = class {
226
+ constructor(viewMapper) {
227
+ this.viewMapper = viewMapper;
228
+ this.filterMapper = new FilterMapper(viewMapper);
229
+ this.sortMapper = new SortMapper();
230
+ }
231
+ async map(options) {
232
+ const {
233
+ viewExternalId,
234
+ select = { _all: true },
235
+ filters,
236
+ sortClauses = {},
237
+ limit: requestedLimit = DEFAULT_LIMIT,
238
+ cursor = null
239
+ } = options;
240
+ const limit = requestedLimit === -1 ? DEFAULT_LIMIT : requestedLimit;
241
+ const rootView = await this.viewMapper.getView(viewExternalId);
242
+ const rootViewRef = toViewReference(rootView);
243
+ const whereFilters = filters ? await this.filterMapper.map(filters, rootView) : [];
244
+ const baseFilters = [{ hasData: [rootViewRef] }, ...whereFilters];
245
+ const withExprs = {
246
+ [viewExternalId]: {
247
+ nodes: {
248
+ filter: { and: baseFilters }
249
+ },
250
+ sort: this.sortMapper.map(sortClauses, rootView),
251
+ limit
252
+ }
253
+ };
254
+ const selectExprs = {};
255
+ const properties = await this.includeStatements(
256
+ viewExternalId,
257
+ rootView,
258
+ select,
259
+ withExprs,
260
+ selectExprs
261
+ );
262
+ selectExprs[viewExternalId] = buildSelect(rootViewRef, properties);
263
+ const cursors = {};
264
+ if (cursor != null) cursors[viewExternalId] = cursor;
265
+ return { with: withExprs, select: selectExprs, cursors };
266
+ }
267
+ async includeStatements(key, view, select, withExprs, selectExprs) {
268
+ const selectProperties = [];
269
+ const selectRecord = select;
270
+ for (const [propertyName, property] of Object.entries(view.properties)) {
271
+ const propertyKey = `${key}${NESTED_SEP}${propertyName}`;
272
+ const canIncludeProperty = select._all === true || propertyName in select;
273
+ if (!canIncludeProperty) {
274
+ continue;
275
+ }
276
+ const relationToInclude = propertyName in select && selectRecord[propertyName] != null && typeof selectRecord[propertyName] === "object" ? selectRecord[propertyName] : null;
277
+ if (isViewPropertyDefinition(property)) {
278
+ const relSource = getDirectRelationSource(property);
279
+ if (!relSource) {
280
+ selectProperties.push(propertyName);
281
+ } else {
282
+ selectProperties.push(propertyName);
283
+ const nestedView = await this.viewMapper.getView(relSource.externalId);
284
+ const props = relationToInclude != null ? await this.includeStatements(
285
+ propertyKey,
286
+ nestedView,
287
+ relationToInclude,
288
+ withExprs,
289
+ selectExprs
290
+ ) : [];
291
+ if (props.length > 0) {
292
+ withExprs[propertyKey] = {
293
+ nodes: {
294
+ from: key,
295
+ direction: "outwards",
296
+ through: { view: toViewReference(view), identifier: propertyName }
297
+ },
298
+ limit: MAX_LIMIT
299
+ };
300
+ selectExprs[propertyKey] = buildSelect(relSource, props);
301
+ }
302
+ }
303
+ } else if (isReverseDirectRelation(property) && relationToInclude != null) {
304
+ const nestedView = await this.viewMapper.getView(property.source.externalId);
305
+ const props = await this.includeStatements(
306
+ propertyKey,
307
+ nestedView,
308
+ relationToInclude,
309
+ withExprs,
310
+ selectExprs
311
+ );
312
+ if (!props.includes(property.through.identifier)) {
313
+ props.push(property.through.identifier);
314
+ }
315
+ withExprs[propertyKey] = {
316
+ nodes: {
317
+ from: key,
318
+ direction: "inwards",
319
+ through: {
320
+ source: property.through.source,
321
+ identifier: property.through.identifier
322
+ }
323
+ },
324
+ limit: MAX_LIMIT
325
+ };
326
+ selectExprs[propertyKey] = buildSelect(property.source, props);
327
+ } else if (isEdgeConnection(property) && relationToInclude != null) {
328
+ const edgePropertyKey = `${propertyKey}${NESTED_SEP}${EDGE_MARKER}`;
329
+ withExprs[edgePropertyKey] = {
330
+ edges: {
331
+ from: key,
332
+ maxDistance: 1,
333
+ filter: {
334
+ equals: { property: ["edge", "type"], value: property.type }
335
+ },
336
+ direction: property.direction ?? "outwards"
337
+ },
338
+ limit: MAX_LIMIT
339
+ };
340
+ withExprs[propertyKey] = {
341
+ nodes: { from: edgePropertyKey },
342
+ limit: MAX_LIMIT
343
+ };
344
+ selectExprs[edgePropertyKey] = {};
345
+ const nestedView = await this.viewMapper.getView(property.source.externalId);
346
+ const props = await this.includeStatements(
347
+ propertyKey,
348
+ nestedView,
349
+ relationToInclude,
350
+ withExprs,
351
+ selectExprs
352
+ );
353
+ selectExprs[propertyKey] = buildSelect(property.source, props);
354
+ }
355
+ }
356
+ return selectProperties;
357
+ }
358
+ };
359
+
360
+ // src/mappers/result-mapper.ts
361
+ function nodeInstanceId(node) {
362
+ return `${node.space}:${node.externalId}`;
363
+ }
364
+ function getElementKeys(node, element) {
365
+ if (element && typeof element === "object" && !Array.isArray(element)) {
366
+ const ref = element;
367
+ return [`${ref.space ?? ""}:${ref.externalId ?? ""}`];
368
+ }
369
+ if (Array.isArray(element)) {
370
+ return element.filter((item) => item && typeof item === "object").map((item) => {
371
+ const ref = item;
372
+ return `${ref.space ?? ""}:${ref.externalId ?? ""}`;
373
+ });
374
+ }
375
+ return [nodeInstanceId(node)];
376
+ }
377
+ var QueryResultMapper = class {
378
+ constructor(viewMapper) {
379
+ this.viewMapper = viewMapper;
380
+ }
381
+ async mapNodes(rootNode, queryResult) {
382
+ if (!(rootNode in queryResult)) {
383
+ throw new Error(`"${rootNode}" is not available in the query result`);
384
+ }
385
+ const rootView = await this.viewMapper.getView(rootNode);
386
+ const values = await this.mapNodeProperty(rootNode, rootView, queryResult);
387
+ if (!values) return [];
388
+ return [...values.values()].flatMap((nodes) => nodes.map((n) => this.nodeToDict(n)));
389
+ }
390
+ async mapNodeProperty(key, view, queryResult, resultPropertyKey) {
391
+ if (!(key in queryResult)) return null;
392
+ const mappings = await this.getPropertyMappings(key, view, queryResult);
393
+ const viewKey = `${view.externalId}/${view.version}`;
394
+ const visited = /* @__PURE__ */ new Set();
395
+ const result = /* @__PURE__ */ new Map();
396
+ for (const item of queryResult[key] ?? []) {
397
+ if (item.instanceType !== "node") continue;
398
+ const node = item;
399
+ const id = nodeInstanceId(node);
400
+ if (visited.has(id)) continue;
401
+ visited.add(id);
402
+ const spaceProps = node.properties?.[view.space];
403
+ if (!spaceProps || !(viewKey in spaceProps)) continue;
404
+ const properties = { ...spaceProps[viewKey] ?? {} };
405
+ const getResultId = () => {
406
+ if (!resultPropertyKey) return id;
407
+ const entry = properties[resultPropertyKey];
408
+ if (!entry || typeof entry !== "object") {
409
+ throw new Error(`Invalid result property key "${resultPropertyKey}"`);
410
+ }
411
+ const ref = entry;
412
+ return `${ref.space ?? ""}:${ref.externalId ?? ""}`;
413
+ };
414
+ const edgesMapping = {};
415
+ const resultId = getResultId();
416
+ for (const [mappingKey, mapping] of Object.entries(mappings)) {
417
+ const element = properties[mappingKey];
418
+ const { isList, connectionType, nodes: mappingNodes, edges: mappingEdges } = mapping;
419
+ if (element === void 0 && connectionType === "DirectRelation") continue;
420
+ const elementKeys = getElementKeys(node, element);
421
+ const nodeEntries = elementKeys.flatMap((k) => mappingNodes.get(k) ?? []);
422
+ if (nodeEntries.length === 0) {
423
+ delete properties[mappingKey];
424
+ continue;
425
+ }
426
+ const entryData = nodeEntries.map((n) => this.nodeToDict(n));
427
+ properties[mappingKey] = isList ? entryData : entryData[0];
428
+ const edgeEntries = elementKeys.flatMap((k) => mappingEdges.get(k) ?? []);
429
+ if (edgeEntries.length > 0) edgesMapping[mappingKey] = edgeEntries;
430
+ }
431
+ properties._edges = edgesMapping;
432
+ if (node.properties?.[view.space]) {
433
+ node.properties[view.space] = {
434
+ ...node.properties[view.space],
435
+ [viewKey]: properties
436
+ };
437
+ }
438
+ const existing = result.get(resultId);
439
+ if (existing) {
440
+ existing.push(node);
441
+ } else {
442
+ result.set(resultId, [node]);
443
+ }
444
+ }
445
+ return result;
446
+ }
447
+ async getPropertyMappings(key, view, queryResult) {
448
+ const mappings = {};
449
+ for (const [propertyName, property] of Object.entries(view.properties)) {
450
+ const propertyKey = `${key}${NESTED_SEP}${propertyName}`;
451
+ let nodes = null;
452
+ let edges = /* @__PURE__ */ new Map();
453
+ let isList = false;
454
+ let connectionType = "DirectRelation";
455
+ if (isViewPropertyDefinition(property)) {
456
+ const source = getDirectRelationSource(property);
457
+ if (source) {
458
+ const nestedView = await this.viewMapper.getView(source.externalId);
459
+ nodes = await this.mapNodeProperty(propertyKey, nestedView, queryResult);
460
+ isList = isListDirectRelation(property);
461
+ connectionType = "DirectRelation";
462
+ }
463
+ } else if (isReverseDirectRelation(property)) {
464
+ const rel = property;
465
+ const nestedView = await this.viewMapper.getView(rel.source.externalId);
466
+ nodes = await this.mapNodeProperty(
467
+ propertyKey,
468
+ nestedView,
469
+ queryResult,
470
+ rel.through.identifier
471
+ );
472
+ isList = rel.connectionType === "multi_reverse_direct_relation" || rel.targetsList === true;
473
+ connectionType = "ReverseDirectRelation";
474
+ } else if (isEdgeConnection(property)) {
475
+ const nestedView = await this.viewMapper.getView(property.source.externalId);
476
+ const [edgeNodes, edgeEdges] = await this.mapEdgeProperty(
477
+ propertyKey,
478
+ nestedView,
479
+ queryResult,
480
+ property.direction ?? "outwards"
481
+ );
482
+ nodes = edgeNodes;
483
+ edges = edgeEdges ?? /* @__PURE__ */ new Map();
484
+ isList = true;
485
+ connectionType = "Edge";
486
+ }
487
+ if (nodes !== null) {
488
+ mappings[propertyName] = { isList, connectionType, nodes, edges };
489
+ }
490
+ }
491
+ return mappings;
492
+ }
493
+ async mapEdgeProperty(key, view, queryResult, edgeDirection) {
494
+ const edgeKey = `${key}${NESTED_SEP}${EDGE_MARKER}`;
495
+ if (!(key in queryResult) || !(edgeKey in queryResult)) return [null, null];
496
+ const nodes = await this.mapNodeProperty(key, view, queryResult);
497
+ if (!nodes) return [null, null];
498
+ const visitedEdges = /* @__PURE__ */ new Set();
499
+ const nodesResult = /* @__PURE__ */ new Map();
500
+ const edgesResult = /* @__PURE__ */ new Map();
501
+ for (const item of queryResult[edgeKey] ?? []) {
502
+ if (item.instanceType !== "edge") continue;
503
+ const edge = item;
504
+ const edgeId = `${edge.space}:${edge.externalId}`;
505
+ if (visitedEdges.has(edgeId)) continue;
506
+ visitedEdges.add(edgeId);
507
+ const entryKey = edgeDirection === "inwards" ? `${edge.endNode.space}:${edge.endNode.externalId}` : `${edge.startNode.space}:${edge.startNode.externalId}`;
508
+ const nodeKey = edgeDirection === "inwards" ? `${edge.startNode.space}:${edge.startNode.externalId}` : `${edge.endNode.space}:${edge.endNode.externalId}`;
509
+ const existingEdges = edgesResult.get(entryKey);
510
+ if (existingEdges) existingEdges.push(edge);
511
+ else edgesResult.set(entryKey, [edge]);
512
+ const relatedNodes = nodes.get(nodeKey);
513
+ if (relatedNodes) {
514
+ const existingNodes = nodesResult.get(entryKey);
515
+ if (existingNodes) existingNodes.push(...relatedNodes);
516
+ else nodesResult.set(entryKey, relatedNodes.slice());
517
+ }
518
+ }
519
+ return [nodesResult, edgesResult];
520
+ }
521
+ nodeToDict(node) {
522
+ const { properties, ...rest } = node;
523
+ const entry = { ...rest };
524
+ for (const spaceProp of Object.values(properties ?? {})) {
525
+ for (const viewProp of Object.values(spaceProp)) {
526
+ Object.assign(entry, viewProp);
527
+ }
528
+ }
529
+ return entry;
530
+ }
531
+ };
532
+
533
+ // src/mappers/view-mapper.ts
534
+ var ViewMapper = class {
535
+ constructor(cognite, dataModelId) {
536
+ this.cognite = cognite;
537
+ this.dataModelId = dataModelId;
538
+ this.cachePromise = null;
539
+ }
540
+ async getView(externalId) {
541
+ const views = await this.loadViews();
542
+ const view = views.get(externalId);
543
+ if (!view) {
544
+ throw new Error(
545
+ `View "${externalId}" not found in data model "${this.dataModelId.externalId}"`
546
+ );
547
+ }
548
+ return view;
549
+ }
550
+ loadViews() {
551
+ if (this.cachePromise == null) {
552
+ this.cachePromise = this.fetchViews();
553
+ }
554
+ return this.cachePromise;
555
+ }
556
+ async fetchViews() {
557
+ const response = await this.cognite.retrieveDataModels(
558
+ [
559
+ {
560
+ space: this.dataModelId.space,
561
+ externalId: this.dataModelId.externalId,
562
+ version: this.dataModelId.version
563
+ }
564
+ ],
565
+ { inlineViews: true }
566
+ );
567
+ const dm = response.items.sort((a, b) => b.createdTime - a.createdTime)[0];
568
+ if (!dm) {
569
+ throw new Error(`Data model "${this.dataModelId.externalId}" not found`);
570
+ }
571
+ const views = /* @__PURE__ */ new Map();
572
+ for (const view of dm.views ?? []) {
573
+ views.set(view.externalId, view);
574
+ }
575
+ return views;
576
+ }
577
+ };
578
+
579
+ // src/utils/query.ts
580
+ function mapNodesAndEdges(queryResult, _query) {
581
+ return queryResult.items;
582
+ }
583
+ function appendNodesAndEdges(initial, additional) {
584
+ if (!additional) return initial;
585
+ for (const [key, items] of Object.entries(additional)) {
586
+ const existing = initial[key];
587
+ if (existing) {
588
+ existing.push(...items);
589
+ } else {
590
+ initial[key] = [...items];
591
+ }
592
+ }
593
+ return initial;
594
+ }
595
+ function getQueryForDependenciesPagination(query, queryResult, viewExternalId) {
596
+ const cursorKeys = new Set(Object.keys(queryResult.nextCursor));
597
+ const { nodesParent, nodesChildren } = getParentAndChildrenNodes(cursorKeys);
598
+ const leafCursors = getLeafCursors(queryResult, viewExternalId, nodesParent, nodesChildren);
599
+ if (Object.keys(leafCursors).length === 0) {
600
+ return null;
601
+ }
602
+ return buildDependenciesQuery(query, nodesParent, nodesChildren, leafCursors);
603
+ }
604
+ function getParentAndChildrenNodes(keys) {
605
+ const nodesParent = /* @__PURE__ */ new Map();
606
+ const nodesChildren = /* @__PURE__ */ new Map();
607
+ for (const key of keys) {
608
+ const keyParts = key.split(NESTED_SEP);
609
+ const validParents = /* @__PURE__ */ new Set();
610
+ for (let i = keyParts.length - 1; i > 0; i--) {
611
+ const parentPath = keyParts.slice(0, i).join(NESTED_SEP);
612
+ const parentWithEdgeMarker = `${parentPath}${NESTED_SEP}${EDGE_MARKER}`;
613
+ if (keys.has(parentWithEdgeMarker)) {
614
+ validParents.add(parentWithEdgeMarker);
615
+ const children = nodesChildren.get(parentWithEdgeMarker) ?? /* @__PURE__ */ new Set();
616
+ children.add(key);
617
+ nodesChildren.set(parentWithEdgeMarker, children);
618
+ }
619
+ if (keys.has(parentPath)) {
620
+ validParents.add(parentPath);
621
+ const children = nodesChildren.get(parentPath) ?? /* @__PURE__ */ new Set();
622
+ children.add(key);
623
+ nodesChildren.set(parentPath, children);
624
+ }
625
+ }
626
+ nodesParent.set(key, validParents);
627
+ }
628
+ return { nodesParent, nodesChildren };
629
+ }
630
+ function getLeafCursors(queryResult, viewExternalId, nodesParent, nodesChildren) {
631
+ const targetCursors = {};
632
+ const targetCursorKeys = /* @__PURE__ */ new Set();
633
+ for (const [cursorKey, cursorValue] of Object.entries(queryResult.nextCursor)) {
634
+ if (cursorKey === viewExternalId || !cursorValue || (queryResult.items[cursorKey]?.length ?? 0) !== MAX_LIMIT) {
635
+ continue;
636
+ }
637
+ const children = nodesChildren.get(cursorKey) ?? /* @__PURE__ */ new Set();
638
+ let skipDueToChild = false;
639
+ for (const c of children) {
640
+ if (targetCursorKeys.has(c)) {
641
+ skipDueToChild = true;
642
+ break;
643
+ }
644
+ }
645
+ if (skipDueToChild) continue;
646
+ const parent = nodesParent.get(cursorKey) ?? /* @__PURE__ */ new Set();
647
+ for (const key of parent) {
648
+ if (targetCursorKeys.has(key)) {
649
+ delete targetCursors[key];
650
+ targetCursorKeys.delete(key);
651
+ }
652
+ }
653
+ targetCursors[cursorKey] = cursorValue;
654
+ targetCursorKeys.add(cursorKey);
655
+ }
656
+ return targetCursors;
657
+ }
658
+ function buildDependenciesQuery(previousQuery, nodesParent, nodesChildren, leafCursors) {
659
+ const withExprs = {};
660
+ const selectExprs = {};
661
+ const finalCursors = {};
662
+ for (const [cursorKey, cursorValue] of Object.entries(leafCursors)) {
663
+ const children = nodesChildren.get(cursorKey) ?? /* @__PURE__ */ new Set();
664
+ const parent = nodesParent.get(cursorKey) ?? /* @__PURE__ */ new Set();
665
+ const validKeys = /* @__PURE__ */ new Set([...parent, ...children, cursorKey]);
666
+ for (const [k, v] of Object.entries(previousQuery.with)) {
667
+ if (validKeys.has(k)) withExprs[k] = v;
668
+ }
669
+ for (const [k, v] of Object.entries(previousQuery.select)) {
670
+ if (validKeys.has(k)) selectExprs[k] = v;
671
+ }
672
+ for (const [k, v] of Object.entries(previousQuery.cursors ?? {})) {
673
+ if (parent.has(k) && v) finalCursors[k] = v;
674
+ }
675
+ finalCursors[cursorKey] = cursorValue;
676
+ }
677
+ return { with: withExprs, select: selectExprs, cursors: finalCursors };
678
+ }
679
+
680
+ // src/client.ts
681
+ var IndustrialModel = class {
682
+ constructor(client, dataModelId) {
683
+ const cognite = createCogniteAdapter(client);
684
+ this.cognite = cognite;
685
+ const viewMapper = new ViewMapper(cognite, dataModelId);
686
+ this.queryMapper = new QueryMapper(viewMapper);
687
+ this.resultMapper = new QueryResultMapper(viewMapper);
688
+ }
689
+ async query(options) {
690
+ const { viewExternalId, limit = DEFAULT_LIMIT } = options;
691
+ const allPages = options.limit === -1;
692
+ const cogniteQuery = await this.queryMapper.map(options);
693
+ const data = [];
694
+ while (true) {
695
+ const queryResult = await this.cognite.queryInstances(cogniteQuery);
696
+ const dependenciesData = await this.queryDependenciesPages(
697
+ cogniteQuery,
698
+ queryResult,
699
+ viewExternalId
700
+ );
701
+ const queryResultData = appendNodesAndEdges(
702
+ mapNodesAndEdges(queryResult),
703
+ dependenciesData
704
+ );
705
+ const pageResult = await this.resultMapper.mapNodes(viewExternalId, queryResultData);
706
+ const nextCursor = queryResult.nextCursor[viewExternalId] ?? null;
707
+ data.push(...pageResult);
708
+ const isLastPage = pageResult.length < limit || !nextCursor;
709
+ const resolvedCursor = isLastPage ? null : nextCursor;
710
+ if (!isLastPage && resolvedCursor !== null) {
711
+ cogniteQuery.cursors = { [viewExternalId]: resolvedCursor };
712
+ }
713
+ if (!allPages || isLastPage) {
714
+ return { items: data, cursor: resolvedCursor };
715
+ }
716
+ }
717
+ }
718
+ async queryDependenciesPages(cogniteQuery, queryResult, viewExternalId, remainingDepth = MAX_DEPENDENCY_DEPTH) {
719
+ if (remainingDepth <= 0) {
720
+ return null;
721
+ }
722
+ const newQuery = getQueryForDependenciesPagination(cogniteQuery, queryResult, viewExternalId);
723
+ if (!newQuery) return null;
724
+ const newQueryResult = await this.cognite.queryInstances(newQuery);
725
+ const result = mapNodesAndEdges(newQueryResult);
726
+ const nestedResults = await this.queryDependenciesPages(
727
+ newQuery,
728
+ newQueryResult,
729
+ viewExternalId,
730
+ remainingDepth - 1
731
+ );
732
+ return appendNodesAndEdges(result, nestedResults);
733
+ }
734
+ };
735
+
736
+ export { IndustrialModel };
737
+ //# sourceMappingURL=index.js.map
738
+ //# sourceMappingURL=index.js.map