@cognite/dune 0.1.2 → 0.2.1

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.
Files changed (39) hide show
  1. package/_templates/app/new/config/biome.json.ejs.t +54 -0
  2. package/_templates/app/new/config/components.json.ejs.t +28 -0
  3. package/_templates/app/new/config/tailwind.config.js.ejs.t +15 -0
  4. package/_templates/app/new/{tsconfig.json.ejs.t → config/tsconfig.json.ejs.t} +4 -1
  5. package/_templates/app/new/config/vite.config.ts.ejs.t +27 -0
  6. package/_templates/app/new/cursor/data-modeling.mdc.ejs.t +1996 -0
  7. package/_templates/app/new/cursor/mcp.json.ejs.t +15 -0
  8. package/_templates/app/new/cursor/rules.mdc.ejs.t +12 -0
  9. package/_templates/app/new/root/PRD.md.ejs.t +5 -0
  10. package/_templates/app/new/{package.json.ejs.t → root/package.json.ejs.t} +12 -3
  11. package/_templates/app/new/{App.test.tsx.ejs.t → src/App.test.tsx.ejs.t} +5 -5
  12. package/_templates/app/new/{App.tsx.ejs.t → src/App.tsx.ejs.t} +2 -3
  13. package/_templates/app/new/src/lib/utils.ts.ejs.t +10 -0
  14. package/_templates/app/new/{main.tsx.ejs.t → src/main.tsx.ejs.t} +2 -0
  15. package/_templates/app/new/src/styles.css.ejs.t +25 -0
  16. package/bin/auth/authentication-flow.js +89 -0
  17. package/bin/auth/callback-server.js +181 -0
  18. package/bin/auth/certificate-manager.js +81 -0
  19. package/bin/auth/client-credentials.js +240 -0
  20. package/bin/auth/oauth-client.js +92 -0
  21. package/bin/cli.js +45 -5
  22. package/bin/deploy-command.js +246 -0
  23. package/bin/deploy-interactive-command.js +382 -0
  24. package/bin/utils/crypto.js +35 -0
  25. package/dist/deploy/index.d.ts +7 -0
  26. package/dist/deploy/index.js +43 -1
  27. package/dist/vite/index.js +1 -1
  28. package/package.json +3 -2
  29. package/src/deploy/application-deployer.ts +38 -0
  30. package/src/deploy/deploy.ts +8 -0
  31. package/src/vite/fusion-open-plugin.ts +1 -1
  32. package/_templates/app/new/biome.json.ejs.t +0 -25
  33. package/_templates/app/new/vite.config.ts.ejs.t +0 -15
  34. /package/_templates/app/new/{tsconfig.node.json.ejs.t → config/tsconfig.node.json.ejs.t} +0 -0
  35. /package/_templates/app/new/{vitest.config.ts.ejs.t → config/vitest.config.ts.ejs.t} +0 -0
  36. /package/_templates/app/new/{vitest.setup.ts.ejs.t → config/vitest.setup.ts.ejs.t} +0 -0
  37. /package/_templates/app/new/{app.json.ejs.t → root/app.json.ejs.t} +0 -0
  38. /package/_templates/app/new/{gitignore.ejs.t → root/gitignore.ejs.t} +0 -0
  39. /package/_templates/app/new/{index.html.ejs.t → root/index.html.ejs.t} +0 -0
