industrial-model 0.1.0 → 0.3.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/README.md +212 -125
- package/dist/index.cjs +448 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +140 -34
- package/dist/index.d.ts +140 -34
- package/dist/index.js +446 -10
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var zod = require('zod');
|
|
4
|
+
|
|
3
5
|
// src/cognite/adapter.ts
|
|
4
6
|
function createCogniteAdapter(client) {
|
|
5
7
|
return new CogniteSdkAdapter(client);
|
|
@@ -204,11 +206,350 @@ var FilterMapper = class {
|
|
|
204
206
|
return value;
|
|
205
207
|
}
|
|
206
208
|
};
|
|
209
|
+
var nodeIdSchema = zod.z.object({
|
|
210
|
+
space: zod.z.string().min(1),
|
|
211
|
+
externalId: zod.z.string().min(1)
|
|
212
|
+
});
|
|
213
|
+
function dateSchema(dateMode) {
|
|
214
|
+
if (dateMode === "coerce") {
|
|
215
|
+
return zod.z.preprocess(
|
|
216
|
+
(value) => typeof value === "string" || typeof value === "number" ? new Date(value) : value,
|
|
217
|
+
zod.z.date()
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
return zod.z.union([zod.z.string(), zod.z.date()]);
|
|
221
|
+
}
|
|
222
|
+
function propertyValueSchema(property, options = {}) {
|
|
223
|
+
const type = property.type;
|
|
224
|
+
let schema;
|
|
225
|
+
switch (type.type) {
|
|
226
|
+
case "text":
|
|
227
|
+
case "enum":
|
|
228
|
+
schema = zod.z.string();
|
|
229
|
+
break;
|
|
230
|
+
case "int32":
|
|
231
|
+
case "int64":
|
|
232
|
+
schema = zod.z.number().int();
|
|
233
|
+
break;
|
|
234
|
+
case "float32":
|
|
235
|
+
case "float64":
|
|
236
|
+
schema = zod.z.number();
|
|
237
|
+
break;
|
|
238
|
+
case "boolean":
|
|
239
|
+
schema = zod.z.boolean();
|
|
240
|
+
break;
|
|
241
|
+
case "date":
|
|
242
|
+
case "timestamp":
|
|
243
|
+
schema = dateSchema(options.dateMode);
|
|
244
|
+
break;
|
|
245
|
+
case "direct":
|
|
246
|
+
schema = nodeIdSchema;
|
|
247
|
+
break;
|
|
248
|
+
case "json":
|
|
249
|
+
schema = zod.z.unknown();
|
|
250
|
+
break;
|
|
251
|
+
default:
|
|
252
|
+
schema = zod.z.unknown();
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
return type.list === true ? zod.z.array(schema) : schema;
|
|
256
|
+
}
|
|
257
|
+
function buildViewSchema(view, options = {}) {
|
|
258
|
+
const shape = {};
|
|
259
|
+
for (const [name, property] of Object.entries(view.properties)) {
|
|
260
|
+
if (isViewPropertyDefinition(property)) {
|
|
261
|
+
shape[name] = propertyValueSchema(property, options).optional();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return zod.z.object(shape).strict();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/mappers/query-validator.ts
|
|
268
|
+
var NODE_STRING_PROPERTIES = ["externalId", "space"];
|
|
269
|
+
var NODE_NUMBER_PROPERTIES = ["createdTime", "deletedTime", "lastUpdatedTime"];
|
|
270
|
+
var NODE_PROPERTIES2 = /* @__PURE__ */ new Set([...NODE_STRING_PROPERTIES, ...NODE_NUMBER_PROPERTIES]);
|
|
271
|
+
var SORT_DIRECTION_SCHEMA = zod.z.enum(["ascending", "descending"]);
|
|
272
|
+
var recordSchema = zod.z.record(zod.z.string(), zod.z.unknown());
|
|
273
|
+
var leafOps = /* @__PURE__ */ new Set([
|
|
274
|
+
"eq",
|
|
275
|
+
"in",
|
|
276
|
+
"gt",
|
|
277
|
+
"gte",
|
|
278
|
+
"lt",
|
|
279
|
+
"lte",
|
|
280
|
+
"exists",
|
|
281
|
+
"prefix",
|
|
282
|
+
"containsAny",
|
|
283
|
+
"containsAll"
|
|
284
|
+
]);
|
|
285
|
+
function isRecord(value) {
|
|
286
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
287
|
+
}
|
|
288
|
+
function isLeafFilter2(value) {
|
|
289
|
+
return Object.keys(value).some((key) => leafOps.has(key));
|
|
290
|
+
}
|
|
291
|
+
function issuePath(path) {
|
|
292
|
+
return path.length === 0 ? "query" : path.map(String).join(".");
|
|
293
|
+
}
|
|
294
|
+
function formatZodIssues(error, path) {
|
|
295
|
+
return error.issues.map((issue) => `${issuePath([...path, ...issue.path])}: ${issue.message}`);
|
|
296
|
+
}
|
|
297
|
+
function getRelationTarget(property) {
|
|
298
|
+
if (isViewPropertyDefinition(property)) {
|
|
299
|
+
return getDirectRelationSource(property)?.externalId ?? null;
|
|
300
|
+
}
|
|
301
|
+
if (isReverseDirectRelation(property) || isEdgeConnection(property)) {
|
|
302
|
+
return property.source.externalId;
|
|
303
|
+
}
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
function baseValueSchema(property) {
|
|
307
|
+
if (property === "node-string") return zod.z.string();
|
|
308
|
+
if (property === "node-number") return zod.z.number();
|
|
309
|
+
switch (property.type.type) {
|
|
310
|
+
case "text":
|
|
311
|
+
case "enum":
|
|
312
|
+
return zod.z.string();
|
|
313
|
+
case "int32":
|
|
314
|
+
case "int64":
|
|
315
|
+
return zod.z.number().int();
|
|
316
|
+
case "float32":
|
|
317
|
+
case "float64":
|
|
318
|
+
return zod.z.number();
|
|
319
|
+
case "boolean":
|
|
320
|
+
return zod.z.boolean();
|
|
321
|
+
case "date":
|
|
322
|
+
case "timestamp":
|
|
323
|
+
return zod.z.union([zod.z.string(), zod.z.date()]);
|
|
324
|
+
case "direct":
|
|
325
|
+
return nodeIdSchema;
|
|
326
|
+
default:
|
|
327
|
+
return zod.z.union([zod.z.string(), zod.z.number(), zod.z.boolean()]);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
function leafFilterSchema(property) {
|
|
331
|
+
const value = baseValueSchema(property);
|
|
332
|
+
const isList = typeof property !== "string" && property.type.list === true;
|
|
333
|
+
if (isList) {
|
|
334
|
+
return zod.z.object({
|
|
335
|
+
containsAny: zod.z.array(value).optional(),
|
|
336
|
+
containsAll: zod.z.array(value).optional(),
|
|
337
|
+
exists: zod.z.boolean().optional()
|
|
338
|
+
}).strict();
|
|
339
|
+
}
|
|
340
|
+
if (property === "node-string" || typeof property !== "string" && property.type.type === "text") {
|
|
341
|
+
return zod.z.object({
|
|
342
|
+
eq: zod.z.string().optional(),
|
|
343
|
+
in: zod.z.array(zod.z.string()).optional(),
|
|
344
|
+
prefix: zod.z.string().optional(),
|
|
345
|
+
exists: zod.z.boolean().optional()
|
|
346
|
+
}).strict();
|
|
347
|
+
}
|
|
348
|
+
if (typeof property !== "string" && property.type.type === "enum") {
|
|
349
|
+
return zod.z.object({
|
|
350
|
+
eq: zod.z.string().optional(),
|
|
351
|
+
in: zod.z.array(zod.z.string()).optional(),
|
|
352
|
+
prefix: zod.z.string().optional(),
|
|
353
|
+
exists: zod.z.boolean().optional()
|
|
354
|
+
}).strict();
|
|
355
|
+
}
|
|
356
|
+
if (property === "node-number" || typeof property !== "string" && ["int32", "int64", "float32", "float64"].includes(property.type.type ?? "")) {
|
|
357
|
+
return zod.z.object({
|
|
358
|
+
eq: value.optional(),
|
|
359
|
+
in: zod.z.array(value).optional(),
|
|
360
|
+
gt: value.optional(),
|
|
361
|
+
gte: value.optional(),
|
|
362
|
+
lt: value.optional(),
|
|
363
|
+
lte: value.optional(),
|
|
364
|
+
exists: zod.z.boolean().optional()
|
|
365
|
+
}).strict();
|
|
366
|
+
}
|
|
367
|
+
if (typeof property !== "string" && ["date", "timestamp"].includes(property.type.type ?? "")) {
|
|
368
|
+
return zod.z.object({
|
|
369
|
+
eq: value.optional(),
|
|
370
|
+
in: zod.z.array(value).optional(),
|
|
371
|
+
gt: value.optional(),
|
|
372
|
+
gte: value.optional(),
|
|
373
|
+
lt: value.optional(),
|
|
374
|
+
lte: value.optional(),
|
|
375
|
+
exists: zod.z.boolean().optional()
|
|
376
|
+
}).strict();
|
|
377
|
+
}
|
|
378
|
+
if (typeof property !== "string" && property.type.type === "boolean") {
|
|
379
|
+
return zod.z.object({
|
|
380
|
+
eq: zod.z.boolean().optional(),
|
|
381
|
+
exists: zod.z.boolean().optional()
|
|
382
|
+
}).strict();
|
|
383
|
+
}
|
|
384
|
+
if (typeof property !== "string" && property.type.type === "direct") {
|
|
385
|
+
return zod.z.object({
|
|
386
|
+
eq: nodeIdSchema.optional(),
|
|
387
|
+
in: zod.z.array(nodeIdSchema).optional(),
|
|
388
|
+
exists: zod.z.boolean().optional()
|
|
389
|
+
}).strict();
|
|
390
|
+
}
|
|
391
|
+
return zod.z.object({
|
|
392
|
+
eq: value.optional(),
|
|
393
|
+
in: zod.z.array(value).optional(),
|
|
394
|
+
exists: zod.z.boolean().optional()
|
|
395
|
+
}).strict();
|
|
396
|
+
}
|
|
397
|
+
var QueryValidator = class {
|
|
398
|
+
constructor(viewMapper) {
|
|
399
|
+
this.viewMapper = viewMapper;
|
|
400
|
+
}
|
|
401
|
+
async validate(options, rootView) {
|
|
402
|
+
const errors = [];
|
|
403
|
+
errors.push(...this.validateOptionsShape(options, rootView));
|
|
404
|
+
if (options.select !== void 0) {
|
|
405
|
+
errors.push(...await this.validateSelect(options.select, rootView, ["select"]));
|
|
406
|
+
}
|
|
407
|
+
if (options.filters !== void 0) {
|
|
408
|
+
errors.push(...await this.validateFilters(options.filters, rootView, ["filters"]));
|
|
409
|
+
}
|
|
410
|
+
if (options.sort !== void 0) {
|
|
411
|
+
errors.push(...this.validateSort(options.sort, rootView, ["sort"]));
|
|
412
|
+
}
|
|
413
|
+
if (errors.length > 0) {
|
|
414
|
+
throw new Error(`Invalid query options:
|
|
415
|
+
${errors.map((error) => `- ${error}`).join("\n")}`);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
validateOptionsShape(options, rootView) {
|
|
419
|
+
const schema = zod.z.object({
|
|
420
|
+
viewExternalId: zod.z.literal(rootView.externalId),
|
|
421
|
+
select: zod.z.unknown().optional(),
|
|
422
|
+
filters: zod.z.unknown().optional(),
|
|
423
|
+
sort: zod.z.unknown().optional(),
|
|
424
|
+
limit: zod.z.union([zod.z.literal(-1), zod.z.number().int().positive().max(MAX_LIMIT)]).optional(),
|
|
425
|
+
cursor: zod.z.string().nullable().optional()
|
|
426
|
+
}).strict();
|
|
427
|
+
const result = schema.safeParse(options);
|
|
428
|
+
return result.success ? [] : formatZodIssues(result.error, []);
|
|
429
|
+
}
|
|
430
|
+
async validateSelect(select, view, path) {
|
|
431
|
+
const shape = {
|
|
432
|
+
_all: zod.z.literal(true).optional()
|
|
433
|
+
};
|
|
434
|
+
for (const property of NODE_PROPERTIES2) {
|
|
435
|
+
shape[property] = zod.z.boolean().optional();
|
|
436
|
+
}
|
|
437
|
+
for (const [name, property] of Object.entries(view.properties)) {
|
|
438
|
+
const target = getRelationTarget(property);
|
|
439
|
+
if (target != null) {
|
|
440
|
+
const nestedSelect = recordSchema;
|
|
441
|
+
shape[name] = isViewPropertyDefinition(property) ? zod.z.union([zod.z.boolean(), nestedSelect]).optional() : nestedSelect.optional();
|
|
442
|
+
} else {
|
|
443
|
+
shape[name] = zod.z.boolean().optional();
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
const result = zod.z.object(shape).strict().safeParse(select);
|
|
447
|
+
if (!result.success) return formatZodIssues(result.error, path);
|
|
448
|
+
if (!isRecord(select)) return [];
|
|
449
|
+
const errors = [];
|
|
450
|
+
for (const [name, value] of Object.entries(select)) {
|
|
451
|
+
if (name === "_all" || value == null || typeof value !== "object" || Array.isArray(value)) {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
const property = view.properties[name];
|
|
455
|
+
if (!property) continue;
|
|
456
|
+
const target = getRelationTarget(property);
|
|
457
|
+
if (target == null) {
|
|
458
|
+
errors.push(
|
|
459
|
+
`${issuePath([...path, name])}: property "${name}" does not support nested select`
|
|
460
|
+
);
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
const targetView = await this.viewMapper.getView(target);
|
|
464
|
+
errors.push(...await this.validateSelect(value, targetView, [...path, name]));
|
|
465
|
+
}
|
|
466
|
+
return errors;
|
|
467
|
+
}
|
|
468
|
+
async validateFilters(filters, view, path) {
|
|
469
|
+
const shape = {
|
|
470
|
+
AND: zod.z.union([recordSchema, zod.z.array(recordSchema)]).optional(),
|
|
471
|
+
OR: zod.z.array(recordSchema).optional(),
|
|
472
|
+
NOT: zod.z.union([recordSchema, zod.z.array(recordSchema)]).optional()
|
|
473
|
+
};
|
|
474
|
+
for (const property of NODE_STRING_PROPERTIES) {
|
|
475
|
+
shape[property] = zod.z.unknown().optional();
|
|
476
|
+
}
|
|
477
|
+
for (const property of NODE_NUMBER_PROPERTIES) {
|
|
478
|
+
shape[property] = zod.z.unknown().optional();
|
|
479
|
+
}
|
|
480
|
+
for (const property of Object.keys(view.properties)) {
|
|
481
|
+
shape[property] = zod.z.unknown().optional();
|
|
482
|
+
}
|
|
483
|
+
const result = zod.z.object(shape).strict().safeParse(filters);
|
|
484
|
+
if (!result.success) return formatZodIssues(result.error, path);
|
|
485
|
+
if (!isRecord(filters)) return [];
|
|
486
|
+
const errors = [];
|
|
487
|
+
for (const [name, value] of Object.entries(filters)) {
|
|
488
|
+
if (value == null) continue;
|
|
489
|
+
if (name === "AND" || name === "OR" || name === "NOT") {
|
|
490
|
+
const clauses = Array.isArray(value) ? value : [value];
|
|
491
|
+
for (const [index, clause] of clauses.entries()) {
|
|
492
|
+
errors.push(...await this.validateFilters(clause, view, [...path, name, index]));
|
|
493
|
+
}
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
if (!isRecord(value)) {
|
|
497
|
+
errors.push(`${issuePath([...path, name])}: Expected object`);
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
const nodePropertyType = NODE_STRING_PROPERTIES.includes(
|
|
501
|
+
name
|
|
502
|
+
) ? "node-string" : NODE_NUMBER_PROPERTIES.includes(name) ? "node-number" : null;
|
|
503
|
+
if (nodePropertyType != null) {
|
|
504
|
+
errors.push(...this.validateLeafFilter(value, nodePropertyType, [...path, name]));
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
const property = view.properties[name];
|
|
508
|
+
if (!property) continue;
|
|
509
|
+
if (isViewPropertyDefinition(property)) {
|
|
510
|
+
const target2 = getDirectRelationSource(property);
|
|
511
|
+
if (target2 != null && !isLeafFilter2(value)) {
|
|
512
|
+
const targetView = await this.viewMapper.getView(target2.externalId);
|
|
513
|
+
errors.push(...await this.validateFilters(value, targetView, [...path, name]));
|
|
514
|
+
} else {
|
|
515
|
+
errors.push(...this.validateLeafFilter(value, property, [...path, name]));
|
|
516
|
+
}
|
|
517
|
+
continue;
|
|
518
|
+
}
|
|
519
|
+
const target = getRelationTarget(property);
|
|
520
|
+
if (target == null) {
|
|
521
|
+
errors.push(`${issuePath([...path, name])}: property "${name}" does not support filters`);
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
errors.push(
|
|
525
|
+
`${issuePath([...path, name])}: filtering through "${name}" is not supported by the query mapper`
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
return errors;
|
|
529
|
+
}
|
|
530
|
+
validateLeafFilter(value, property, path) {
|
|
531
|
+
const result = leafFilterSchema(property).safeParse(value);
|
|
532
|
+
return result.success ? [] : formatZodIssues(result.error, path);
|
|
533
|
+
}
|
|
534
|
+
validateSort(sort, view, path) {
|
|
535
|
+
const shape = {};
|
|
536
|
+
for (const property of NODE_PROPERTIES2) {
|
|
537
|
+
shape[property] = SORT_DIRECTION_SCHEMA.optional();
|
|
538
|
+
}
|
|
539
|
+
for (const [name, property] of Object.entries(view.properties)) {
|
|
540
|
+
if (isViewPropertyDefinition(property) && property.type.list !== true) {
|
|
541
|
+
shape[name] = SORT_DIRECTION_SCHEMA.optional();
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
const result = zod.z.object(shape).strict().safeParse(sort);
|
|
545
|
+
return result.success ? [] : formatZodIssues(result.error, path);
|
|
546
|
+
}
|
|
547
|
+
};
|
|
207
548
|
|
|
208
549
|
// src/mappers/sort-mapper.ts
|
|
209
550
|
var SortMapper = class {
|
|
210
|
-
map(
|
|
211
|
-
return Object.entries(
|
|
551
|
+
map(sort, rootView) {
|
|
552
|
+
return Object.entries(sort).map(([property, direction]) => ({
|
|
212
553
|
property: getPropertyRef(property, rootView),
|
|
213
554
|
direction,
|
|
214
555
|
nullsFirst: this.isNullsFirst(property, rootView, direction)
|
|
@@ -229,18 +570,20 @@ var QueryMapper = class {
|
|
|
229
570
|
this.viewMapper = viewMapper;
|
|
230
571
|
this.filterMapper = new FilterMapper(viewMapper);
|
|
231
572
|
this.sortMapper = new SortMapper();
|
|
573
|
+
this.validator = new QueryValidator(viewMapper);
|
|
232
574
|
}
|
|
233
575
|
async map(options) {
|
|
234
576
|
const {
|
|
235
577
|
viewExternalId,
|
|
236
578
|
select = { _all: true },
|
|
237
579
|
filters,
|
|
238
|
-
|
|
580
|
+
sort = {},
|
|
239
581
|
limit: requestedLimit = DEFAULT_LIMIT,
|
|
240
582
|
cursor = null
|
|
241
583
|
} = options;
|
|
242
584
|
const limit = requestedLimit === -1 ? DEFAULT_LIMIT : requestedLimit;
|
|
243
585
|
const rootView = await this.viewMapper.getView(viewExternalId);
|
|
586
|
+
await this.validator.validate(options, rootView);
|
|
244
587
|
const rootViewRef = toViewReference(rootView);
|
|
245
588
|
const whereFilters = filters ? await this.filterMapper.map(filters, rootView) : [];
|
|
246
589
|
const baseFilters = [{ hasData: [rootViewRef] }, ...whereFilters];
|
|
@@ -249,7 +592,7 @@ var QueryMapper = class {
|
|
|
249
592
|
nodes: {
|
|
250
593
|
filter: { and: baseFilters }
|
|
251
594
|
},
|
|
252
|
-
sort: this.sortMapper.map(
|
|
595
|
+
sort: this.sortMapper.map(sort, rootView),
|
|
253
596
|
limit
|
|
254
597
|
}
|
|
255
598
|
};
|
|
@@ -531,6 +874,92 @@ var QueryResultMapper = class {
|
|
|
531
874
|
return entry;
|
|
532
875
|
}
|
|
533
876
|
};
|
|
877
|
+
var nodeMetadataSchema = {
|
|
878
|
+
instanceType: zod.z.literal("node").optional(),
|
|
879
|
+
space: zod.z.string(),
|
|
880
|
+
externalId: zod.z.string(),
|
|
881
|
+
version: zod.z.number().optional(),
|
|
882
|
+
createdTime: zod.z.number().optional(),
|
|
883
|
+
deletedTime: zod.z.number().optional(),
|
|
884
|
+
lastUpdatedTime: zod.z.number().optional(),
|
|
885
|
+
_edges: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
886
|
+
};
|
|
887
|
+
function isListRelation(property) {
|
|
888
|
+
if (isViewPropertyDefinition(property)) {
|
|
889
|
+
return isListDirectRelation(property);
|
|
890
|
+
}
|
|
891
|
+
if (isReverseDirectRelation(property)) {
|
|
892
|
+
return property.connectionType === "multi_reverse_direct_relation" || property.targetsList === true;
|
|
893
|
+
}
|
|
894
|
+
return isEdgeConnection(property);
|
|
895
|
+
}
|
|
896
|
+
function isRecord2(value) {
|
|
897
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
898
|
+
}
|
|
899
|
+
var QueryResultValidator = class {
|
|
900
|
+
constructor(viewMapper) {
|
|
901
|
+
this.viewMapper = viewMapper;
|
|
902
|
+
}
|
|
903
|
+
async parseItems(rootViewExternalId, items, select) {
|
|
904
|
+
const rootView = await this.viewMapper.getView(rootViewExternalId);
|
|
905
|
+
const schema = await this.buildResultSchema(rootView, MAX_DEPENDENCY_DEPTH, select);
|
|
906
|
+
const result = zod.z.array(schema).safeParse(items);
|
|
907
|
+
if (!result.success) {
|
|
908
|
+
throw new Error(
|
|
909
|
+
`Invalid query result:
|
|
910
|
+
${result.error.issues.map((issue) => `- ${issue.path.map(String).join(".")}: ${issue.message}`).join("\n")}`
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
return result.data;
|
|
914
|
+
}
|
|
915
|
+
async buildResultSchema(view, remainingDepth, select) {
|
|
916
|
+
const shape = { ...nodeMetadataSchema };
|
|
917
|
+
const includeAllProperties = select == null || select._all === true;
|
|
918
|
+
for (const [name, property] of Object.entries(view.properties)) {
|
|
919
|
+
const isSelected = includeAllProperties || name in select;
|
|
920
|
+
if (!isSelected) continue;
|
|
921
|
+
const nestedSelect = isRecord2(select?.[name]) ? select[name] : void 0;
|
|
922
|
+
if (isViewPropertyDefinition(property)) {
|
|
923
|
+
const relationSource = getDirectRelationSource(property);
|
|
924
|
+
if (relationSource) {
|
|
925
|
+
shape[name] = await this.buildRelationSchema(
|
|
926
|
+
property,
|
|
927
|
+
relationSource.externalId,
|
|
928
|
+
remainingDepth,
|
|
929
|
+
nestedSelect
|
|
930
|
+
);
|
|
931
|
+
} else {
|
|
932
|
+
shape[name] = propertyValueSchema(property, { dateMode: "coerce" }).optional();
|
|
933
|
+
}
|
|
934
|
+
continue;
|
|
935
|
+
}
|
|
936
|
+
if (isReverseDirectRelation(property) || isEdgeConnection(property)) {
|
|
937
|
+
shape[name] = await this.buildRelationSchema(
|
|
938
|
+
property,
|
|
939
|
+
property.source.externalId,
|
|
940
|
+
remainingDepth,
|
|
941
|
+
nestedSelect
|
|
942
|
+
);
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
const schema = zod.z.object(shape);
|
|
946
|
+
return includeAllProperties ? schema.strict() : schema;
|
|
947
|
+
}
|
|
948
|
+
async buildRelationSchema(property, targetViewExternalId, remainingDepth, select) {
|
|
949
|
+
const isList = isListRelation(property);
|
|
950
|
+
const fallbackSchema = isViewPropertyDefinition(property) ? propertyValueSchema(property, { dateMode: "coerce" }) : zod.z.unknown();
|
|
951
|
+
if (remainingDepth <= 0 || select == null) {
|
|
952
|
+
return fallbackSchema.optional();
|
|
953
|
+
}
|
|
954
|
+
const targetView = await this.viewMapper.getView(targetViewExternalId);
|
|
955
|
+
const nestedSchema = await this.buildResultSchema(targetView, remainingDepth - 1, select);
|
|
956
|
+
if (isViewPropertyDefinition(property)) {
|
|
957
|
+
const nestedRelationSchema = isList ? zod.z.array(nestedSchema) : nestedSchema;
|
|
958
|
+
return zod.z.union([nestedRelationSchema, fallbackSchema]).optional();
|
|
959
|
+
}
|
|
960
|
+
return (isList ? zod.z.array(nestedSchema) : nestedSchema).optional();
|
|
961
|
+
}
|
|
962
|
+
};
|
|
534
963
|
|
|
535
964
|
// src/mappers/view-mapper.ts
|
|
536
965
|
var ViewMapper = class {
|
|
@@ -680,15 +1109,21 @@ function buildDependenciesQuery(previousQuery, nodesParent, nodesChildren, leafC
|
|
|
680
1109
|
}
|
|
681
1110
|
|
|
682
1111
|
// src/client.ts
|
|
683
|
-
var
|
|
684
|
-
constructor(client, dataModelId) {
|
|
1112
|
+
var IndustrialModelClient = class {
|
|
1113
|
+
constructor(client, dataModelId, options = {}) {
|
|
685
1114
|
const cognite = createCogniteAdapter(client);
|
|
686
1115
|
this.cognite = cognite;
|
|
687
1116
|
const viewMapper = new ViewMapper(cognite, dataModelId);
|
|
688
1117
|
this.queryMapper = new QueryMapper(viewMapper);
|
|
689
1118
|
this.resultMapper = new QueryResultMapper(viewMapper);
|
|
1119
|
+
this.resultValidator = new QueryResultValidator(viewMapper);
|
|
1120
|
+
this.validateResults = options.validateResults ?? false;
|
|
690
1121
|
}
|
|
691
|
-
|
|
1122
|
+
query() {
|
|
1123
|
+
const execute = (options) => this.queryInternal(options);
|
|
1124
|
+
return execute;
|
|
1125
|
+
}
|
|
1126
|
+
async queryInternal(options) {
|
|
692
1127
|
const { viewExternalId, limit = DEFAULT_LIMIT } = options;
|
|
693
1128
|
const allPages = options.limit === -1;
|
|
694
1129
|
const cogniteQuery = await this.queryMapper.map(options);
|
|
@@ -704,11 +1139,12 @@ var IndustrialModel = class {
|
|
|
704
1139
|
mapNodesAndEdges(queryResult),
|
|
705
1140
|
dependenciesData
|
|
706
1141
|
);
|
|
707
|
-
const
|
|
1142
|
+
const mappedPageResult = await this.resultMapper.mapNodes(viewExternalId, queryResultData);
|
|
1143
|
+
const pageResult = this.validateResults ? await this.resultValidator.parseItems(viewExternalId, mappedPageResult, options.select) : mappedPageResult;
|
|
708
1144
|
const nextCursor = queryResult.nextCursor[viewExternalId] ?? null;
|
|
709
|
-
data.push(...pageResult);
|
|
710
1145
|
const isLastPage = pageResult.length < limit || !nextCursor;
|
|
711
1146
|
const resolvedCursor = isLastPage ? null : nextCursor;
|
|
1147
|
+
data.push(...pageResult);
|
|
712
1148
|
if (!isLastPage && resolvedCursor !== null) {
|
|
713
1149
|
cogniteQuery.cursors = { [viewExternalId]: resolvedCursor };
|
|
714
1150
|
}
|
|
@@ -735,6 +1171,8 @@ var IndustrialModel = class {
|
|
|
735
1171
|
}
|
|
736
1172
|
};
|
|
737
1173
|
|
|
738
|
-
exports.
|
|
1174
|
+
exports.IndustrialModelClient = IndustrialModelClient;
|
|
1175
|
+
exports.buildViewSchema = buildViewSchema;
|
|
1176
|
+
exports.nodeIdSchema = nodeIdSchema;
|
|
739
1177
|
//# sourceMappingURL=index.cjs.map
|
|
740
1178
|
//# sourceMappingURL=index.cjs.map
|