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/README.md
CHANGED
|
@@ -21,11 +21,16 @@ npm install industrial-model
|
|
|
21
21
|
npm install @cognite/sdk
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
+
## Requirements
|
|
25
|
+
|
|
26
|
+
- Node.js `>=20`
|
|
27
|
+
- `@cognite/sdk` `^10.10.0` (peer dependency)
|
|
28
|
+
|
|
24
29
|
## Quick start
|
|
25
30
|
|
|
26
31
|
```ts
|
|
27
32
|
import { CogniteClient } from "@cognite/sdk";
|
|
28
|
-
import {
|
|
33
|
+
import { IndustrialModelClient } from "industrial-model";
|
|
29
34
|
|
|
30
35
|
const client = new CogniteClient({
|
|
31
36
|
appId: "my-app",
|
|
@@ -34,13 +39,13 @@ const client = new CogniteClient({
|
|
|
34
39
|
oidcTokenProvider: async () => getAccessToken(),
|
|
35
40
|
});
|
|
36
41
|
|
|
37
|
-
const model = new
|
|
42
|
+
const model = new IndustrialModelClient(client, {
|
|
38
43
|
space: "cdf_cdm",
|
|
39
44
|
externalId: "CogniteCore",
|
|
40
45
|
version: "v1",
|
|
41
46
|
});
|
|
42
47
|
|
|
43
|
-
const { items } = await model.query({
|
|
48
|
+
const { items } = await model.query<{ name: string; description: string }>()({
|
|
44
49
|
viewExternalId: "CogniteAsset",
|
|
45
50
|
select: { name: true, description: true },
|
|
46
51
|
filters: { name: { prefix: "Pump" } },
|
|
@@ -57,7 +62,7 @@ const { items } = await model.query({
|
|
|
57
62
|
| Relations | [Parent/root](#query-assets-with-parent-and-root-relations), [Path](#query-assets-with-their-full-path), [Children](#query-child-assets-reverse-relation), [Edges](#traverse-edge-relations-360-images-on-3d-objects) |
|
|
58
63
|
| Filters | [AND/OR/NOT](#combine-filters-with-and--or--not), [Nested](#filter-on-related-nodes), [Tags](#filter-assets-by-tags), [Batch IDs](#filter-by-multiple-external-ids) |
|
|
59
64
|
| Select & sort | [Select all scalars](#select-all-scalar-fields), [Multi-field sort](#sort-by-multiple-fields) |
|
|
60
|
-
| Pagination | [Manual cursor loop](#paginate-through-all-assets), [Fetch all pages](#fetch-all-pages-
|
|
65
|
+
| Pagination | [Manual cursor loop](#paginate-through-all-assets), [Fetch all pages](#fetch-all-pages-automatically) |
|
|
61
66
|
| Advanced | [Custom data model](#use-a-custom-data-model), [Full query](#full-example-assets-equipment-and-filters) |
|
|
62
67
|
|
|
63
68
|
All examples below use the [Cognite Core Data Model](https://docs.cognite.com/cdf/data_modeling/reference_data_models/cognite_core/), space `cdf_cdm`, version `v1`.
|
|
@@ -65,52 +70,44 @@ All examples below use the [Cognite Core Data Model](https://docs.cognite.com/cd
|
|
|
65
70
|
### Shared type definitions
|
|
66
71
|
|
|
67
72
|
```ts
|
|
68
|
-
import type {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
sourceUpdatedTime: string;
|
|
78
|
-
parent?: NodeId;
|
|
79
|
-
root?: NodeId;
|
|
80
|
-
path: NodeId[];
|
|
81
|
-
assetClass?: NodeId;
|
|
82
|
-
type?: NodeId;
|
|
83
|
-
source?: NodeId;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
type CogniteAssetRelations = {
|
|
87
|
-
parent: CogniteAsset;
|
|
88
|
-
root: CogniteAsset;
|
|
89
|
-
path: CogniteAsset[];
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
type CogniteEquipment = {
|
|
93
|
-
name: string;
|
|
94
|
-
description: string;
|
|
95
|
-
manufacturer: string;
|
|
96
|
-
serialNumber: string;
|
|
97
|
-
tags: string[];
|
|
98
|
-
asset?: NodeId;
|
|
99
|
-
equipmentType?: NodeId;
|
|
100
|
-
source?: NodeId;
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
type CogniteTimeSeries = {
|
|
73
|
+
import type {
|
|
74
|
+
IndustrialModel,
|
|
75
|
+
ModelProps,
|
|
76
|
+
ModelRelations,
|
|
77
|
+
NodeId,
|
|
78
|
+
QueryResultItem,
|
|
79
|
+
} from "industrial-model";
|
|
80
|
+
|
|
81
|
+
type CogniteAssetClass = IndustrialModel<{
|
|
104
82
|
name: string;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
83
|
+
code: string;
|
|
84
|
+
}>;
|
|
85
|
+
|
|
86
|
+
type CogniteAsset = IndustrialModel<
|
|
87
|
+
{
|
|
88
|
+
name: string;
|
|
89
|
+
description: string;
|
|
90
|
+
tags: string[];
|
|
91
|
+
aliases: string[];
|
|
92
|
+
sourceId: string;
|
|
93
|
+
sourceCreatedTime: string;
|
|
94
|
+
sourceUpdatedTime: string;
|
|
95
|
+
parent?: NodeId;
|
|
96
|
+
root?: NodeId;
|
|
97
|
+
path: NodeId[];
|
|
98
|
+
assetClass?: NodeId;
|
|
99
|
+
type?: NodeId;
|
|
100
|
+
source?: NodeId;
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
parent?: CogniteAsset;
|
|
104
|
+
root?: CogniteAsset;
|
|
105
|
+
path?: CogniteAsset[];
|
|
106
|
+
assetClass?: CogniteAssetClass;
|
|
107
|
+
}
|
|
108
|
+
>;
|
|
109
|
+
|
|
110
|
+
type CogniteActivity = IndustrialModel<{
|
|
114
111
|
name: string;
|
|
115
112
|
description: string;
|
|
116
113
|
startTime: string;
|
|
@@ -120,27 +117,60 @@ type CogniteActivity = {
|
|
|
120
117
|
assets: NodeId[];
|
|
121
118
|
equipment: NodeId[];
|
|
122
119
|
timeSeries: NodeId[];
|
|
123
|
-
}
|
|
120
|
+
}>;
|
|
121
|
+
|
|
122
|
+
type CogniteEquipment = IndustrialModel<
|
|
123
|
+
{
|
|
124
|
+
name: string;
|
|
125
|
+
description: string;
|
|
126
|
+
manufacturer: string;
|
|
127
|
+
serialNumber: string;
|
|
128
|
+
tags: string[];
|
|
129
|
+
asset?: NodeId;
|
|
130
|
+
equipmentType?: NodeId;
|
|
131
|
+
source?: NodeId;
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
asset?: CogniteAsset;
|
|
135
|
+
activities?: CogniteActivity[];
|
|
136
|
+
}
|
|
137
|
+
>;
|
|
124
138
|
|
|
125
|
-
type CogniteUnit = {
|
|
139
|
+
type CogniteUnit = IndustrialModel<{
|
|
126
140
|
name: string;
|
|
127
141
|
symbol: string;
|
|
128
142
|
quantity: string;
|
|
129
143
|
source: string;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
type
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
+
}>;
|
|
145
|
+
|
|
146
|
+
type CogniteTimeSeries = IndustrialModel<
|
|
147
|
+
{
|
|
148
|
+
name: string;
|
|
149
|
+
description: string;
|
|
150
|
+
isStep: boolean;
|
|
151
|
+
sourceUnit: string;
|
|
152
|
+
unit?: NodeId;
|
|
153
|
+
assets: NodeId[];
|
|
154
|
+
equipment: NodeId[];
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
unit?: CogniteUnit;
|
|
158
|
+
}
|
|
159
|
+
>;
|
|
160
|
+
|
|
161
|
+
type Cognite360Image = IndustrialModel<{
|
|
162
|
+
takenAt: string;
|
|
163
|
+
}>;
|
|
164
|
+
|
|
165
|
+
type Cognite3DObject = IndustrialModel<
|
|
166
|
+
{
|
|
167
|
+
name: string;
|
|
168
|
+
description: string;
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
images360?: Cognite360Image[];
|
|
172
|
+
}
|
|
173
|
+
>;
|
|
144
174
|
```
|
|
145
175
|
|
|
146
176
|
---
|
|
@@ -150,7 +180,7 @@ type Cognite360ImageRelations = {
|
|
|
150
180
|
Fetch the first 100 assets whose name starts with `"Pump"`, sorted alphabetically.
|
|
151
181
|
|
|
152
182
|
```ts
|
|
153
|
-
const { items, cursor } = await model.query<CogniteAsset>({
|
|
183
|
+
const { items, cursor } = await model.query<CogniteAsset>()({
|
|
154
184
|
viewExternalId: "CogniteAsset",
|
|
155
185
|
select: {
|
|
156
186
|
name: true,
|
|
@@ -161,7 +191,7 @@ const { items, cursor } = await model.query<CogniteAsset>({
|
|
|
161
191
|
filters: {
|
|
162
192
|
name: { prefix: "Pump" },
|
|
163
193
|
},
|
|
164
|
-
|
|
194
|
+
sort: { name: "ascending" },
|
|
165
195
|
limit: 100,
|
|
166
196
|
});
|
|
167
197
|
```
|
|
@@ -171,7 +201,7 @@ const { items, cursor } = await model.query<CogniteAsset>({
|
|
|
171
201
|
### Query a single asset by externalId
|
|
172
202
|
|
|
173
203
|
```ts
|
|
174
|
-
const { items } = await model.query<CogniteAsset>({
|
|
204
|
+
const { items } = await model.query<CogniteAsset>()({
|
|
175
205
|
viewExternalId: "CogniteAsset",
|
|
176
206
|
select: { name: true, description: true, tags: true },
|
|
177
207
|
filters: {
|
|
@@ -189,7 +219,7 @@ const asset = items[0];
|
|
|
189
219
|
Traverse up the asset hierarchy — fetch each asset alongside its direct parent and the root of the tree.
|
|
190
220
|
|
|
191
221
|
```ts
|
|
192
|
-
const { items } = await model.query<CogniteAsset
|
|
222
|
+
const { items } = await model.query<CogniteAsset>()({
|
|
193
223
|
viewExternalId: "CogniteAsset",
|
|
194
224
|
select: {
|
|
195
225
|
name: true,
|
|
@@ -210,6 +240,8 @@ const { items } = await model.query<CogniteAsset, CogniteAssetRelations>({
|
|
|
210
240
|
},
|
|
211
241
|
limit: 50,
|
|
212
242
|
});
|
|
243
|
+
|
|
244
|
+
const firstParentName = items[0]?.parent?.name;
|
|
213
245
|
```
|
|
214
246
|
|
|
215
247
|
---
|
|
@@ -219,7 +251,7 @@ const { items } = await model.query<CogniteAsset, CogniteAssetRelations>({
|
|
|
219
251
|
The `path` property is a list of `NodeId` references representing the ancestor chain. Use it to reconstruct breadcrumbs.
|
|
220
252
|
|
|
221
253
|
```ts
|
|
222
|
-
const { items } = await model.query<CogniteAsset
|
|
254
|
+
const { items } = await model.query<CogniteAsset>()({
|
|
223
255
|
viewExternalId: "CogniteAsset",
|
|
224
256
|
select: {
|
|
225
257
|
name: true,
|
|
@@ -239,7 +271,7 @@ const { items } = await model.query<CogniteAsset, CogniteAssetRelations>({
|
|
|
239
271
|
### Query equipment linked to an asset
|
|
240
272
|
|
|
241
273
|
```ts
|
|
242
|
-
const { items } = await model.query<CogniteEquipment>({
|
|
274
|
+
const { items } = await model.query<CogniteEquipment>()({
|
|
243
275
|
viewExternalId: "CogniteEquipment",
|
|
244
276
|
select: {
|
|
245
277
|
name: true,
|
|
@@ -252,7 +284,7 @@ const { items } = await model.query<CogniteEquipment>({
|
|
|
252
284
|
asset: { eq: { space: "my-space", externalId: "WMT:VAL" } },
|
|
253
285
|
manufacturer: { exists: true },
|
|
254
286
|
},
|
|
255
|
-
|
|
287
|
+
sort: { name: "ascending" },
|
|
256
288
|
limit: 50,
|
|
257
289
|
});
|
|
258
290
|
```
|
|
@@ -262,7 +294,7 @@ const { items } = await model.query<CogniteEquipment>({
|
|
|
262
294
|
### Query time series with their unit
|
|
263
295
|
|
|
264
296
|
```ts
|
|
265
|
-
const { items } = await model.query<CogniteTimeSeries
|
|
297
|
+
const { items } = await model.query<CogniteTimeSeries>()({
|
|
266
298
|
viewExternalId: "CogniteTimeSeries",
|
|
267
299
|
select: {
|
|
268
300
|
name: true,
|
|
@@ -288,7 +320,7 @@ const { items } = await model.query<CogniteTimeSeries, CogniteUnitRelations>({
|
|
|
288
320
|
### Query activities in a time window
|
|
289
321
|
|
|
290
322
|
```ts
|
|
291
|
-
const { items } = await model.query<CogniteActivity>({
|
|
323
|
+
const { items } = await model.query<CogniteActivity>()({
|
|
292
324
|
viewExternalId: "CogniteActivity",
|
|
293
325
|
select: {
|
|
294
326
|
name: true,
|
|
@@ -301,7 +333,7 @@ const { items } = await model.query<CogniteActivity>({
|
|
|
301
333
|
filters: {
|
|
302
334
|
startTime: { gte: "2024-01-01T00:00:00Z", lte: "2024-12-31T23:59:59Z" },
|
|
303
335
|
},
|
|
304
|
-
|
|
336
|
+
sort: { startTime: "ascending" },
|
|
305
337
|
limit: 500,
|
|
306
338
|
});
|
|
307
339
|
```
|
|
@@ -313,7 +345,7 @@ const { items } = await model.query<CogniteActivity>({
|
|
|
313
345
|
Fetch assets that are either tagged `"critical"` or have a name starting with `"Compressor"`, but exclude those from source `"legacy-system"`.
|
|
314
346
|
|
|
315
347
|
```ts
|
|
316
|
-
const { items } = await model.query<CogniteAsset>({
|
|
348
|
+
const { items } = await model.query<CogniteAsset>()({
|
|
317
349
|
viewExternalId: "CogniteAsset",
|
|
318
350
|
select: { name: true, tags: true, sourceId: true },
|
|
319
351
|
filters: {
|
|
@@ -333,10 +365,10 @@ const { items } = await model.query<CogniteAsset>({
|
|
|
333
365
|
|
|
334
366
|
```ts
|
|
335
367
|
let cursor: string | null = null;
|
|
336
|
-
const allAssets:
|
|
368
|
+
const allAssets: QueryResultItem<CogniteAsset, { name: true; description: true }>[] = [];
|
|
337
369
|
|
|
338
370
|
do {
|
|
339
|
-
const result = await model.query<CogniteAsset>({
|
|
371
|
+
const result = await model.query<CogniteAsset>()({
|
|
340
372
|
viewExternalId: "CogniteAsset",
|
|
341
373
|
select: { name: true, description: true },
|
|
342
374
|
limit: 1000,
|
|
@@ -352,19 +384,19 @@ console.log(`Total assets: ${allAssets.length}`);
|
|
|
352
384
|
|
|
353
385
|
---
|
|
354
386
|
|
|
355
|
-
### Fetch all pages
|
|
387
|
+
### Fetch all pages automatically
|
|
356
388
|
|
|
357
|
-
Pass `limit: -1` to
|
|
389
|
+
Pass `limit: -1` to follow root-view cursors until every page is loaded. The SDK issues multiple `instances.query` calls (1000 items per page by default). The returned `cursor` is always `null`.
|
|
358
390
|
|
|
359
391
|
```ts
|
|
360
|
-
const { items } = await model.query<CogniteAsset>({
|
|
392
|
+
const { items } = await model.query<CogniteAsset>()({
|
|
361
393
|
viewExternalId: "CogniteAsset",
|
|
362
394
|
select: { name: true, description: true },
|
|
363
395
|
filters: { tags: { containsAny: ["production"] } },
|
|
364
396
|
limit: -1,
|
|
365
397
|
});
|
|
366
398
|
|
|
367
|
-
console.log(`Loaded ${items.length} assets
|
|
399
|
+
console.log(`Loaded ${items.length} assets across all pages`);
|
|
368
400
|
```
|
|
369
401
|
|
|
370
402
|
---
|
|
@@ -374,7 +406,7 @@ console.log(`Loaded ${items.length} assets in one request chain`);
|
|
|
374
406
|
Use `_all` to include every scalar property on the view without listing them individually. Relation fields are returned as `NodeId` references but are not expanded — add nested `select` blocks when you need related data.
|
|
375
407
|
|
|
376
408
|
```ts
|
|
377
|
-
const { items } = await model.query<CogniteAsset>({
|
|
409
|
+
const { items } = await model.query<CogniteAsset>()({
|
|
378
410
|
viewExternalId: "CogniteAsset",
|
|
379
411
|
select: { _all: true },
|
|
380
412
|
limit: 50,
|
|
@@ -386,7 +418,7 @@ const { items } = await model.query<CogniteAsset>({
|
|
|
386
418
|
Combine `_all` with explicit relation expansion:
|
|
387
419
|
|
|
388
420
|
```ts
|
|
389
|
-
const { items } = await model.query<CogniteAsset
|
|
421
|
+
const { items } = await model.query<CogniteAsset>()({
|
|
390
422
|
viewExternalId: "CogniteAsset",
|
|
391
423
|
select: {
|
|
392
424
|
_all: true,
|
|
@@ -401,7 +433,7 @@ const { items } = await model.query<CogniteAsset, CogniteAssetRelations>({
|
|
|
401
433
|
### Filter by multiple external IDs
|
|
402
434
|
|
|
403
435
|
```ts
|
|
404
|
-
const { items } = await model.query<CogniteAsset>({
|
|
436
|
+
const { items } = await model.query<CogniteAsset>()({
|
|
405
437
|
viewExternalId: "CogniteAsset",
|
|
406
438
|
select: { name: true, description: true },
|
|
407
439
|
filters: {
|
|
@@ -418,7 +450,7 @@ const { items } = await model.query<CogniteAsset>({
|
|
|
418
450
|
|
|
419
451
|
```ts
|
|
420
452
|
// Match assets that have at least one of these tags
|
|
421
|
-
const critical = await model.query<CogniteAsset>({
|
|
453
|
+
const critical = await model.query<CogniteAsset>()({
|
|
422
454
|
viewExternalId: "CogniteAsset",
|
|
423
455
|
select: { name: true, tags: true },
|
|
424
456
|
filters: { tags: { containsAny: ["critical", "safety"] } },
|
|
@@ -426,7 +458,7 @@ const critical = await model.query<CogniteAsset>({
|
|
|
426
458
|
});
|
|
427
459
|
|
|
428
460
|
// Match assets that must have every tag
|
|
429
|
-
const fullyTagged = await model.query<CogniteAsset>({
|
|
461
|
+
const fullyTagged = await model.query<CogniteAsset>()({
|
|
430
462
|
viewExternalId: "CogniteAsset",
|
|
431
463
|
select: { name: true, tags: true },
|
|
432
464
|
filters: { tags: { containsAll: ["production", "verified"] } },
|
|
@@ -442,7 +474,7 @@ Filter the root view based on properties of a direct or nested relation. This us
|
|
|
442
474
|
|
|
443
475
|
```ts
|
|
444
476
|
// Assets whose parent is named "Site Root"
|
|
445
|
-
const { items } = await model.query<CogniteAsset>({
|
|
477
|
+
const { items } = await model.query<CogniteAsset>()({
|
|
446
478
|
viewExternalId: "CogniteAsset",
|
|
447
479
|
select: { name: true, parent: { name: true } },
|
|
448
480
|
filters: {
|
|
@@ -452,7 +484,7 @@ const { items } = await model.query<CogniteAsset>({
|
|
|
452
484
|
});
|
|
453
485
|
|
|
454
486
|
// Assets whose parent's asset class code is "PUMP"
|
|
455
|
-
const pumpsByClass = await model.query<CogniteAsset>({
|
|
487
|
+
const pumpsByClass = await model.query<CogniteAsset>()({
|
|
456
488
|
viewExternalId: "CogniteAsset",
|
|
457
489
|
select: {
|
|
458
490
|
name: true,
|
|
@@ -465,7 +497,7 @@ const pumpsByClass = await model.query<CogniteAsset>({
|
|
|
465
497
|
});
|
|
466
498
|
|
|
467
499
|
// Combine root and nested conditions
|
|
468
|
-
const filtered = await model.query<CogniteAsset>({
|
|
500
|
+
const filtered = await model.query<CogniteAsset>()({
|
|
469
501
|
viewExternalId: "CogniteAsset",
|
|
470
502
|
select: { name: true, parent: { name: true } },
|
|
471
503
|
filters: {
|
|
@@ -482,14 +514,15 @@ const filtered = await model.query<CogniteAsset>({
|
|
|
482
514
|
|
|
483
515
|
### Query child assets (reverse relation)
|
|
484
516
|
|
|
485
|
-
Declare reverse relations in the
|
|
517
|
+
Declare reverse relations in the `IndustrialModel<TProps, TRelations>` metadata. The library resolves the correct traversal direction from your data model.
|
|
486
518
|
|
|
487
519
|
```ts
|
|
488
|
-
type AssetWithChildren =
|
|
489
|
-
|
|
490
|
-
}
|
|
520
|
+
type AssetWithChildren = IndustrialModel<
|
|
521
|
+
ModelProps<CogniteAsset>,
|
|
522
|
+
ModelRelations<CogniteAsset> & { children?: CogniteAsset[] }
|
|
523
|
+
>;
|
|
491
524
|
|
|
492
|
-
const { items } = await model.query<AssetWithChildren
|
|
525
|
+
const { items } = await model.query<AssetWithChildren>()({
|
|
493
526
|
viewExternalId: "CogniteAsset",
|
|
494
527
|
select: {
|
|
495
528
|
name: true,
|
|
@@ -511,7 +544,7 @@ const { items } = await model.query<AssetWithChildren, { children: CogniteAsset
|
|
|
511
544
|
Some relations are modeled as edges rather than direct node links. Select them the same way — the SDK builds the edge hop automatically.
|
|
512
545
|
|
|
513
546
|
```ts
|
|
514
|
-
const { items } = await model.query<Cognite3DObject
|
|
547
|
+
const { items } = await model.query<Cognite3DObject>()({
|
|
515
548
|
viewExternalId: "Cognite3DObject",
|
|
516
549
|
select: {
|
|
517
550
|
name: true,
|
|
@@ -531,10 +564,10 @@ const { items } = await model.query<Cognite3DObject, Cognite360ImageRelations>({
|
|
|
531
564
|
Sort clauses apply to primitive fields on the root view, including node-level properties like `externalId`.
|
|
532
565
|
|
|
533
566
|
```ts
|
|
534
|
-
const { items } = await model.query<CogniteAsset>({
|
|
567
|
+
const { items } = await model.query<CogniteAsset>()({
|
|
535
568
|
viewExternalId: "CogniteAsset",
|
|
536
569
|
select: { name: true, sourceId: true },
|
|
537
|
-
|
|
570
|
+
sort: {
|
|
538
571
|
name: "ascending",
|
|
539
572
|
externalId: "descending",
|
|
540
573
|
},
|
|
@@ -546,22 +579,22 @@ const { items } = await model.query<CogniteAsset>({
|
|
|
546
579
|
|
|
547
580
|
### Use a custom data model
|
|
548
581
|
|
|
549
|
-
Point the client at any FDM in your project — not only Cognite Core.
|
|
582
|
+
Point the client at any FDM in your project — not only Cognite Core. Scalar fields work with a plain object type; use `IndustrialModel<TProps, TRelations>` when you need relation selects, filters, or inference.
|
|
550
583
|
|
|
551
584
|
```ts
|
|
552
|
-
const model = new
|
|
585
|
+
const model = new IndustrialModelClient(client, {
|
|
553
586
|
space: "my-custom-space",
|
|
554
587
|
externalId: "MyPlantModel",
|
|
555
588
|
version: "1",
|
|
556
589
|
});
|
|
557
590
|
|
|
558
|
-
type PlantArea = {
|
|
591
|
+
type PlantArea = IndustrialModel<{
|
|
559
592
|
name: string;
|
|
560
593
|
code: string;
|
|
561
594
|
site?: NodeId;
|
|
562
|
-
}
|
|
595
|
+
}>;
|
|
563
596
|
|
|
564
|
-
const { items } = await model.query<PlantArea>({
|
|
597
|
+
const { items } = await model.query<PlantArea>()({
|
|
565
598
|
viewExternalId: "PlantArea",
|
|
566
599
|
select: { name: true, code: true, site: true },
|
|
567
600
|
filters: { code: { prefix: "AREA-" } },
|
|
@@ -576,11 +609,12 @@ const { items } = await model.query<PlantArea>({
|
|
|
576
609
|
A single query combining nested selects, nested filters, sorting, and pagination.
|
|
577
610
|
|
|
578
611
|
```ts
|
|
579
|
-
type AssetWithRelations =
|
|
580
|
-
|
|
581
|
-
}
|
|
612
|
+
type AssetWithRelations = IndustrialModel<
|
|
613
|
+
ModelProps<CogniteAsset>,
|
|
614
|
+
ModelRelations<CogniteAsset> & { children?: CogniteAsset[] }
|
|
615
|
+
>;
|
|
582
616
|
|
|
583
|
-
const { items, cursor } = await model.query<AssetWithRelations
|
|
617
|
+
const { items, cursor } = await model.query<AssetWithRelations>()({
|
|
584
618
|
viewExternalId: "CogniteAsset",
|
|
585
619
|
select: {
|
|
586
620
|
name: true,
|
|
@@ -599,14 +633,14 @@ const { items, cursor } = await model.query<AssetWithRelations, CogniteAssetRela
|
|
|
599
633
|
{ sourceId: { eq: "sap" } },
|
|
600
634
|
],
|
|
601
635
|
},
|
|
602
|
-
|
|
636
|
+
sort: { name: "ascending" },
|
|
603
637
|
limit: 25,
|
|
604
638
|
cursor: null,
|
|
605
639
|
});
|
|
606
640
|
|
|
607
641
|
// Follow-up page
|
|
608
642
|
if (cursor) {
|
|
609
|
-
const next = await model.query<AssetWithRelations
|
|
643
|
+
const next = await model.query<AssetWithRelations>()({
|
|
610
644
|
viewExternalId: "CogniteAsset",
|
|
611
645
|
select: {
|
|
612
646
|
name: true,
|
|
@@ -618,7 +652,7 @@ if (cursor) {
|
|
|
618
652
|
name: { prefix: "WMT" },
|
|
619
653
|
parent: { name: { exists: true } },
|
|
620
654
|
},
|
|
621
|
-
|
|
655
|
+
sort: { name: "ascending" },
|
|
622
656
|
limit: 25,
|
|
623
657
|
cursor,
|
|
624
658
|
});
|
|
@@ -629,33 +663,86 @@ if (cursor) {
|
|
|
629
663
|
|
|
630
664
|
## API
|
|
631
665
|
|
|
632
|
-
###
|
|
666
|
+
### Exports
|
|
667
|
+
|
|
668
|
+
| Symbol | Description |
|
|
669
|
+
|--------|-------------|
|
|
670
|
+
| `IndustrialModelClient` | Main client |
|
|
671
|
+
| `IndustrialModel`, `ModelProps`, `ModelRelations` | Type helpers for models and relations |
|
|
672
|
+
| `NodeId`, `DataModelId` | Instance and data-model identifiers |
|
|
673
|
+
| `QueryOptions`, `QuerySelect`, `WhereInput`, `SortInput` | Query input types |
|
|
674
|
+
| `QueryResult`, `QueryResultItem`, `QueryResultMetadata` | Query output types |
|
|
675
|
+
| `buildViewSchema`, `nodeIdSchema` | Zod schemas built from Cognite view metadata |
|
|
676
|
+
| `SortDirection` | `"ascending"` \| `"descending"` |
|
|
677
|
+
|
|
678
|
+
### `new IndustrialModelClient(client, dataModelId, options?)`
|
|
633
679
|
|
|
634
680
|
| Parameter | Type | Description |
|
|
635
681
|
|-----------|------|-------------|
|
|
636
682
|
| `client` | `CogniteClient` | Authenticated Cognite SDK client |
|
|
637
683
|
| `dataModelId` | `DataModelId` | Space, externalId, and version of the data model |
|
|
684
|
+
| `options.validateResults` | `boolean` | Optional. Validate and parse query results with Zod schemas derived from Cognite view metadata |
|
|
685
|
+
|
|
686
|
+
On the first query, view definitions are loaded from CDF and cached for the lifetime of the client instance.
|
|
638
687
|
|
|
639
|
-
|
|
688
|
+
Query inputs are validated against the loaded view metadata before the Cognite request is built. Result validation is opt-in because it parses every returned item:
|
|
689
|
+
|
|
690
|
+
```ts
|
|
691
|
+
const model = new IndustrialModelClient(client, dataModelId, {
|
|
692
|
+
validateResults: true,
|
|
693
|
+
});
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
When `validateResults` is enabled, Cognite `date` and `timestamp` view properties are converted to JavaScript `Date` objects. Without this option, result values are returned as Cognite provides them, usually ISO strings for timestamps.
|
|
697
|
+
|
|
698
|
+
### `model.query<TModel>()(options)`
|
|
640
699
|
|
|
641
700
|
| Option | Type | Description |
|
|
642
701
|
|--------|------|-------------|
|
|
643
702
|
| `viewExternalId` | `string` | The view to query |
|
|
644
|
-
| `select` | `QuerySelect<
|
|
645
|
-
| `filters` | `WhereInput<
|
|
646
|
-
| `
|
|
647
|
-
| `limit` | `number` |
|
|
703
|
+
| `select` | `QuerySelect<TModel>` | Optional. Defaults to `{ _all: true }` (all scalar fields). Use `_all: true` explicitly or list fields; use nested objects for relations |
|
|
704
|
+
| `filters` | `WhereInput<TModel>` | Filter conditions (supports nested relation filters) |
|
|
705
|
+
| `sort` | `SortInput<TModel>` | Sort by primitive fields on the **root** view only |
|
|
706
|
+
| `limit` | `number` | Root page size (default `1000`). Use `-1` to fetch all root pages automatically |
|
|
648
707
|
| `cursor` | `string \| null` | Pagination cursor from a previous response |
|
|
649
708
|
|
|
650
|
-
|
|
709
|
+
`query()` uses a curried form so you can supply the model types first and still get return-type inference from `select`.
|
|
710
|
+
|
|
711
|
+
Use `IndustrialModel<TProps, TRelations>` when the model has expandable direct, reverse, or edge relations.
|
|
712
|
+
|
|
713
|
+
Returns `Promise<QueryResult<QueryResultItem<TModel, TSelect>>>`:
|
|
651
714
|
|
|
652
715
|
```ts
|
|
653
|
-
type QueryResult = {
|
|
654
|
-
items:
|
|
655
|
-
cursor: string | null; // null when no more pages
|
|
716
|
+
type QueryResult<TItem> = {
|
|
717
|
+
items: TItem[];
|
|
718
|
+
cursor: string | null; // null when no more root pages
|
|
656
719
|
};
|
|
657
720
|
```
|
|
658
721
|
|
|
722
|
+
Each item always includes instance metadata (`space`, `externalId`, `createdTime`, `deletedTime`, `lastUpdatedTime`, `instanceType`) plus the fields you selected. With `{ _all: true }`, scalar view properties are included as well.
|
|
723
|
+
|
|
724
|
+
Example:
|
|
725
|
+
|
|
726
|
+
```ts
|
|
727
|
+
const { items } = await model.query<CogniteAsset>()({
|
|
728
|
+
viewExternalId: "CogniteAsset",
|
|
729
|
+
select: {
|
|
730
|
+
parent: {
|
|
731
|
+
name: true,
|
|
732
|
+
},
|
|
733
|
+
},
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
items[0]?.parent?.name;
|
|
737
|
+
items[0]?.externalId;
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
### Automatic query behavior
|
|
741
|
+
|
|
742
|
+
- **`hasData` filter** — every root query includes a `hasData` constraint for the target view.
|
|
743
|
+
- **Nested relation limits** — expanded relations use an internal page size of `10000` per sub-query.
|
|
744
|
+
- **Dependency pagination** — when a nested sub-query returns `10000` items and a cursor, the client issues follow-up queries (up to 3 rounds) to load additional related data.
|
|
745
|
+
|
|
659
746
|
### Filter operators
|
|
660
747
|
|
|
661
748
|
| Type | Operators |
|
|
@@ -663,7 +750,7 @@ type QueryResult = {
|
|
|
663
750
|
| `string` | `eq`, `in`, `prefix`, `exists` |
|
|
664
751
|
| `number` | `eq`, `in`, `gt`, `gte`, `lt`, `lte`, `exists` |
|
|
665
752
|
| `boolean` | `eq`, `exists` |
|
|
666
|
-
| `Date` | `eq`, `in`, `gt`, `gte`, `lt`, `lte`, `exists` |
|
|
753
|
+
| timestamp / `Date` | `eq`, `in`, `gt`, `gte`, `lt`, `lte`, `exists` — use ISO strings or `Date` values (coerced to ISO) |
|
|
667
754
|
| `NodeId` | `eq`, `in`, `exists` |
|
|
668
755
|
| `T[]` | `containsAny`, `containsAll`, `exists` |
|
|
669
756
|
|
|
@@ -671,10 +758,10 @@ Logical combinators `AND`, `OR`, and `NOT` are supported at any nesting level, i
|
|
|
671
758
|
|
|
672
759
|
### Relation traversal
|
|
673
760
|
|
|
674
|
-
- **Direct relations** — `parent`, `asset`, `unit` (outwards from the current node)
|
|
675
|
-
- **Reverse relations** — declare in `
|
|
676
|
-
- **Edge relations** — declare in `
|
|
677
|
-
- **Depth** — nested
|
|
761
|
+
- **Direct relations** — `parent`, `asset`, `unit` (outwards from the current node). List relations such as `path` return arrays when expanded.
|
|
762
|
+
- **Reverse relations** — declare in `TRelations` (e.g. `children` on `CogniteAsset`)
|
|
763
|
+
- **Edge relations** — declare in `TRelations` (e.g. `images360` on `Cognite3DObject`)
|
|
764
|
+
- **Depth** — nested `select` and `filters` up to 3 levels; dependency pages for large nested result sets are fetched automatically (see above)
|
|
678
765
|
|
|
679
766
|
## Releasing
|
|
680
767
|
|