@@ -0,0 +1,1996 @@
1
+ ---
2
+ to: <%= name %>/.cursor/rules/data-modeling.mdc
3
+ ---
4
+ ---
5
+ alwaysApply: true
6
+ ---
7
+
8
+ # Cognite Data Modeling SDK Guide
9
+
10
+ ## Introduction
11
+
12
+ The Cognite Data Modeling service (DMS) enables you to build, populate, and query flexible data models in Cognite Data Fusion (CDF). This SDK provides JavaScript/TypeScript APIs to work with the core components of data modeling: **Instances** (nodes and edges), **Views**, **Containers**, and **Data Models**. Together, these components allow you to create an industrial knowledge graph that represents your assets, their relationships, and associated data in a structured, scalable way.
13
+
14
+ Data modeling in CDF follows a property graph approach where:
15
+
16
+ - **Nodes** represent entities (like assets, equipment, or documents)
17
+ - **Edges** represent relationships between nodes
18
+ - **Properties** store the actual data values
19
+ - **Views** define the schema and how data is accessed
20
+ - **Containers** handle the physical storage and indexing
21
+ - **Data Models** group views together for specific use cases
22
+
23
+ ## Core Concepts
24
+
25
+ ### Spaces
26
+
27
+ Spaces are logical groupings that help organize and secure data model components. Each container, view, data model, and instance belongs to a specific space. Spaces provide:
28
+
29
+ - **Organization**: Group related data model components together
30
+ - **Access Control**: Manage permissions at the space level
31
+ - **Isolation**: Separate different projects or domains
32
+ - **Namespacing**: Avoid naming conflicts between components
33
+
34
+ CDF provides several system spaces:
35
+
36
+ - `cdf_cdm`: Contains the Cognite core data model
37
+ - `cdf_cdm_units`: Contains unit definitions
38
+ - `cdf_extraction_extensions`: Used by Cognite extractors
39
+
40
+ Reserved space names that cannot be used:
41
+
42
+ - `space`, `cdf`, `dms`, `pg3`, `shared`, `system`, `node`, `edge`
43
+
44
+ ### Property Graph Model
45
+
46
+ CDF uses a property graph where:
47
+
48
+ - **Nodes** are vertices in the graph with properties
49
+ - **Edges** are directed connections between nodes with their own properties
50
+ - **Direct Relations** are properties that reference other nodes (stored on the node itself)
51
+ - **Types** categorize nodes and edges using direct relations
52
+
53
+ ### Schema Components Hierarchy
54
+
55
+ 1. **Containers**: Define physical storage with properties, constraints, and indexes
56
+ 2. **Views**: Provide semantic layers over containers, supporting inheritance and filtering
57
+ 3. **Data Models**: Group related views for specific use cases or applications
58
+
59
+ ## Key Methods & Functions
60
+
61
+ ### Spaces API
62
+
63
+ The Spaces API manages the logical groupings that organize and secure your data model components.
64
+
65
+ #### client.spaces.upsert(params)
66
+
67
+ - **Description**: Creates or updates spaces
68
+ - **Parameters**:
69
+ - `params` (SpaceCreateDefinition[], required): Array of space definitions
70
+ - **Return Type**: Promise<SpaceCollectionResponseV3Response>
71
+ - **Example**:
72
+
73
+ ```javascript
74
+ const spaces = await client.spaces.upsert([
75
+ {
76
+ space: "equipment_data",
77
+ name: "Equipment Data",
78
+ description: "Space for equipment-related data models and instances",
79
+ },
80
+ {
81
+ space: "maintenance_ops",
82
+ name: "Maintenance Operations",
83
+ description: "Space for maintenance workflows and history",
84
+ },
85
+ ]);
86
+
87
+ console.log(`Created ${spaces.items.length} spaces`);
88
+ ```
89
+
90
+ #### client.spaces.list(params?)
91
+
92
+ - **Description**: Lists spaces with optional filtering
93
+ - **Parameters**:
94
+ - `params` (Object, optional): Query parameters
95
+ - `includeGlobal` (boolean): Include global/system spaces
96
+ - `limit` (number): Maximum number of results
97
+ - `cursor` (string): Pagination cursor
98
+ - **Return Type**: CursorAndAsyncIterator<SpaceDefinition>
99
+ - **Example**:
100
+
101
+ ```javascript
102
+ // List user-created spaces
103
+ const userSpaces = await client.spaces
104
+ .list({
105
+ includeGlobal: false,
106
+ limit: 100,
107
+ })
108
+ .autoPagingToArray();
109
+
110
+ console.log("User spaces:");
111
+ userSpaces.forEach((space) => {
112
+ console.log(`- ${space.space}: ${space.name}`);
113
+ });
114
+
115
+ // List all spaces including global ones
116
+ const allSpaces = await client.spaces
117
+ .list({
118
+ includeGlobal: true,
119
+ })
120
+ .autoPagingToArray();
121
+
122
+ console.log(`Total spaces: ${allSpaces.length}`);
123
+ ```
124
+
125
+ #### client.spaces.retrieve(params)
126
+
127
+ - **Description**: Retrieves specific spaces by ID
128
+ - **Parameters**:
129
+ - `params` (string[], required): Array of space IDs
130
+ - **Return Type**: Promise<SpaceCollectionResponseV3Response>
131
+ - **Example**:
132
+
133
+ ```javascript
134
+ const spaces = await client.spaces.retrieve([
135
+ "equipment_data",
136
+ "maintenance_ops",
137
+ "cdf_cdm", // Core data model space
138
+ ]);
139
+
140
+ spaces.items.forEach((space) => {
141
+ console.log(`Space: ${space.space}`);
142
+ console.log(` Name: ${space.name}`);
143
+ console.log(` Description: ${space.description}`);
144
+ console.log(` Is Global: ${space.isGlobal}`);
145
+ console.log(` Created: ${new Date(space.createdTime)}`);
146
+ });
147
+ ```
148
+
149
+ #### client.spaces.delete(params)
150
+
151
+ - **Description**: Deletes spaces (and all contained data)
152
+ - **Parameters**:
153
+ - `params` (string[], required): Array of space IDs to delete
154
+ - **Return Type**: Promise<{ items: string[] }>
155
+ - **Example**:
156
+
157
+ ```javascript
158
+ // WARNING: This deletes the space and ALL its contents
159
+ const result = await client.spaces.delete(["obsolete_space"]);
160
+
161
+ console.log(`Deleted spaces: ${result.items.join(", ")}`);
162
+ ```
163
+
164
+ **Important**: Deleting a space will delete all containers, views, data models, and instances within that space. This operation cannot be undone.
165
+
166
+ ### Instances API
167
+
168
+ The Instances API manages nodes and edges in your property graph.
169
+
170
+ #### client.instances.upsert(params)
171
+
172
+ - **Description**: Creates or updates nodes and edges
173
+ - **Parameters**:
174
+ - `params` (NodeAndEdgeCreateCollection, required): Collection of nodes/edges to upsert
175
+ - **Return Type**: Promise<SlimNodeAndEdgeCollectionResponse>
176
+ - **Example**:
177
+
178
+ ```javascript
179
+ const result = await client.instances.upsert({
180
+ items: [
181
+ {
182
+ instanceType: "node",
183
+ externalId: "pump-001",
184
+ space: "industrial-assets",
185
+ sources: [
186
+ {
187
+ source: {
188
+ externalId: "Equipment",
189
+ space: "cdf_core",
190
+ type: "view",
191
+ version: "v1",
192
+ },
193
+ properties: {
194
+ name: "Water Pump 001",
195
+ description: "Primary cooling system pump",
196
+ manufacturer: "ACME Corp",
197
+ serialNumber: "WP-5000-001",
198
+ },
199
+ },
200
+ ],
201
+ },
202
+ {
203
+ instanceType: "edge",
204
+ externalId: "located-in-001",
205
+ space: "industrial-assets",
206
+ type: { externalId: "locatedIn", space: "relationships" },
207
+ startNode: { externalId: "pump-001", space: "industrial-assets" },
208
+ endNode: { externalId: "facility-001", space: "industrial-assets" },
209
+ sources: [
210
+ {
211
+ source: {
212
+ externalId: "LocationRelation",
213
+ space: "relationships",
214
+ type: "view",
215
+ version: "v1",
216
+ },
217
+ properties: {
218
+ since: "2024-01-15",
219
+ floor: 2,
220
+ room: "2B",
221
+ },
222
+ },
223
+ ],
224
+ },
225
+ ],
226
+ autoCreateDirectRelations: true, // Auto-create missing target nodes
227
+ replace: false, // Merge properties instead of replacing
228
+ });
229
+ ```
230
+
231
+ #### client.instances.list(params)
232
+
233
+ - **Description**: Lists instances with filtering and pagination
234
+ - **Parameters**:
235
+ - `params` (NodeOrEdgeListRequestV3, required): Query parameters
236
+ - **Return Type**: Promise<NodeAndEdgeCollectionResponseWithCursorV3Response>
237
+ - **Example**:
238
+
239
+ ```javascript
240
+ const nodes = await client.instances.list({
241
+ instanceType: "node",
242
+ sources: [
243
+ {
244
+ source: {
245
+ externalId: "Equipment",
246
+ space: "cdf_core",
247
+ type: "view",
248
+ version: "v1",
249
+ },
250
+ },
251
+ ],
252
+ filter: {
253
+ equals: {
254
+ property: ["node", "space"],
255
+ value: "industrial-assets",
256
+ },
257
+ },
258
+ sort: [
259
+ {
260
+ property: ["name"],
261
+ direction: "ascending",
262
+ nullsFirst: false,
263
+ },
264
+ ],
265
+ limit: 100,
266
+ });
267
+
268
+ // Iterate through results
269
+ console.log(`Found ${nodes.items.length} equipment nodes`);
270
+ for (const node of nodes.items) {
271
+ console.log(node.externalId, node.properties);
272
+ }
273
+ ```
274
+
275
+ #### client.instances.retrieve(params)
276
+
277
+ - **Description**: Retrieves specific instances by ID
278
+ - **Parameters**:
279
+ - `params` (ListOfSpaceExternalIdsRequestWithTyping, required): Items to retrieve
280
+ - **Return Type**: Promise<NodeAndEdgeCollectionResponseV3Response>
281
+ - **Example**:
282
+
283
+ ```javascript
284
+ const instances = await client.instances.retrieve({
285
+ sources: [
286
+ {
287
+ source: {
288
+ externalId: "Equipment",
289
+ space: "cdf_core",
290
+ type: "view",
291
+ version: "v1",
292
+ },
293
+ },
294
+ ],
295
+ items: [
296
+ {
297
+ externalId: "pump-001",
298
+ space: "industrial-assets",
299
+ instanceType: "node",
300
+ },
301
+ {
302
+ externalId: "pump-002",
303
+ space: "industrial-assets",
304
+ instanceType: "node",
305
+ },
306
+ ],
307
+ });
308
+ ```
309
+
310
+ #### client.instances.search(params)
311
+
312
+ - **Description**: Searches instances using text queries and filters
313
+ - **Parameters**:
314
+ - `params` (NodeOrEdgeSearchRequest, required): Search parameters
315
+ - **Return Type**: Promise<NodeAndEdgeCollectionResponseV3Response>
316
+ - **Example**:
317
+
318
+ ```javascript
319
+ const searchResults = await client.instances.search({
320
+ view: {
321
+ externalId: "Equipment",
322
+ space: "cdf_core",
323
+ type: "view",
324
+ version: "v1",
325
+ },
326
+ query: "pump ACME", // Text search
327
+ filter: {
328
+ and: [
329
+ {
330
+ equals: {
331
+ property: ["manufacturer"],
332
+ value: "ACME Corp",
333
+ },
334
+ },
335
+ {
336
+ range: {
337
+ property: ["installedDate"],
338
+ gte: "2023-01-01",
339
+ },
340
+ },
341
+ ],
342
+ },
343
+ limit: 50,
344
+ });
345
+ ```
346
+
347
+ #### client.instances.aggregate(params)
348
+
349
+ - **Description**: Aggregates instance data with grouping and calculations
350
+ - **Parameters**:
351
+ - `params` (ViewAggregationRequest, required): Aggregation query
352
+ - **Return Type**: Promise<AggregationResponse>
353
+ - **Example**:
354
+
355
+ ```javascript
356
+ const aggregation = await client.instances.aggregate({
357
+ view: {
358
+ externalId: "Equipment",
359
+ space: "cdf_core",
360
+ type: "view",
361
+ version: "v1",
362
+ },
363
+ groupBy: ["manufacturer", "equipmentType"],
364
+ aggregates: [
365
+ { count: { property: "externalId" } },
366
+ { avg: { property: "maintenanceCost" } },
367
+ { sum: { property: "powerRating" } },
368
+ ],
369
+ filter: {
370
+ prefix: {
371
+ property: ["name"],
372
+ value: "Pump",
373
+ },
374
+ },
375
+ limit: 10,
376
+ });
377
+
378
+ // Process results
379
+ for (const group of aggregation.items) {
380
+ console.log(
381
+ `${group.group[0]} - ${group.group[1]}: ${group.aggregates[0].value} units`
382
+ );
383
+ }
384
+ ```
385
+
386
+ #### client.instances.query(params)
387
+
388
+ - **Description**: Executes complex queries across multiple node/edge types
389
+ - **Parameters**:
390
+ - `params` (QueryRequest, required): Query definition
391
+ - **Return Type**: Promise<QueryResponse>
392
+ - **Example**:
393
+
394
+ ```javascript
395
+ const queryResult = await client.instances.query({
396
+ with: {
397
+ // Define data sources
398
+ pumps: {
399
+ nodes: {
400
+ filter: {
401
+ equals: {
402
+ property: ["node", "type"],
403
+ value: { space: "types", externalId: "Pump" },
404
+ },
405
+ },
406
+ },
407
+ },
408
+ maintenanceEvents: {
409
+ edges: {
410
+ from: "pumps",
411
+ type: { space: "relationships", externalId: "hasMaintenanceEvent" },
412
+ direction: "outwards",
413
+ },
414
+ },
415
+ },
416
+ select: {
417
+ // Define what to return
418
+ pumps: {
419
+ sources: [
420
+ {
421
+ source: {
422
+ externalId: "Equipment",
423
+ space: "cdf_core",
424
+ type: "view",
425
+ version: "v1",
426
+ },
427
+ properties: ["name", "serialNumber", "manufacturer"],
428
+ },
429
+ ],
430
+ },
431
+ maintenanceEvents: {
432
+ sources: [
433
+ {
434
+ source: {
435
+ externalId: "MaintenanceEvent",
436
+ space: "maintenance",
437
+ type: "view",
438
+ version: "v1",
439
+ },
440
+ properties: ["scheduledDate", "description", "status"],
441
+ },
442
+ ],
443
+ },
444
+ },
445
+ parameters: {
446
+ limit: 100,
447
+ },
448
+ });
449
+ ```
450
+
451
+ #### client.instances.sync(params)
452
+
453
+ - **Description**: Synchronizes data with cursor-based pagination for large datasets
454
+ - **Parameters**:
455
+ - `params` (SyncRequest, required): Sync query with cursor support
456
+ - **Return Type**: Promise<QueryResponse>
457
+ - **Example**:
458
+
459
+ ```javascript
460
+ let cursor = null;
461
+ const allData = [];
462
+
463
+ do {
464
+ const syncResult = await client.instances.sync({
465
+ with: {
466
+ equipment: {
467
+ nodes: {
468
+ filter: {
469
+ equals: {
470
+ property: ["node", "space"],
471
+ value: "industrial-assets",
472
+ },
473
+ },
474
+ },
475
+ },
476
+ },
477
+ select: {
478
+ equipment: {},
479
+ },
480
+ cursors: cursor ? { equipment: cursor } : {},
481
+ });
482
+
483
+ allData.push(...syncResult.items.equipment);
484
+ cursor = syncResult.nextCursor?.equipment;
485
+ } while (cursor);
486
+
487
+ console.log(`Synced ${allData.length} equipment nodes`);
488
+ ```
489
+
490
+ #### client.instances.delete(items)
491
+
492
+ - **Description**: Deletes instances by ID
493
+ - **Parameters**:
494
+ - `items` (Array, required): Items to delete
495
+ - **Return Type**: Promise<{}>
496
+ - **Example**:
497
+
498
+ ```javascript
499
+ await client.instances.delete([
500
+ {
501
+ instanceType: "node",
502
+ externalId: "pump-001",
503
+ space: "industrial-assets",
504
+ },
505
+ {
506
+ instanceType: "edge",
507
+ externalId: "located-in-001",
508
+ space: "industrial-assets",
509
+ },
510
+ ]);
511
+ ```
512
+
513
+ ### Views API
514
+
515
+ Views define the semantic schema for your data, supporting inheritance and property mapping.
516
+
517
+ #### client.views.upsert(params)
518
+
519
+ - **Description**: Creates or updates view definitions
520
+ - **Parameters**:
521
+ - `params` (ViewCreateDefinition[], required): Array of view definitions
522
+ - **Return Type**: Promise<ViewCollectionResponse>
523
+ - **Example**:
524
+
525
+ ```javascript
526
+ const views = await client.views.upsert([
527
+ {
528
+ externalId: "Pump",
529
+ space: "equipment-types",
530
+ name: "Pump Equipment",
531
+ description: "View for pump equipment with extended properties",
532
+ version: "v1",
533
+ implements: [
534
+ {
535
+ type: "view",
536
+ space: "cdf_core",
537
+ externalId: "Equipment",
538
+ version: "v1",
539
+ },
540
+ ],
541
+ properties: {
542
+ flowRate: {
543
+ container: {
544
+ type: "container",
545
+ space: "equipment-data",
546
+ externalId: "PumpData",
547
+ },
548
+ containerPropertyIdentifier: "flowRate",
549
+ name: "Flow Rate",
550
+ description: "Maximum flow rate in liters per minute",
551
+ },
552
+ pressure: {
553
+ container: {
554
+ type: "container",
555
+ space: "equipment-data",
556
+ externalId: "PumpData",
557
+ },
558
+ containerPropertyIdentifier: "pressure",
559
+ name: "Operating Pressure",
560
+ description: "Operating pressure in bar",
561
+ },
562
+ manufacturer: {
563
+ container: {
564
+ type: "container",
565
+ space: "equipment-data",
566
+ externalId: "EquipmentCore",
567
+ },
568
+ containerPropertyIdentifier: "manufacturer",
569
+ name: "Manufacturer",
570
+ description: "Equipment manufacturer name",
571
+ },
572
+ },
573
+ filter: {
574
+ equals: {
575
+ property: ["node", "type"],
576
+ value: { space: "types", externalId: "Pump" },
577
+ },
578
+ },
579
+ },
580
+ ]);
581
+ ```
582
+
583
+ #### client.views.list(params)
584
+
585
+ - **Description**: Lists views with optional filtering
586
+ - **Parameters**:
587
+ - `params` (Object, optional): Query parameters
588
+ - **Return Type**: CursorAndAsyncIterator<ViewDefinition>
589
+ - **Example**:
590
+
591
+ ```javascript
592
+ // List all views in a space
593
+ const views = await client.views
594
+ .list({
595
+ space: "equipment-types",
596
+ includeInheritedProperties: true,
597
+ allVersions: false,
598
+ })
599
+ .autoPagingToArray();
600
+
601
+ // List global views
602
+ const globalViews = await client.views
603
+ .list({
604
+ includeGlobal: true,
605
+ limit: 50,
606
+ })
607
+ .autoPagingToArray();
608
+ ```
609
+
610
+ #### client.views.retrieve(params, options?)
611
+
612
+ - **Description**: Retrieves specific views by ID
613
+ - **Parameters**:
614
+ - `params` (Array, required): View references
615
+ - `options` (Object, optional): Additional options
616
+ - **Return Type**: Promise<ViewCollectionResponse>
617
+ - **Example**:
618
+
619
+ ```javascript
620
+ const views = await client.views.retrieve(
621
+ [
622
+ {
623
+ space: "cdf_core",
624
+ externalId: "Equipment",
625
+ version: "v1",
626
+ },
627
+ {
628
+ space: "equipment-types",
629
+ externalId: "Pump",
630
+ // Omit version to get latest
631
+ },
632
+ ],
633
+ {
634
+ includeInheritedProperties: true,
635
+ }
636
+ );
637
+
638
+ // Inspect view properties
639
+ for (const view of views.items) {
640
+ console.log(`View: ${view.externalId}`);
641
+ console.log(`Properties:`, Object.keys(view.properties || {}));
642
+ console.log(`Implements:`, view.implements);
643
+ }
644
+ ```
645
+
646
+ #### client.views.delete(params)
647
+
648
+ - **Description**: Deletes views
649
+ - **Parameters**:
650
+ - `params` (Array, required): View references to delete
651
+ - **Return Type**: Promise<ListOfVersionReferences>
652
+ - **Example**:
653
+
654
+ ```javascript
655
+ await client.views.delete([
656
+ {
657
+ space: "equipment-types",
658
+ externalId: "ObsoletePumpView",
659
+ version: "v1",
660
+ },
661
+ ]);
662
+ ```
663
+
664
+ ### Containers API
665
+
666
+ Containers define the physical storage layer with properties, constraints, and indexes.
667
+
668
+ #### client.containers.upsert(params)
669
+
670
+ - **Description**: Creates or updates container definitions
671
+ - **Parameters**:
672
+ - `params` (ContainerCreateDefinition[], required): Container definitions
673
+ - **Return Type**: Promise<ContainerCollectionResponse>
674
+ - **Example**:
675
+
676
+ ```javascript
677
+ const containers = await client.containers.upsert([
678
+ {
679
+ space: "equipment-data",
680
+ externalId: "PumpData",
681
+ name: "Pump Data Container",
682
+ description: "Stores pump-specific properties",
683
+ usedFor: "node", // Can be 'node', 'edge', or 'all'
684
+ properties: {
685
+ flowRate: {
686
+ type: {
687
+ type: "float64",
688
+ },
689
+ nullable: true,
690
+ description: "Flow rate in liters per minute",
691
+ },
692
+ pressure: {
693
+ type: {
694
+ type: "float64",
695
+ },
696
+ nullable: false,
697
+ defaultValue: 1.0,
698
+ description: "Operating pressure in bar",
699
+ },
700
+ manufacturer: {
701
+ type: {
702
+ type: "text",
703
+ list: false,
704
+ },
705
+ nullable: true,
706
+ description: "Manufacturer name",
707
+ },
708
+ installedDate: {
709
+ type: {
710
+ type: "timestamp",
711
+ },
712
+ nullable: true,
713
+ description: "Installation date",
714
+ },
715
+ maintenanceSchedule: {
716
+ type: {
717
+ type: "json",
718
+ },
719
+ nullable: true,
720
+ description: "Maintenance schedule configuration",
721
+ },
722
+ relatedAssets: {
723
+ type: {
724
+ type: "direct",
725
+ container: {
726
+ type: "container",
727
+ space: "cdf_core",
728
+ externalId: "Asset",
729
+ },
730
+ },
731
+ list: true,
732
+ description: "Related asset references",
733
+ },
734
+ },
735
+ constraints: {
736
+ uniqueSerialNumber: {
737
+ constraintType: "unique",
738
+ properties: ["serialNumber"],
739
+ },
740
+ },
741
+ indexes: {
742
+ byManufacturer: {
743
+ properties: ["manufacturer"],
744
+ },
745
+ byInstallDate: {
746
+ properties: ["installedDate"],
747
+ },
748
+ },
749
+ },
750
+ ]);
751
+ ```
752
+
753
+ #### client.containers.list(params)
754
+
755
+ - **Description**: Lists containers
756
+ - **Parameters**:
757
+ - `params` (Object, optional): Query parameters
758
+ - **Return Type**: CursorAndAsyncIterator<ContainerDefinition>
759
+ - **Example**:
760
+
761
+ ```javascript
762
+ // List containers in a specific space
763
+ const containers = await client.containers
764
+ .list({
765
+ space: "equipment-data",
766
+ includeGlobal: false,
767
+ })
768
+ .autoPagingToArray();
769
+
770
+ // List all accessible containers including global ones
771
+ const allContainers = await client.containers
772
+ .list({
773
+ includeGlobal: true,
774
+ limit: 100,
775
+ })
776
+ .autoPagingToArray();
777
+ ```
778
+
779
+ #### client.containers.retrieve(params)
780
+
781
+ - **Description**: Retrieves specific containers
782
+ - **Parameters**:
783
+ - `params` (Array, required): Container identifiers
784
+ - **Return Type**: Promise<ContainerCollectionResponse>
785
+ - **Example**:
786
+
787
+ ```javascript
788
+ const containers = await client.containers.retrieve([
789
+ {
790
+ space: "equipment-data",
791
+ externalId: "PumpData",
792
+ },
793
+ {
794
+ space: "cdf_core",
795
+ externalId: "Asset",
796
+ },
797
+ ]);
798
+ ```
799
+
800
+ #### client.containers.delete(params)
801
+
802
+ - **Description**: Deletes containers
803
+ - **Parameters**:
804
+ - `params` (Array, required): Container identifiers
805
+ - **Return Type**: Promise<ListOfSpaceExternalIdsResponse>
806
+ - **Example**:
807
+
808
+ ```javascript
809
+ await client.containers.delete([
810
+ {
811
+ space: "equipment-data",
812
+ externalId: "ObsoleteContainer",
813
+ },
814
+ ]);
815
+ ```
816
+
817
+ ### Data Models API
818
+
819
+ Data models group related views together for specific use cases or applications.
820
+
821
+ #### client.dataModels.upsert(params)
822
+
823
+ - **Description**: Creates or updates data models
824
+ - **Parameters**:
825
+ - `params` (DataModelCreate[], required): Data model definitions
826
+ - **Return Type**: Promise<DataModelCollectionResponse>
827
+ - **Example**:
828
+
829
+ ```javascript
830
+ const dataModels = await client.dataModels.upsert([
831
+ {
832
+ space: "industrial-models",
833
+ externalId: "MaintenanceModel",
834
+ name: "Maintenance Management Model",
835
+ description: "Data model for equipment maintenance workflows",
836
+ version: "v1",
837
+ views: [
838
+ // Reference existing views
839
+ {
840
+ type: "view",
841
+ space: "cdf_core",
842
+ externalId: "Asset",
843
+ version: "v1",
844
+ },
845
+ {
846
+ type: "view",
847
+ space: "equipment-types",
848
+ externalId: "Pump",
849
+ version: "v1",
850
+ },
851
+ // Create new view inline
852
+ {
853
+ externalId: "MaintenanceEvent",
854
+ space: "maintenance",
855
+ version: "v1",
856
+ name: "Maintenance Event",
857
+ description: "Maintenance activities on equipment",
858
+ properties: {
859
+ scheduledDate: {
860
+ container: {
861
+ type: "container",
862
+ space: "maintenance",
863
+ externalId: "MaintenanceData",
864
+ },
865
+ containerPropertyIdentifier: "scheduledDate",
866
+ name: "Scheduled Date",
867
+ },
868
+ completedDate: {
869
+ container: {
870
+ type: "container",
871
+ space: "maintenance",
872
+ externalId: "MaintenanceData",
873
+ },
874
+ containerPropertyIdentifier: "completedDate",
875
+ name: "Completed Date",
876
+ },
877
+ description: {
878
+ container: {
879
+ type: "container",
880
+ space: "maintenance",
881
+ externalId: "MaintenanceData",
882
+ },
883
+ containerPropertyIdentifier: "description",
884
+ name: "Description",
885
+ },
886
+ status: {
887
+ container: {
888
+ type: "container",
889
+ space: "maintenance",
890
+ externalId: "MaintenanceData",
891
+ },
892
+ containerPropertyIdentifier: "status",
893
+ name: "Status",
894
+ },
895
+ },
896
+ },
897
+ ],
898
+ },
899
+ ]);
900
+ ```
901
+
902
+ #### client.dataModels.list(params)
903
+
904
+ - **Description**: Lists data models
905
+ - **Parameters**:
906
+ - `params` (Object, optional): Query parameters
907
+ - **Return Type**: DataModelCollectionResponseWithCursorResponse
908
+ - **Example**:
909
+
910
+ ```javascript
911
+ // List all data models
912
+ const models = await client.dataModels.list();
913
+
914
+ // List with inline views expanded
915
+ const modelsWithViews = await client.dataModels.list({
916
+ inlineViews: true,
917
+ includeGlobal: true,
918
+ allVersions: false,
919
+ });
920
+
921
+ // Iterate through models
922
+ await modelsWithViews.autoPagingEach((model) => {
923
+ console.log(`Model: ${model.externalId} v${model.version}`);
924
+ console.log(`Views: ${model.views?.length || 0}`);
925
+ });
926
+ ```
927
+
928
+ #### client.dataModels.retrieve(params, options?)
929
+
930
+ - **Description**: Retrieves specific data models
931
+ - **Parameters**:
932
+ - `params` (Array, required): Model references
933
+ - `options` (Object, optional): Additional options
934
+ - **Return Type**: Promise<DataModelCollectionResponse>
935
+ - **Example**:
936
+
937
+ ```javascript
938
+ const models = await client.dataModels.retrieve(
939
+ [
940
+ {
941
+ space: "industrial-models",
942
+ externalId: "MaintenanceModel",
943
+ version: "v1",
944
+ },
945
+ ],
946
+ {
947
+ inlineViews: true, // Include full view definitions
948
+ }
949
+ );
950
+ ```
951
+
952
+ #### client.dataModels.delete(params)
953
+
954
+ - **Description**: Deletes data models
955
+ - **Parameters**:
956
+ - `params` (Array, required): Model references
957
+ - **Return Type**: Promise<ListOfVersionReferences>
958
+ - **Example**:
959
+
960
+ ```javascript
961
+ await client.dataModels.delete([
962
+ {
963
+ space: "industrial-models",
964
+ externalId: "DeprecatedModel",
965
+ version: "v1",
966
+ },
967
+ ]);
968
+ ```
969
+
970
+ ## Data Models
971
+
972
+ ### Space Structure
973
+
974
+ ```typescript
975
+ interface SpaceDefinition {
976
+ space: string; // Space ID (3-43 chars, alphanumeric with _ and -)
977
+ name?: string; // Human-readable name
978
+ description?: string; // Space description
979
+ createdTime: number; // Creation timestamp (epoch milliseconds)
980
+ lastUpdatedTime: number; // Last update timestamp
981
+ isGlobal: boolean; // Whether this is a system/global space
982
+ }
983
+ ```
984
+
985
+ Space IDs must:
986
+
987
+ - Start with a letter
988
+ - Be 3-43 characters long
989
+ - Contain only letters, numbers, underscores, and hyphens
990
+ - Not use reserved names: `space`, `cdf`, `dms`, `pg3`, `shared`, `system`, `node`, `edge`
991
+
992
+ ### Core Property Types
993
+
994
+ Properties in containers can have the following types:
995
+
996
+ ```typescript
997
+ // Text property
998
+ {
999
+ type: "text",
1000
+ list?: boolean, // Array of strings
1001
+ collation?: string, // Collation for sorting
1002
+ }
1003
+
1004
+ // Primitive properties
1005
+ {
1006
+ type: "int32" | "int64" | "float32" | "float64" | "boolean",
1007
+ list?: boolean,
1008
+ }
1009
+
1010
+ // Timestamp property
1011
+ {
1012
+ type: "timestamp",
1013
+ list?: boolean,
1014
+ }
1015
+
1016
+ // JSON property
1017
+ {
1018
+ type: "json",
1019
+ list?: boolean,
1020
+ }
1021
+
1022
+ // Direct relation (reference to another node)
1023
+ {
1024
+ type: "direct",
1025
+ container?: { // Optional: enforce target node type
1026
+ type: "container",
1027
+ space: string,
1028
+ externalId: string,
1029
+ },
1030
+ list?: boolean,
1031
+ }
1032
+
1033
+ // CDF resource reference
1034
+ {
1035
+ type: "timeseries" | "file" | "sequence",
1036
+ list?: boolean,
1037
+ }
1038
+ ```
1039
+
1040
+ ### Node Structure
1041
+
1042
+ ```typescript
1043
+ interface NodeDefinition {
1044
+ instanceType: "node";
1045
+ space: string;
1046
+ externalId: string;
1047
+ version: number;
1048
+ createdTime: number;
1049
+ lastUpdatedTime: number;
1050
+ deletedTime?: number;
1051
+
1052
+ // Optional type categorization
1053
+ type?: {
1054
+ space: string;
1055
+ externalId: string;
1056
+ };
1057
+
1058
+ // Properties grouped by view/container
1059
+ properties?: {
1060
+ [viewOrContainerKey: string]: {
1061
+ [propertyName: string]: any;
1062
+ };
1063
+ };
1064
+ }
1065
+ ```
1066
+
1067
+ ### Edge Structure
1068
+
1069
+ ```typescript
1070
+ interface EdgeDefinition {
1071
+ instanceType: "edge";
1072
+ space: string;
1073
+ externalId: string;
1074
+ version: number;
1075
+ createdTime: number;
1076
+ lastUpdatedTime: number;
1077
+ deletedTime?: number;
1078
+
1079
+ // Required edge type
1080
+ type: {
1081
+ space: string;
1082
+ externalId: string;
1083
+ };
1084
+
1085
+ // Required start and end nodes
1086
+ startNode: {
1087
+ space: string;
1088
+ externalId: string;
1089
+ };
1090
+ endNode: {
1091
+ space: string;
1092
+ externalId: string;
1093
+ };
1094
+
1095
+ // Properties grouped by view/container
1096
+ properties?: {
1097
+ [viewOrContainerKey: string]: {
1098
+ [propertyName: string]: any;
1099
+ };
1100
+ };
1101
+ }
1102
+ ```
1103
+
1104
+ ### View Structure
1105
+
1106
+ ```typescript
1107
+ interface ViewDefinition {
1108
+ space: string;
1109
+ externalId: string;
1110
+ version: string;
1111
+ name?: string;
1112
+ description?: string;
1113
+ createdTime: number;
1114
+ lastUpdatedTime: number;
1115
+ writable: boolean;
1116
+ usedFor: "node" | "edge" | "all";
1117
+
1118
+ // Views this view inherits from
1119
+ implements?: Array<{
1120
+ type: "view";
1121
+ space: string;
1122
+ externalId: string;
1123
+ version: string;
1124
+ }>;
1125
+
1126
+ // Filter to apply to instances
1127
+ filter?: FilterDefinition;
1128
+
1129
+ // Property mappings
1130
+ properties?: {
1131
+ [propertyName: string]: {
1132
+ container: {
1133
+ type: "container";
1134
+ space: string;
1135
+ externalId: string;
1136
+ };
1137
+ containerPropertyIdentifier: string;
1138
+ name?: string;
1139
+ description?: string;
1140
+ // For direct relations
1141
+ source?: ViewReference;
1142
+ };
1143
+ };
1144
+ }
1145
+ ```
1146
+
1147
+ ### Container Structure
1148
+
1149
+ ```typescript
1150
+ interface ContainerDefinition {
1151
+ space: string;
1152
+ externalId: string;
1153
+ name?: string;
1154
+ description?: string;
1155
+ createdTime?: number;
1156
+ lastUpdatedTime?: number;
1157
+ usedFor?: "node" | "edge" | "all";
1158
+
1159
+ // Property definitions
1160
+ properties: {
1161
+ [propertyName: string]: {
1162
+ type: PropertyType;
1163
+ nullable?: boolean;
1164
+ autoIncrement?: boolean;
1165
+ defaultValue?: any;
1166
+ description?: string;
1167
+ name?: string;
1168
+ };
1169
+ };
1170
+
1171
+ // Constraints
1172
+ constraints?: {
1173
+ [constraintName: string]: {
1174
+ constraintType: "unique" | "required";
1175
+ properties: string[];
1176
+ };
1177
+ };
1178
+
1179
+ // Indexes for performance
1180
+ indexes?: {
1181
+ [indexName: string]: {
1182
+ properties: string[];
1183
+ };
1184
+ };
1185
+ }
1186
+ ```
1187
+
1188
+ ### Filter Definitions
1189
+
1190
+ Filters support complex queries using boolean operators and various conditions:
1191
+
1192
+ ```typescript
1193
+ // Boolean filters
1194
+ {
1195
+ and: FilterDefinition[];
1196
+ }
1197
+ {
1198
+ or: FilterDefinition[];
1199
+ }
1200
+ {
1201
+ not: FilterDefinition;
1202
+ }
1203
+
1204
+ // Comparison filters
1205
+ {
1206
+ equals: {
1207
+ property: string[];
1208
+ value: any;
1209
+ };
1210
+ }
1211
+ {
1212
+ in: {
1213
+ property: string[];
1214
+ values: any[];
1215
+ };
1216
+ }
1217
+ {
1218
+ range: {
1219
+ property: string[];
1220
+ gt?: any;
1221
+ gte?: any;
1222
+ lt?: any;
1223
+ lte?: any;
1224
+ };
1225
+ }
1226
+ {
1227
+ prefix: {
1228
+ property: string[];
1229
+ value: string;
1230
+ };
1231
+ }
1232
+ {
1233
+ exists: {
1234
+ property: string[];
1235
+ };
1236
+ }
1237
+ {
1238
+ containsAny: {
1239
+ property: string[];
1240
+ values: any[];
1241
+ };
1242
+ }
1243
+ {
1244
+ containsAll: {
1245
+ property: string[];
1246
+ values: any[];
1247
+ };
1248
+ }
1249
+
1250
+ // Nested filter for direct relations
1251
+ {
1252
+ nested: {
1253
+ scope: string[];
1254
+ filter: FilterDefinition;
1255
+ };
1256
+ }
1257
+
1258
+ // Special filters
1259
+ {
1260
+ hasData: {
1261
+ sources: Array<{
1262
+ type: "view" | "container";
1263
+ space: string;
1264
+ externalId: string;
1265
+ version?: string;
1266
+ }>;
1267
+ };
1268
+ }
1269
+ {
1270
+ matchAll: {};
1271
+ }
1272
+ ```
1273
+
1274
+ ## Core Data Model
1275
+
1276
+ CDF provides the Cognite Core Data Model (`cdf_cdm`) as a foundation for industrial data. Key concepts include:
1277
+
1278
+ ### Core Features (Reusable Property Sets)
1279
+
1280
+ - **CogniteDescribable**: Provides `name`, `description`, `tags`, and `aliases`
1281
+ - **CogniteSourceable**: Tracks data origin with `sourceId`, `sourceContext`, `source`
1282
+ - **CogniteSchedulable**: Manages time windows with `startTime`, `endTime`, `scheduledStartTime`, `scheduledEndTime`
1283
+ - **CogniteVisualizable**: Links to 3D representations via `object3D`
1284
+
1285
+ ### Core Concepts
1286
+
1287
+ - **CogniteAsset**: Represents physical or logical assets in your industrial facility
1288
+ - **CogniteEquipment**: Specialized assets representing industrial equipment
1289
+ - **CogniteTimeSeries**: References to time series data
1290
+ - **CogniteFile**: References to files stored in CDF
1291
+ - **CogniteActivity**: Represents activities or events with time boundaries
1292
+ - **CogniteAnnotation**: Comments or observations on other objects
1293
+
1294
+ ### 3D Concepts
1295
+
1296
+ - **Cognite3DModel**: 3D models (CAD, point cloud, 360 images)
1297
+ - **CogniteCADNode**: Individual nodes within CAD models
1298
+ - **CognitePointCloudVolume**: Volumes within point cloud data
1299
+ - **Cognite360Image**: 360-degree photospheres
1300
+
1301
+ ## Access Control
1302
+
1303
+ Data modeling uses capability-based access control:
1304
+
1305
+ ### Required Capabilities
1306
+
1307
+ ```javascript
1308
+ // Basic data model access
1309
+ {
1310
+ dataModelsAcl: ["READ", "WRITE"],
1311
+ dataModelInstancesAcl: ["READ", "WRITE"],
1312
+ }
1313
+
1314
+ // For using core data model
1315
+ {
1316
+ dataModelsAcl: {
1317
+ actions: ["READ"],
1318
+ scope: { spaceIdScope: { spaceIds: ["cdf_cdm"] } }
1319
+ },
1320
+ dataModelInstancesAcl: {
1321
+ actions: ["READ"],
1322
+ scope: { spaceIdScope: { spaceIds: ["cdf_cdm_units"] } }
1323
+ },
1324
+ }
1325
+
1326
+ // For specific spaces
1327
+ {
1328
+ dataModelInstancesAcl: {
1329
+ actions: ["READ", "WRITE"],
1330
+ scope: { spaceIdScope: { spaceIds: ["your-space"] } }
1331
+ },
1332
+ }
1333
+ ```
1334
+
1335
+ ## Error Handling
1336
+
1337
+ The Data Modeling APIs return specific error types:
1338
+
1339
+ ### Common Error Scenarios
1340
+
1341
+ ```javascript
1342
+ try {
1343
+ await client.instances.upsert({ items: [...] });
1344
+ } catch (error) {
1345
+ if (error instanceof CogniteError) {
1346
+ switch (error.status) {
1347
+ case 400:
1348
+ // Validation errors
1349
+ console.error("Validation failed:", error.errorMessage);
1350
+ if (error.extra?.violations) {
1351
+ // Schema violations
1352
+ console.error("Violations:", error.extra.violations);
1353
+ }
1354
+ break;
1355
+
1356
+ case 409:
1357
+ // Conflict errors (e.g., version mismatch)
1358
+ console.error("Version conflict:", error.errorMessage);
1359
+ break;
1360
+
1361
+ case 422:
1362
+ // Business logic errors
1363
+ console.error("Business rule violation:", error.errorMessage);
1364
+ break;
1365
+
1366
+ default:
1367
+ console.error(`API Error ${error.status}:`, error.errorMessage);
1368
+ }
1369
+ }
1370
+ }
1371
+ ```
1372
+
1373
+ ### Handling Large Result Sets
1374
+
1375
+ ```javascript
1376
+ // Use cursor pagination for large datasets
1377
+ async function getAllEquipment() {
1378
+ const allItems = [];
1379
+ let cursor = null;
1380
+
1381
+ do {
1382
+ try {
1383
+ const response = await client.instances.list({
1384
+ instanceType: "node",
1385
+ sources: [
1386
+ {
1387
+ source: {
1388
+ type: "view",
1389
+ space: "cdf_core",
1390
+ externalId: "Equipment",
1391
+ version: "v1",
1392
+ },
1393
+ },
1394
+ ],
1395
+ cursor: cursor,
1396
+ limit: 1000,
1397
+ });
1398
+
1399
+ allItems.push(...response.items);
1400
+ cursor = response.nextCursor;
1401
+ } catch (error) {
1402
+ console.error("Failed to fetch page:", error);
1403
+ break;
1404
+ }
1405
+ } while (cursor);
1406
+
1407
+ return allItems;
1408
+ }
1409
+ ```
1410
+
1411
+ ## Code Example
1412
+
1413
+ Here's a complete example building an industrial data model:
1414
+
1415
+ ```javascript
1416
+ import { CogniteClient } from "@cognite/sdk";
1417
+
1418
+ async function buildIndustrialDataModel() {
1419
+ // 1. Initialize client
1420
+ const client = new CogniteClient({
1421
+ appId: "IndustrialDataModeling",
1422
+ project: "my-project",
1423
+ oidcTokenProvider: async () => process.env.CDF_ACCESS_TOKEN,
1424
+ });
1425
+
1426
+ try {
1427
+ // 2. Create spaces for organization
1428
+ console.log("Creating spaces...");
1429
+ await client.spaces.upsert([
1430
+ {
1431
+ space: "equipment",
1432
+ name: "Equipment Management",
1433
+ description: "Space for equipment data models and instances",
1434
+ },
1435
+ {
1436
+ space: "maintenance",
1437
+ name: "Maintenance Operations",
1438
+ description: "Space for maintenance workflows and events",
1439
+ },
1440
+ {
1441
+ space: "types",
1442
+ name: "Type Definitions",
1443
+ description: "Space for type categorization nodes",
1444
+ },
1445
+ {
1446
+ space: "assets",
1447
+ name: "Asset Instances",
1448
+ description: "Space for actual asset instances",
1449
+ },
1450
+ {
1451
+ space: "industrial",
1452
+ name: "Industrial Models",
1453
+ description: "Space for industrial data models",
1454
+ },
1455
+ {
1456
+ space: "relationships",
1457
+ name: "Relationship Types",
1458
+ description: "Space for edge type definitions",
1459
+ },
1460
+ ]);
1461
+
1462
+ // 3. Create containers for physical storage
1463
+ console.log("Creating containers...");
1464
+ await client.containers.upsert([
1465
+ {
1466
+ space: "equipment",
1467
+ externalId: "EquipmentData",
1468
+ name: "Equipment Data",
1469
+ description: "Core equipment properties",
1470
+ usedFor: "node",
1471
+ properties: {
1472
+ serialNumber: {
1473
+ type: { type: "text" },
1474
+ nullable: false,
1475
+ description: "Unique serial number",
1476
+ },
1477
+ manufacturer: {
1478
+ type: { type: "text" },
1479
+ nullable: true,
1480
+ },
1481
+ model: {
1482
+ type: { type: "text" },
1483
+ nullable: true,
1484
+ },
1485
+ installationDate: {
1486
+ type: { type: "timestamp" },
1487
+ nullable: true,
1488
+ },
1489
+ specifications: {
1490
+ type: { type: "json" },
1491
+ nullable: true,
1492
+ description: "Technical specifications",
1493
+ },
1494
+ },
1495
+ constraints: {
1496
+ uniqueSerial: {
1497
+ constraintType: "unique",
1498
+ properties: ["serialNumber"],
1499
+ },
1500
+ },
1501
+ },
1502
+ {
1503
+ space: "equipment",
1504
+ externalId: "PumpSpecific",
1505
+ name: "Pump Specific Data",
1506
+ usedFor: "node",
1507
+ properties: {
1508
+ flowRate: {
1509
+ type: { type: "float64" },
1510
+ nullable: true,
1511
+ description: "Flow rate in L/min",
1512
+ },
1513
+ headPressure: {
1514
+ type: { type: "float64" },
1515
+ nullable: true,
1516
+ description: "Head pressure in bar",
1517
+ },
1518
+ efficiency: {
1519
+ type: { type: "float64" },
1520
+ nullable: true,
1521
+ description: "Pump efficiency percentage",
1522
+ },
1523
+ },
1524
+ },
1525
+ {
1526
+ space: "maintenance",
1527
+ externalId: "MaintenanceData",
1528
+ name: "Maintenance Data",
1529
+ usedFor: "edge",
1530
+ properties: {
1531
+ scheduledDate: {
1532
+ type: { type: "timestamp" },
1533
+ nullable: false,
1534
+ },
1535
+ completedDate: {
1536
+ type: { type: "timestamp" },
1537
+ nullable: true,
1538
+ },
1539
+ cost: {
1540
+ type: { type: "float64" },
1541
+ nullable: true,
1542
+ },
1543
+ notes: {
1544
+ type: { type: "text" },
1545
+ nullable: true,
1546
+ },
1547
+ },
1548
+ },
1549
+ ]);
1550
+
1551
+ // 4. Create views for semantic access
1552
+ console.log("Creating views...");
1553
+ await client.views.upsert([
1554
+ {
1555
+ space: "equipment",
1556
+ externalId: "BaseEquipment",
1557
+ version: "v1",
1558
+ name: "Base Equipment",
1559
+ description: "Common equipment properties",
1560
+ properties: {
1561
+ serialNumber: {
1562
+ container: {
1563
+ type: "container",
1564
+ space: "equipment",
1565
+ externalId: "EquipmentData",
1566
+ },
1567
+ containerPropertyIdentifier: "serialNumber",
1568
+ },
1569
+ manufacturer: {
1570
+ container: {
1571
+ type: "container",
1572
+ space: "equipment",
1573
+ externalId: "EquipmentData",
1574
+ },
1575
+ containerPropertyIdentifier: "manufacturer",
1576
+ },
1577
+ model: {
1578
+ container: {
1579
+ type: "container",
1580
+ space: "equipment",
1581
+ externalId: "EquipmentData",
1582
+ },
1583
+ containerPropertyIdentifier: "model",
1584
+ },
1585
+ installationDate: {
1586
+ container: {
1587
+ type: "container",
1588
+ space: "equipment",
1589
+ externalId: "EquipmentData",
1590
+ },
1591
+ containerPropertyIdentifier: "installationDate",
1592
+ },
1593
+ },
1594
+ },
1595
+ {
1596
+ space: "equipment",
1597
+ externalId: "Pump",
1598
+ version: "v1",
1599
+ name: "Pump",
1600
+ description: "Industrial pump with extended properties",
1601
+ implements: [
1602
+ {
1603
+ type: "view",
1604
+ space: "equipment",
1605
+ externalId: "BaseEquipment",
1606
+ version: "v1",
1607
+ },
1608
+ ],
1609
+ properties: {
1610
+ flowRate: {
1611
+ container: {
1612
+ type: "container",
1613
+ space: "equipment",
1614
+ externalId: "PumpSpecific",
1615
+ },
1616
+ containerPropertyIdentifier: "flowRate",
1617
+ name: "Flow Rate (L/min)",
1618
+ },
1619
+ headPressure: {
1620
+ container: {
1621
+ type: "container",
1622
+ space: "equipment",
1623
+ externalId: "PumpSpecific",
1624
+ },
1625
+ containerPropertyIdentifier: "headPressure",
1626
+ name: "Head Pressure (bar)",
1627
+ },
1628
+ efficiency: {
1629
+ container: {
1630
+ type: "container",
1631
+ space: "equipment",
1632
+ externalId: "PumpSpecific",
1633
+ },
1634
+ containerPropertyIdentifier: "efficiency",
1635
+ name: "Efficiency (%)",
1636
+ },
1637
+ },
1638
+ filter: {
1639
+ equals: {
1640
+ property: ["node", "type"],
1641
+ value: { space: "types", externalId: "Pump" },
1642
+ },
1643
+ },
1644
+ },
1645
+ {
1646
+ space: "maintenance",
1647
+ externalId: "MaintenanceEvent",
1648
+ version: "v1",
1649
+ name: "Maintenance Event",
1650
+ description: "Maintenance performed on equipment",
1651
+ properties: {
1652
+ scheduledDate: {
1653
+ container: {
1654
+ type: "container",
1655
+ space: "maintenance",
1656
+ externalId: "MaintenanceData",
1657
+ },
1658
+ containerPropertyIdentifier: "scheduledDate",
1659
+ },
1660
+ completedDate: {
1661
+ container: {
1662
+ type: "container",
1663
+ space: "maintenance",
1664
+ externalId: "MaintenanceData",
1665
+ },
1666
+ containerPropertyIdentifier: "completedDate",
1667
+ },
1668
+ cost: {
1669
+ container: {
1670
+ type: "container",
1671
+ space: "maintenance",
1672
+ externalId: "MaintenanceData",
1673
+ },
1674
+ containerPropertyIdentifier: "cost",
1675
+ name: "Cost (USD)",
1676
+ },
1677
+ notes: {
1678
+ container: {
1679
+ type: "container",
1680
+ space: "maintenance",
1681
+ externalId: "MaintenanceData",
1682
+ },
1683
+ containerPropertyIdentifier: "notes",
1684
+ },
1685
+ },
1686
+ },
1687
+ ]);
1688
+
1689
+ // 5. Create data model
1690
+ console.log("Creating data model...");
1691
+ await client.dataModels.upsert([
1692
+ {
1693
+ space: "industrial",
1694
+ externalId: "EquipmentMaintenance",
1695
+ name: "Equipment Maintenance Model",
1696
+ description: "Model for equipment and maintenance management",
1697
+ version: "v1",
1698
+ views: [
1699
+ {
1700
+ type: "view",
1701
+ space: "equipment",
1702
+ externalId: "Pump",
1703
+ version: "v1",
1704
+ },
1705
+ {
1706
+ type: "view",
1707
+ space: "maintenance",
1708
+ externalId: "MaintenanceEvent",
1709
+ version: "v1",
1710
+ },
1711
+ ],
1712
+ },
1713
+ ]);
1714
+
1715
+ // 6. Create type nodes
1716
+ console.log("Creating type nodes...");
1717
+ await client.instances.upsert({
1718
+ items: [
1719
+ {
1720
+ instanceType: "node",
1721
+ space: "types",
1722
+ externalId: "Pump",
1723
+ },
1724
+ ],
1725
+ });
1726
+
1727
+ // 7. Create pump instances
1728
+ console.log("Creating pump instances...");
1729
+ const pumps = await client.instances.upsert({
1730
+ items: [
1731
+ {
1732
+ instanceType: "node",
1733
+ space: "assets",
1734
+ externalId: "pump-001",
1735
+ type: { space: "types", externalId: "Pump" },
1736
+ sources: [
1737
+ {
1738
+ source: {
1739
+ type: "view",
1740
+ space: "equipment",
1741
+ externalId: "Pump",
1742
+ version: "v1",
1743
+ },
1744
+ properties: {
1745
+ serialNumber: "P2024-001",
1746
+ manufacturer: "FlowTech Industries",
1747
+ model: "FT-5000",
1748
+ installationDate: "2024-01-15T10:00:00Z",
1749
+ flowRate: 500.0,
1750
+ headPressure: 10.5,
1751
+ efficiency: 85.0,
1752
+ },
1753
+ },
1754
+ ],
1755
+ },
1756
+ {
1757
+ instanceType: "node",
1758
+ space: "assets",
1759
+ externalId: "pump-002",
1760
+ type: { space: "types", externalId: "Pump" },
1761
+ sources: [
1762
+ {
1763
+ source: {
1764
+ type: "view",
1765
+ space: "equipment",
1766
+ externalId: "Pump",
1767
+ version: "v1",
1768
+ },
1769
+ properties: {
1770
+ serialNumber: "P2024-002",
1771
+ manufacturer: "FlowTech Industries",
1772
+ model: "FT-3000",
1773
+ installationDate: "2024-02-01T14:30:00Z",
1774
+ flowRate: 300.0,
1775
+ headPressure: 8.0,
1776
+ efficiency: 82.0,
1777
+ },
1778
+ },
1779
+ ],
1780
+ },
1781
+ ],
1782
+ });
1783
+
1784
+ // 8. Create maintenance events as edges
1785
+ console.log("Creating maintenance events...");
1786
+ await client.instances.upsert({
1787
+ items: [
1788
+ {
1789
+ instanceType: "edge",
1790
+ space: "maintenance",
1791
+ externalId: "maint-001",
1792
+ type: { space: "relationships", externalId: "hasMaintenanceEvent" },
1793
+ startNode: { space: "assets", externalId: "pump-001" },
1794
+ endNode: { space: "maintenance", externalId: "event-001" },
1795
+ sources: [
1796
+ {
1797
+ source: {
1798
+ type: "view",
1799
+ space: "maintenance",
1800
+ externalId: "MaintenanceEvent",
1801
+ version: "v1",
1802
+ },
1803
+ properties: {
1804
+ scheduledDate: "2024-03-01T08:00:00Z",
1805
+ completedDate: "2024-03-01T12:00:00Z",
1806
+ cost: 1250.0,
1807
+ notes: "Routine maintenance and seal replacement",
1808
+ },
1809
+ },
1810
+ ],
1811
+ },
1812
+ ],
1813
+ });
1814
+
1815
+ // 9. Query data using the model
1816
+ console.log("Querying pump data with maintenance history...");
1817
+ const queryResult = await client.instances.query({
1818
+ with: {
1819
+ pumps: {
1820
+ nodes: {
1821
+ filter: {
1822
+ and: [
1823
+ {
1824
+ equals: {
1825
+ property: ["node", "type"],
1826
+ value: { space: "types", externalId: "Pump" },
1827
+ },
1828
+ },
1829
+ {
1830
+ range: {
1831
+ property: ["pump", "efficiency"],
1832
+ gte: 80.0,
1833
+ },
1834
+ },
1835
+ ],
1836
+ },
1837
+ },
1838
+ },
1839
+ maintenance: {
1840
+ edges: {
1841
+ from: "pumps",
1842
+ type: { space: "relationships", externalId: "hasMaintenanceEvent" },
1843
+ direction: "outwards",
1844
+ },
1845
+ },
1846
+ },
1847
+ select: {
1848
+ pumps: {
1849
+ sources: [
1850
+ {
1851
+ source: {
1852
+ type: "view",
1853
+ space: "equipment",
1854
+ externalId: "Pump",
1855
+ version: "v1",
1856
+ },
1857
+ properties: [
1858
+ "serialNumber",
1859
+ "manufacturer",
1860
+ "model",
1861
+ "flowRate",
1862
+ "efficiency",
1863
+ ],
1864
+ },
1865
+ ],
1866
+ },
1867
+ maintenance: {
1868
+ sources: [
1869
+ {
1870
+ source: {
1871
+ type: "view",
1872
+ space: "maintenance",
1873
+ externalId: "MaintenanceEvent",
1874
+ version: "v1",
1875
+ },
1876
+ properties: ["scheduledDate", "completedDate", "cost", "notes"],
1877
+ },
1878
+ ],
1879
+ },
1880
+ },
1881
+ });
1882
+
1883
+ console.log("Query results:");
1884
+ console.log(`Found ${queryResult.items.pumps.length} efficient pumps`);
1885
+ queryResult.items.pumps.forEach((pump) => {
1886
+ console.log(`\nPump: ${pump.externalId}`);
1887
+ console.log(
1888
+ `- Serial: ${pump.properties?.equipment?.Pump?.serialNumber}`
1889
+ );
1890
+ console.log(
1891
+ `- Efficiency: ${pump.properties?.equipment?.Pump?.efficiency}%`
1892
+ );
1893
+ });
1894
+
1895
+ // 10. Aggregate maintenance costs
1896
+ console.log("\nAggregating maintenance costs...");
1897
+ const aggregation = await client.instances.aggregate({
1898
+ view: {
1899
+ type: "view",
1900
+ space: "maintenance",
1901
+ externalId: "MaintenanceEvent",
1902
+ version: "v1",
1903
+ },
1904
+ groupBy: ["notes"],
1905
+ aggregates: [
1906
+ { count: { property: "externalId" } },
1907
+ { sum: { property: "cost" } },
1908
+ { avg: { property: "cost" } },
1909
+ ],
1910
+ });
1911
+
1912
+ console.log("Maintenance cost summary:");
1913
+ aggregation.items.forEach((group) => {
1914
+ console.log(`- Count: ${group.aggregates[0].value}`);
1915
+ console.log(`- Total cost: $${group.aggregates[1].value}`);
1916
+ console.log(`- Average cost: $${group.aggregates[2].value}`);
1917
+ });
1918
+ } catch (error) {
1919
+ if (error instanceof CogniteError) {
1920
+ console.error(`CDF API Error ${error.status}: ${error.errorMessage}`);
1921
+ if (error.extra) {
1922
+ console.error("Details:", JSON.stringify(error.extra, null, 2));
1923
+ }
1924
+ } else {
1925
+ console.error("Unexpected error:", error);
1926
+ }
1927
+ }
1928
+ }
1929
+
1930
+ // Run the example
1931
+ buildIndustrialDataModel();
1932
+ ```
1933
+
1934
+ This example demonstrates:
1935
+
1936
+ - Creating spaces for logical organization
1937
+ - Creating containers to define physical storage
1938
+ - Building views with inheritance and property mapping
1939
+ - Composing data models from views
1940
+ - Creating nodes with typed properties
1941
+ - Establishing relationships using edges
1942
+ - Querying across related data
1943
+ - Aggregating instance data
1944
+ - Handling errors appropriately
1945
+
1946
+ ## Best Practices
1947
+
1948
+ 1. **Space Organization**
1949
+
1950
+ - Use meaningful space names that reflect organizational structure
1951
+ - Separate concerns (e.g., `equipment`, `maintenance`, `operations`)
1952
+ - Consider access control requirements when designing spaces
1953
+
1954
+ 2. **Container Design**
1955
+
1956
+ - Keep containers focused on a single concept
1957
+ - Use appropriate data types and constraints
1958
+ - Add indexes for frequently queried properties
1959
+ - Set sensible defaults and nullable flags
1960
+
1961
+ 3. **View Composition**
1962
+
1963
+ - Use inheritance to avoid duplication
1964
+ - Apply filters to create specialized views
1965
+ - Document views thoroughly with descriptions
1966
+ - Version views when making breaking changes
1967
+
1968
+ 4. **Data Model Structure**
1969
+
1970
+ - Group related views into cohesive data models
1971
+ - Version data models for application compatibility
1972
+ - Include all necessary views for a use case
1973
+ - Document the intended usage clearly
1974
+
1975
+ 5. **Instance Management**
1976
+
1977
+ - Use meaningful external IDs following a naming convention
1978
+ - Leverage node types for categorization
1979
+ - Model relationships explicitly as edges
1980
+ - Include metadata in properties for traceability
1981
+
1982
+ 6. **Query Optimization**
1983
+
1984
+ - Use filters to reduce result sets early
1985
+ - Leverage indexes in containers
1986
+ - Paginate large result sets with cursors
1987
+ - Select only needed properties
1988
+
1989
+ 7. **Error Handling**
1990
+ - Implement retry logic for transient failures
1991
+ - Handle version conflicts appropriately
1992
+ - Validate data before upserting
1993
+ - Log errors with context for debugging
1994
+
1995
+
1996
+