industrial-model 0.5.0 → 0.6.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.cjs CHANGED
@@ -54,7 +54,108 @@ var MAX_DEPENDENCY_DEPTH = 3;
54
54
  var AGGREGATE_LIMIT = 1e3;
55
55
  var MAX_GROUP_BY = 5;
56
56
 
57
- // src/mappers/utils.ts
57
+ // src/utils/query.ts
58
+ function mapNodesAndEdges(queryResult, _query) {
59
+ return queryResult.items;
60
+ }
61
+ function appendNodesAndEdges(initial, additional) {
62
+ if (!additional) return initial;
63
+ for (const [key, items] of Object.entries(additional)) {
64
+ const existing = initial[key];
65
+ if (existing) {
66
+ existing.push(...items);
67
+ } else {
68
+ initial[key] = [...items];
69
+ }
70
+ }
71
+ return initial;
72
+ }
73
+ function getQueryForDependenciesPagination(query, queryResult, viewExternalId) {
74
+ const cursorKeys = new Set(Object.keys(queryResult.nextCursor));
75
+ const { nodesParent, nodesChildren } = getParentAndChildrenNodes(cursorKeys);
76
+ const leafCursors = getLeafCursors(queryResult, viewExternalId, nodesParent, nodesChildren);
77
+ if (Object.keys(leafCursors).length === 0) {
78
+ return null;
79
+ }
80
+ return buildDependenciesQuery(query, nodesParent, nodesChildren, leafCursors);
81
+ }
82
+ function getParentAndChildrenNodes(keys) {
83
+ const nodesParent = /* @__PURE__ */ new Map();
84
+ const nodesChildren = /* @__PURE__ */ new Map();
85
+ for (const key of keys) {
86
+ const keyParts = key.split(NESTED_SEP);
87
+ const validParents = /* @__PURE__ */ new Set();
88
+ for (let i = keyParts.length - 1; i > 0; i--) {
89
+ const parentPath = keyParts.slice(0, i).join(NESTED_SEP);
90
+ const parentWithEdgeMarker = `${parentPath}${NESTED_SEP}${EDGE_MARKER}`;
91
+ if (keys.has(parentWithEdgeMarker)) {
92
+ validParents.add(parentWithEdgeMarker);
93
+ const children = nodesChildren.get(parentWithEdgeMarker) ?? /* @__PURE__ */ new Set();
94
+ children.add(key);
95
+ nodesChildren.set(parentWithEdgeMarker, children);
96
+ }
97
+ if (keys.has(parentPath)) {
98
+ validParents.add(parentPath);
99
+ const children = nodesChildren.get(parentPath) ?? /* @__PURE__ */ new Set();
100
+ children.add(key);
101
+ nodesChildren.set(parentPath, children);
102
+ }
103
+ }
104
+ nodesParent.set(key, validParents);
105
+ }
106
+ return { nodesParent, nodesChildren };
107
+ }
108
+ function getLeafCursors(queryResult, viewExternalId, nodesParent, nodesChildren) {
109
+ const targetCursors = {};
110
+ const targetCursorKeys = /* @__PURE__ */ new Set();
111
+ for (const [cursorKey, cursorValue] of Object.entries(queryResult.nextCursor)) {
112
+ if (cursorKey === viewExternalId || !cursorValue || (queryResult.items[cursorKey]?.length ?? 0) !== MAX_LIMIT) {
113
+ continue;
114
+ }
115
+ const children = nodesChildren.get(cursorKey) ?? /* @__PURE__ */ new Set();
116
+ let skipDueToChild = false;
117
+ for (const c of children) {
118
+ if (targetCursorKeys.has(c)) {
119
+ skipDueToChild = true;
120
+ break;
121
+ }
122
+ }
123
+ if (skipDueToChild) continue;
124
+ const parent = nodesParent.get(cursorKey) ?? /* @__PURE__ */ new Set();
125
+ for (const key of parent) {
126
+ if (targetCursorKeys.has(key)) {
127
+ delete targetCursors[key];
128
+ targetCursorKeys.delete(key);
129
+ }
130
+ }
131
+ targetCursors[cursorKey] = cursorValue;
132
+ targetCursorKeys.add(cursorKey);
133
+ }
134
+ return targetCursors;
135
+ }
136
+ function buildDependenciesQuery(previousQuery, nodesParent, nodesChildren, leafCursors) {
137
+ const withExprs = {};
138
+ const selectExprs = {};
139
+ const finalCursors = {};
140
+ for (const [cursorKey, cursorValue] of Object.entries(leafCursors)) {
141
+ const children = nodesChildren.get(cursorKey) ?? /* @__PURE__ */ new Set();
142
+ const parent = nodesParent.get(cursorKey) ?? /* @__PURE__ */ new Set();
143
+ const validKeys = /* @__PURE__ */ new Set([...parent, ...children, cursorKey]);
144
+ for (const [k, v] of Object.entries(previousQuery.with)) {
145
+ if (validKeys.has(k)) withExprs[k] = v;
146
+ }
147
+ for (const [k, v] of Object.entries(previousQuery.select)) {
148
+ if (validKeys.has(k)) selectExprs[k] = v;
149
+ }
150
+ for (const [k, v] of Object.entries(previousQuery.cursors ?? {})) {
151
+ if (parent.has(k) && v) finalCursors[k] = v;
152
+ }
153
+ finalCursors[cursorKey] = cursorValue;
154
+ }
155
+ return { with: withExprs, select: selectExprs, cursors: finalCursors };
156
+ }
157
+
158
+ // src/utils/view.ts
58
159
  var NODE_PROPERTIES = /* @__PURE__ */ new Set([
59
160
  "externalId",
60
161
  "space",
@@ -118,8 +219,6 @@ function isNumericProperty(property) {
118
219
  function getSelectedGroupByKeys(groupBy) {
119
220
  return Object.entries(groupBy).filter((entry) => entry[1] === true).map(([key]) => key);
120
221
  }
121
-
122
- // src/validation.ts
123
222
  var nodeIdSchema = zod.z.object({
124
223
  space: zod.z.string().min(1),
125
224
  externalId: zod.z.string().min(1)
@@ -168,17 +267,8 @@ function propertyValueSchema(property, options = {}) {
168
267
  }
169
268
  return type.list === true ? zod.z.array(schema) : schema;
170
269
  }
171
- function buildViewSchema(view, options = {}) {
172
- const shape = {};
173
- for (const [name, property] of Object.entries(view.properties)) {
174
- if (isViewPropertyDefinition(property)) {
175
- shape[name] = propertyValueSchema(property, options).optional();
176
- }
177
- }
178
- return zod.z.object(shape).strict();
179
- }
180
270
 
181
- // src/mappers/query-validator.ts
271
+ // src/validators/query-validator.ts
182
272
  var NODE_STRING_PROPERTIES = ["externalId", "space"];
183
273
  var NODE_NUMBER_PROPERTIES = ["createdTime", "deletedTime", "lastUpdatedTime"];
184
274
  var NODE_PROPERTIES2 = /* @__PURE__ */ new Set([...NODE_STRING_PROPERTIES, ...NODE_NUMBER_PROPERTIES]);
@@ -389,6 +479,12 @@ ${errors.map((error) => `- ${error}`).join("\n")}`);
389
479
  );
390
480
  continue;
391
481
  }
482
+ if (isReverseDirectRelation(property) && property.targetsList) {
483
+ errors.push(
484
+ `${issuePath([...path, name])}: cannot select "${name}" \u2014 Cognite does not support inward traversal of list direct relations. Query "${property.source.externalId}" directly and filter by the "${property.through.identifier}" field instead.`
485
+ );
486
+ continue;
487
+ }
392
488
  const targetView = await this.viewMapper.getView(target);
393
489
  errors.push(...await this.validateSelect(value, targetView, [...path, name]));
394
490
  }
@@ -478,7 +574,7 @@ ${errors.map((error) => `- ${error}`).join("\n")}`);
478
574
  }
479
575
  };
480
576
 
481
- // src/mappers/aggregate-validator.ts
577
+ // src/validators/aggregate-validator.ts
482
578
  var NODE_COUNT_PROPERTIES = /* @__PURE__ */ new Set(["externalId", "space"]);
483
579
  function issuePath2(path) {
484
580
  return path.length === 0 ? "aggregate" : path.map(String).join(".");
@@ -614,6 +710,92 @@ ${errors.map((error) => `- ${error}`).join("\n")}`
614
710
  return [];
615
711
  }
616
712
  };
713
+ var nodeMetadataSchema = {
714
+ instanceType: zod.z.literal("node").optional(),
715
+ space: zod.z.string(),
716
+ externalId: zod.z.string(),
717
+ version: zod.z.number().optional(),
718
+ createdTime: zod.z.number().optional(),
719
+ deletedTime: zod.z.number().optional(),
720
+ lastUpdatedTime: zod.z.number().optional(),
721
+ _edges: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
722
+ };
723
+ function isListRelation(property) {
724
+ if (isViewPropertyDefinition(property)) {
725
+ return isListDirectRelation(property);
726
+ }
727
+ if (isReverseDirectRelation(property)) {
728
+ return property.connectionType === "multi_reverse_direct_relation" || property.targetsList === true;
729
+ }
730
+ return isEdgeConnection(property);
731
+ }
732
+ function isRecord2(value) {
733
+ return value != null && typeof value === "object" && !Array.isArray(value);
734
+ }
735
+ var QueryResultValidator = class {
736
+ constructor(viewMapper) {
737
+ this.viewMapper = viewMapper;
738
+ }
739
+ async parseItems(rootViewExternalId, items, select) {
740
+ const rootView = await this.viewMapper.getView(rootViewExternalId);
741
+ const schema = await this.buildResultSchema(rootView, MAX_DEPENDENCY_DEPTH, select);
742
+ const result = zod.z.array(schema).safeParse(items);
743
+ if (!result.success) {
744
+ throw new Error(
745
+ `Invalid query result:
746
+ ${result.error.issues.map((issue) => `- ${issue.path.map(String).join(".")}: ${issue.message}`).join("\n")}`
747
+ );
748
+ }
749
+ return result.data;
750
+ }
751
+ async buildResultSchema(view, remainingDepth, select) {
752
+ const shape = { ...nodeMetadataSchema };
753
+ const includeAllProperties = select == null || select._all === true;
754
+ for (const [name, property] of Object.entries(view.properties)) {
755
+ const isSelected = includeAllProperties || name in select;
756
+ if (!isSelected) continue;
757
+ const nestedSelect = isRecord2(select?.[name]) ? select[name] : void 0;
758
+ if (isViewPropertyDefinition(property)) {
759
+ const relationSource = getDirectRelationSource(property);
760
+ if (relationSource) {
761
+ shape[name] = await this.buildRelationSchema(
762
+ property,
763
+ relationSource.externalId,
764
+ remainingDepth,
765
+ nestedSelect
766
+ );
767
+ } else {
768
+ shape[name] = propertyValueSchema(property, { dateMode: "coerce" }).optional();
769
+ }
770
+ continue;
771
+ }
772
+ if (isReverseDirectRelation(property) || isEdgeConnection(property)) {
773
+ shape[name] = await this.buildRelationSchema(
774
+ property,
775
+ property.source.externalId,
776
+ remainingDepth,
777
+ nestedSelect
778
+ );
779
+ }
780
+ }
781
+ const schema = zod.z.object(shape);
782
+ return includeAllProperties ? schema.strict() : schema;
783
+ }
784
+ async buildRelationSchema(property, targetViewExternalId, remainingDepth, select) {
785
+ const isList = isListRelation(property);
786
+ const fallbackSchema = isViewPropertyDefinition(property) ? propertyValueSchema(property, { dateMode: "coerce" }) : zod.z.unknown();
787
+ if (remainingDepth <= 0 || select == null) {
788
+ return fallbackSchema.optional();
789
+ }
790
+ const targetView = await this.viewMapper.getView(targetViewExternalId);
791
+ const nestedSchema = await this.buildResultSchema(targetView, remainingDepth - 1, select);
792
+ if (isViewPropertyDefinition(property)) {
793
+ const nestedRelationSchema = isList ? zod.z.array(nestedSchema) : nestedSchema;
794
+ return zod.z.union([nestedRelationSchema, fallbackSchema]).optional();
795
+ }
796
+ return (isList ? zod.z.array(nestedSchema) : nestedSchema).optional();
797
+ }
798
+ };
617
799
 
618
800
  // src/mappers/filter-mapper.ts
619
801
  var LEAF_OPS = /* @__PURE__ */ new Set([
@@ -1180,92 +1362,6 @@ var QueryResultMapper = class {
1180
1362
  return entry;
1181
1363
  }
1182
1364
  };
1183
- var nodeMetadataSchema = {
1184
- instanceType: zod.z.literal("node").optional(),
1185
- space: zod.z.string(),
1186
- externalId: zod.z.string(),
1187
- version: zod.z.number().optional(),
1188
- createdTime: zod.z.number().optional(),
1189
- deletedTime: zod.z.number().optional(),
1190
- lastUpdatedTime: zod.z.number().optional(),
1191
- _edges: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
1192
- };
1193
- function isListRelation(property) {
1194
- if (isViewPropertyDefinition(property)) {
1195
- return isListDirectRelation(property);
1196
- }
1197
- if (isReverseDirectRelation(property)) {
1198
- return property.connectionType === "multi_reverse_direct_relation" || property.targetsList === true;
1199
- }
1200
- return isEdgeConnection(property);
1201
- }
1202
- function isRecord2(value) {
1203
- return value != null && typeof value === "object" && !Array.isArray(value);
1204
- }
1205
- var QueryResultValidator = class {
1206
- constructor(viewMapper) {
1207
- this.viewMapper = viewMapper;
1208
- }
1209
- async parseItems(rootViewExternalId, items, select) {
1210
- const rootView = await this.viewMapper.getView(rootViewExternalId);
1211
- const schema = await this.buildResultSchema(rootView, MAX_DEPENDENCY_DEPTH, select);
1212
- const result = zod.z.array(schema).safeParse(items);
1213
- if (!result.success) {
1214
- throw new Error(
1215
- `Invalid query result:
1216
- ${result.error.issues.map((issue) => `- ${issue.path.map(String).join(".")}: ${issue.message}`).join("\n")}`
1217
- );
1218
- }
1219
- return result.data;
1220
- }
1221
- async buildResultSchema(view, remainingDepth, select) {
1222
- const shape = { ...nodeMetadataSchema };
1223
- const includeAllProperties = select == null || select._all === true;
1224
- for (const [name, property] of Object.entries(view.properties)) {
1225
- const isSelected = includeAllProperties || name in select;
1226
- if (!isSelected) continue;
1227
- const nestedSelect = isRecord2(select?.[name]) ? select[name] : void 0;
1228
- if (isViewPropertyDefinition(property)) {
1229
- const relationSource = getDirectRelationSource(property);
1230
- if (relationSource) {
1231
- shape[name] = await this.buildRelationSchema(
1232
- property,
1233
- relationSource.externalId,
1234
- remainingDepth,
1235
- nestedSelect
1236
- );
1237
- } else {
1238
- shape[name] = propertyValueSchema(property, { dateMode: "coerce" }).optional();
1239
- }
1240
- continue;
1241
- }
1242
- if (isReverseDirectRelation(property) || isEdgeConnection(property)) {
1243
- shape[name] = await this.buildRelationSchema(
1244
- property,
1245
- property.source.externalId,
1246
- remainingDepth,
1247
- nestedSelect
1248
- );
1249
- }
1250
- }
1251
- const schema = zod.z.object(shape);
1252
- return includeAllProperties ? schema.strict() : schema;
1253
- }
1254
- async buildRelationSchema(property, targetViewExternalId, remainingDepth, select) {
1255
- const isList = isListRelation(property);
1256
- const fallbackSchema = isViewPropertyDefinition(property) ? propertyValueSchema(property, { dateMode: "coerce" }) : zod.z.unknown();
1257
- if (remainingDepth <= 0 || select == null) {
1258
- return fallbackSchema.optional();
1259
- }
1260
- const targetView = await this.viewMapper.getView(targetViewExternalId);
1261
- const nestedSchema = await this.buildResultSchema(targetView, remainingDepth - 1, select);
1262
- if (isViewPropertyDefinition(property)) {
1263
- const nestedRelationSchema = isList ? zod.z.array(nestedSchema) : nestedSchema;
1264
- return zod.z.union([nestedRelationSchema, fallbackSchema]).optional();
1265
- }
1266
- return (isList ? zod.z.array(nestedSchema) : nestedSchema).optional();
1267
- }
1268
- };
1269
1365
 
1270
1366
  // src/mappers/view-mapper.ts
1271
1367
  var ViewMapper = class {
@@ -1313,107 +1409,6 @@ var ViewMapper = class {
1313
1409
  }
1314
1410
  };
1315
1411
 
1316
- // src/utils/query.ts
1317
- function mapNodesAndEdges(queryResult, _query) {
1318
- return queryResult.items;
1319
- }
1320
- function appendNodesAndEdges(initial, additional) {
1321
- if (!additional) return initial;
1322
- for (const [key, items] of Object.entries(additional)) {
1323
- const existing = initial[key];
1324
- if (existing) {
1325
- existing.push(...items);
1326
- } else {
1327
- initial[key] = [...items];
1328
- }
1329
- }
1330
- return initial;
1331
- }
1332
- function getQueryForDependenciesPagination(query, queryResult, viewExternalId) {
1333
- const cursorKeys = new Set(Object.keys(queryResult.nextCursor));
1334
- const { nodesParent, nodesChildren } = getParentAndChildrenNodes(cursorKeys);
1335
- const leafCursors = getLeafCursors(queryResult, viewExternalId, nodesParent, nodesChildren);
1336
- if (Object.keys(leafCursors).length === 0) {
1337
- return null;
1338
- }
1339
- return buildDependenciesQuery(query, nodesParent, nodesChildren, leafCursors);
1340
- }
1341
- function getParentAndChildrenNodes(keys) {
1342
- const nodesParent = /* @__PURE__ */ new Map();
1343
- const nodesChildren = /* @__PURE__ */ new Map();
1344
- for (const key of keys) {
1345
- const keyParts = key.split(NESTED_SEP);
1346
- const validParents = /* @__PURE__ */ new Set();
1347
- for (let i = keyParts.length - 1; i > 0; i--) {
1348
- const parentPath = keyParts.slice(0, i).join(NESTED_SEP);
1349
- const parentWithEdgeMarker = `${parentPath}${NESTED_SEP}${EDGE_MARKER}`;
1350
- if (keys.has(parentWithEdgeMarker)) {
1351
- validParents.add(parentWithEdgeMarker);
1352
- const children = nodesChildren.get(parentWithEdgeMarker) ?? /* @__PURE__ */ new Set();
1353
- children.add(key);
1354
- nodesChildren.set(parentWithEdgeMarker, children);
1355
- }
1356
- if (keys.has(parentPath)) {
1357
- validParents.add(parentPath);
1358
- const children = nodesChildren.get(parentPath) ?? /* @__PURE__ */ new Set();
1359
- children.add(key);
1360
- nodesChildren.set(parentPath, children);
1361
- }
1362
- }
1363
- nodesParent.set(key, validParents);
1364
- }
1365
- return { nodesParent, nodesChildren };
1366
- }
1367
- function getLeafCursors(queryResult, viewExternalId, nodesParent, nodesChildren) {
1368
- const targetCursors = {};
1369
- const targetCursorKeys = /* @__PURE__ */ new Set();
1370
- for (const [cursorKey, cursorValue] of Object.entries(queryResult.nextCursor)) {
1371
- if (cursorKey === viewExternalId || !cursorValue || (queryResult.items[cursorKey]?.length ?? 0) !== MAX_LIMIT) {
1372
- continue;
1373
- }
1374
- const children = nodesChildren.get(cursorKey) ?? /* @__PURE__ */ new Set();
1375
- let skipDueToChild = false;
1376
- for (const c of children) {
1377
- if (targetCursorKeys.has(c)) {
1378
- skipDueToChild = true;
1379
- break;
1380
- }
1381
- }
1382
- if (skipDueToChild) continue;
1383
- const parent = nodesParent.get(cursorKey) ?? /* @__PURE__ */ new Set();
1384
- for (const key of parent) {
1385
- if (targetCursorKeys.has(key)) {
1386
- delete targetCursors[key];
1387
- targetCursorKeys.delete(key);
1388
- }
1389
- }
1390
- targetCursors[cursorKey] = cursorValue;
1391
- targetCursorKeys.add(cursorKey);
1392
- }
1393
- return targetCursors;
1394
- }
1395
- function buildDependenciesQuery(previousQuery, nodesParent, nodesChildren, leafCursors) {
1396
- const withExprs = {};
1397
- const selectExprs = {};
1398
- const finalCursors = {};
1399
- for (const [cursorKey, cursorValue] of Object.entries(leafCursors)) {
1400
- const children = nodesChildren.get(cursorKey) ?? /* @__PURE__ */ new Set();
1401
- const parent = nodesParent.get(cursorKey) ?? /* @__PURE__ */ new Set();
1402
- const validKeys = /* @__PURE__ */ new Set([...parent, ...children, cursorKey]);
1403
- for (const [k, v] of Object.entries(previousQuery.with)) {
1404
- if (validKeys.has(k)) withExprs[k] = v;
1405
- }
1406
- for (const [k, v] of Object.entries(previousQuery.select)) {
1407
- if (validKeys.has(k)) selectExprs[k] = v;
1408
- }
1409
- for (const [k, v] of Object.entries(previousQuery.cursors ?? {})) {
1410
- if (parent.has(k) && v) finalCursors[k] = v;
1411
- }
1412
- finalCursors[cursorKey] = cursorValue;
1413
- }
1414
- return { with: withExprs, select: selectExprs, cursors: finalCursors };
1415
- }
1416
-
1417
1412
  // src/client.ts
1418
1413
  var IndustrialModelClient = class {
1419
1414
  constructor(client, dataModelId, options = {}) {
@@ -1493,7 +1488,5 @@ var IndustrialModelClient = class {
1493
1488
  };
1494
1489
 
1495
1490
  exports.IndustrialModelClient = IndustrialModelClient;
1496
- exports.buildViewSchema = buildViewSchema;
1497
- exports.nodeIdSchema = nodeIdSchema;
1498
1491
  //# sourceMappingURL=index.cjs.map
1499
1492
  //# sourceMappingURL=index.cjs.map