cognite-create 0.2.14 → 0.2.16

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.
@@ -0,0 +1,1525 @@
1
+ ---
2
+ alwaysApply: true
3
+ ---
4
+
5
+ # Cognite Core APIs SDK Guide
6
+
7
+ ## Introduction
8
+
9
+ This guide covers the core Cognite Data Fusion (CDF) APIs that handle industrial data management: **3D Models**, **Files**, **Time Series**, **Data Points**, **Raw** (NoSQL storage), and **Units**. These APIs enable you to work with various types of industrial data including 3D models for digital twins, files for documents and images, time series for sensor data, raw tables for flexible storage, and standardized units for measurements.
10
+
11
+ ## Installation
12
+
13
+ To use these APIs, install the Cognite SDK:
14
+
15
+ Using npm:
16
+
17
+ ```bash
18
+ npm install @cognite/sdk --save
19
+ ```
20
+
21
+ Using yarn:
22
+
23
+ ```bash
24
+ yarn add @cognite/sdk
25
+ ```
26
+
27
+ ## Initialization
28
+
29
+ Initialize the CogniteClient with your project details and authentication:
30
+
31
+ ```javascript
32
+ import { CogniteClient } from "@cognite/sdk";
33
+
34
+ const client = new CogniteClient({
35
+ appId: "YOUR_APP_NAME",
36
+ project: "YOUR_PROJECT_NAME",
37
+ oidcTokenProvider: async () => {
38
+ return "YOUR_OIDC_ACCESS_TOKEN";
39
+ },
40
+ baseUrl: "https://api.cognitedata.com", // Optional
41
+ });
42
+ ```
43
+
44
+ ## 3D APIs
45
+
46
+ CDF's 3D APIs enable you to work with 3D models for digital twins, including CAD models, point clouds, and 360-degree images.
47
+
48
+ ### Models 3D API
49
+
50
+ #### client.models3D.create(models)
51
+
52
+ - **Description**: Creates new 3D models
53
+ - **Parameters**:
54
+ - `models` (CreateModel3D[], required): Array of 3D model definitions
55
+ - **Return Type**: Promise<Model3D[]>
56
+ - **Example**:
57
+
58
+ ```javascript
59
+ const models = await client.models3D.create([
60
+ {
61
+ name: "Process Plant 3D Model",
62
+ description: "Complete 3D model of the processing facility",
63
+ dataSetId: 123456789,
64
+ metadata: {
65
+ source: "AutoCAD",
66
+ version: "2024",
67
+ },
68
+ },
69
+ ]);
70
+ ```
71
+
72
+ #### client.models3D.list(scope?)
73
+
74
+ - **Description**: Lists 3D models with optional filtering
75
+ - **Parameters**:
76
+ - `scope` (Model3DListRequest, optional): Filter options
77
+ - **Return Type**: CursorAndAsyncIterator<Model3D>
78
+ - **Example**:
79
+
80
+ ```javascript
81
+ // List published 3D models
82
+ const publishedModels = await client.models3D
83
+ .list({ published: true })
84
+ .autoPagingToArray();
85
+
86
+ // List all models
87
+ const allModels = await client.models3D.list().autoPagingToArray();
88
+ ```
89
+
90
+ #### client.models3D.retrieve(id)
91
+
92
+ - **Description**: Retrieves a specific 3D model
93
+ - **Parameters**:
94
+ - `id` (number, required): Model ID
95
+ - **Return Type**: Promise<Model3D>
96
+ - **Example**:
97
+
98
+ ```javascript
99
+ const model = await client.models3D.retrieve(3744350296805509);
100
+ console.log(`Model: ${model.name}`);
101
+ console.log(`Created: ${new Date(model.createdTime)}`);
102
+ ```
103
+
104
+ #### client.models3D.update(changes)
105
+
106
+ - **Description**: Updates 3D models
107
+ - **Parameters**:
108
+ - `changes` (UpdateModel3D[], required): Update operations
109
+ - **Return Type**: Promise<Model3D[]>
110
+ - **Example**:
111
+
112
+ ```javascript
113
+ const updated = await client.models3D.update([
114
+ {
115
+ id: 3744350296805509,
116
+ update: {
117
+ name: { set: "Updated Plant Model" },
118
+ metadata: { set: { status: "reviewed" } },
119
+ },
120
+ },
121
+ ]);
122
+ ```
123
+
124
+ #### client.models3D.delete(ids)
125
+
126
+ - **Description**: Deletes 3D models
127
+ - **Parameters**:
128
+ - `ids` (InternalId[], required): Model IDs to delete
129
+ - **Return Type**: Promise<{}>
130
+ - **Example**:
131
+
132
+ ```javascript
133
+ await client.models3D.delete([{ id: 3744350296805509 }]);
134
+ ```
135
+
136
+ ### Revisions 3D API
137
+
138
+ 3D revisions represent versions of a 3D model, linked to uploaded 3D files.
139
+
140
+ #### client.revisions3D.create(modelId, items)
141
+
142
+ - **Description**: Creates revisions for a 3D model
143
+ - **Parameters**:
144
+ - `modelId` (number, required): Parent model ID
145
+ - `items` (CreateRevision3D[], required): Revision definitions
146
+ - **Return Type**: Promise<Revision3D[]>
147
+ - **Example**:
148
+
149
+ ```javascript
150
+ const revisions = await client.revisions3D.create(3744350296805509, [
151
+ {
152
+ fileId: 8252999965991682,
153
+ published: false,
154
+ rotation: [0, 0, 0],
155
+ scale: [1, 1, 1],
156
+ translation: [0, 0, 0],
157
+ metadata: {
158
+ revision: "A",
159
+ status: "draft",
160
+ },
161
+ },
162
+ ]);
163
+ ```
164
+
165
+ #### client.revisions3D.list(modelId, filter?)
166
+
167
+ - **Description**: Lists revisions for a 3D model
168
+ - **Parameters**:
169
+ - `modelId` (number, required): Model ID
170
+ - `filter` (Revision3DListRequest, optional): Filter options
171
+ - **Return Type**: CursorAndAsyncIterator<Revision3D>
172
+ - **Example**:
173
+
174
+ ```javascript
175
+ const revisions = await client.revisions3D
176
+ .list(3744350296805509, {
177
+ published: true,
178
+ })
179
+ .autoPagingToArray();
180
+ ```
181
+
182
+ #### client.revisions3D.update(modelId, changes)
183
+
184
+ - **Description**: Updates 3D revisions
185
+ - **Parameters**:
186
+ - `modelId` (number, required): Model ID
187
+ - `changes` (UpdateRevision3D[], required): Update operations
188
+ - **Return Type**: Promise<Revision3D[]>
189
+ - **Example**:
190
+
191
+ ```javascript
192
+ const updated = await client.revisions3D.update(3744350296805509, [
193
+ {
194
+ id: 4190022127342195,
195
+ update: {
196
+ published: { set: true },
197
+ rotation: { set: [0, 0, 90] },
198
+ metadata: { set: { status: "approved" } },
199
+ },
200
+ },
201
+ ]);
202
+ ```
203
+
204
+ ### Asset Mappings 3D API
205
+
206
+ Links 3D model nodes to assets in CDF.
207
+
208
+ #### client.assetMappings3D.create(modelId, revisionId, items)
209
+
210
+ - **Description**: Creates mappings between 3D nodes and assets
211
+ - **Parameters**:
212
+ - `modelId` (number, required): Model ID
213
+ - `revisionId` (number, required): Revision ID
214
+ - `items` (CreateAssetMapping3D[], required): Mapping definitions
215
+ - **Return Type**: Promise<AssetMapping3D[]>
216
+ - **Example**:
217
+
218
+ ```javascript
219
+ const mappings = await client.assetMappings3D.create(
220
+ 3744350296805509,
221
+ 4190022127342195,
222
+ [
223
+ {
224
+ nodeId: 1234,
225
+ assetId: 5678,
226
+ },
227
+ {
228
+ nodeId: 2345,
229
+ assetId: 6789,
230
+ },
231
+ ]
232
+ );
233
+ ```
234
+
235
+ #### client.assetMappings3D.list(modelId, revisionId, scope?)
236
+
237
+ - **Description**: Lists asset mappings for a revision
238
+ - **Parameters**:
239
+ - `modelId` (number, required): Model ID
240
+ - `revisionId` (number, required): Revision ID
241
+ - `scope` (AssetMappings3DListFilter, optional): Filter options
242
+ - **Return Type**: CursorAndAsyncIterator<AssetMapping3D>
243
+ - **Example**:
244
+
245
+ ```javascript
246
+ const mappings = await client.assetMappings3D
247
+ .list(3744350296805509, 4190022127342195, {
248
+ assetId: 5678,
249
+ })
250
+ .autoPagingToArray();
251
+ ```
252
+
253
+ ### Files 3D API
254
+
255
+ Manages 3D file uploads for models.
256
+
257
+ #### client.files3D.retrieve(fileId)
258
+
259
+ - **Description**: Retrieves 3D file information
260
+ - **Parameters**:
261
+ - `fileId` (number, required): File ID
262
+ - **Return Type**: Promise<File3D>
263
+ - **Example**:
264
+
265
+ ```javascript
266
+ const file3D = await client.files3D.retrieve(8252999965991682);
267
+ console.log(`File: ${file3D.fileName}`);
268
+ console.log(`Size: ${file3D.size} bytes`);
269
+ ```
270
+
271
+ ## Files API
272
+
273
+ The Files API manages documents, images, and other file types in CDF.
274
+
275
+ ### client.files.upload(fileInfo, fileContent?, overwrite?, waitUntilAcknowledged?)
276
+
277
+ - **Description**: Uploads a file to CDF
278
+ - **Parameters**:
279
+ - `fileInfo` (ExternalFileInfo, required): File metadata
280
+ - `fileContent` (FileContent, optional): File data (Buffer, Blob, string, etc.)
281
+ - `overwrite` (boolean, optional): Whether to overwrite existing file
282
+ - `waitUntilAcknowledged` (boolean, optional): Wait for upload confirmation
283
+ - **Return Type**: Promise<FileUploadResponse | FileInfo>
284
+ - **Example**:
285
+
286
+ ```javascript
287
+ // Upload with content
288
+ const file = await client.files.upload(
289
+ {
290
+ name: "equipment-manual.pdf",
291
+ externalId: "manual-pump-001",
292
+ mimeType: "application/pdf",
293
+ source: "manufacturer-website",
294
+ assetIds: [123456789],
295
+ dataSetId: 987654321,
296
+ metadata: {
297
+ documentType: "manual",
298
+ equipmentType: "pump",
299
+ language: "en",
300
+ },
301
+ },
302
+ fileBuffer // Buffer, Blob, or string
303
+ );
304
+
305
+ // Upload metadata only (get upload URL)
306
+ const uploadInfo = await client.files.upload({
307
+ name: "large-video.mp4",
308
+ mimeType: "video/mp4",
309
+ });
310
+ // Then upload to uploadInfo.uploadUrl separately
311
+ ```
312
+
313
+ ### client.files.list(scope?)
314
+
315
+ - **Description**: Lists files with advanced filtering
316
+ - **Parameters**:
317
+ - `scope` (FileRequestFilter, optional): Filter and pagination options
318
+ - **Return Type**: CursorAndAsyncIterator<FileInfo>
319
+ - **Example**:
320
+
321
+ ```javascript
322
+ // List PDF files
323
+ const pdfFiles = await client.files
324
+ .list({
325
+ filter: {
326
+ mimeType: "application/pdf",
327
+ assetIds: [123456789],
328
+ uploaded: true,
329
+ },
330
+ })
331
+ .autoPagingToArray();
332
+
333
+ // List files by source
334
+ const manualFiles = await client.files
335
+ .list({
336
+ filter: {
337
+ source: "manufacturer-website",
338
+ createdTime: {
339
+ min: new Date("2024-01-01"),
340
+ },
341
+ },
342
+ limit: 100,
343
+ })
344
+ .autoPagingToArray();
345
+ ```
346
+
347
+ ### client.files.retrieve(ids, params?)
348
+
349
+ - **Description**: Retrieves specific files by ID
350
+ - **Parameters**:
351
+ - `ids` (IdEitherWithInstance[], required): File identifiers
352
+ - `params` (FileRetrieveParams, optional): Additional parameters
353
+ - **Return Type**: Promise<FileInfo[]>
354
+ - **Example**:
355
+
356
+ ```javascript
357
+ const files = await client.files.retrieve([
358
+ { id: 8252999965991682 },
359
+ { externalId: "manual-pump-001" },
360
+ ]);
361
+
362
+ files.forEach((file) => {
363
+ console.log(`File: ${file.name}`);
364
+ console.log(`Size: ${file.size} bytes`);
365
+ console.log(`Uploaded: ${file.uploaded}`);
366
+ });
367
+ ```
368
+
369
+ ### client.files.download(items)
370
+
371
+ - **Description**: Downloads file content
372
+ - **Parameters**:
373
+ - `items` (FileDownloadRequest[], required): Files to download
374
+ - **Return Type**: Promise<(FileContent | undefined)[]>
375
+ - **Example**:
376
+
377
+ ```javascript
378
+ const contents = await client.files.download([
379
+ { id: 8252999965991682 },
380
+ { externalId: "manual-pump-001" },
381
+ ]);
382
+
383
+ // Save first file
384
+ const fileContent = contents[0];
385
+ if (fileContent) {
386
+ // fileContent is ArrayBuffer
387
+ const buffer = Buffer.from(fileContent);
388
+ fs.writeFileSync("downloaded-manual.pdf", buffer);
389
+ }
390
+ ```
391
+
392
+ ### client.files.search(query)
393
+
394
+ - **Description**: Searches files using text queries
395
+ - **Parameters**:
396
+ - `query` (FilesSearchFilter, required): Search parameters
397
+ - **Return Type**: Promise<FileInfo[]>
398
+ - **Example**:
399
+
400
+ ```javascript
401
+ const searchResults = await client.files.search({
402
+ filter: {
403
+ mimeType: "application/pdf",
404
+ },
405
+ search: {
406
+ name: "pump manual",
407
+ },
408
+ });
409
+ ```
410
+
411
+ ### client.files.update(changes)
412
+
413
+ - **Description**: Updates file metadata
414
+ - **Parameters**:
415
+ - `changes` (FileChangeUpdate[], required): Update operations
416
+ - **Return Type**: Promise<FileInfo[]>
417
+ - **Example**:
418
+
419
+ ```javascript
420
+ const updated = await client.files.update([
421
+ {
422
+ id: 8252999965991682,
423
+ update: {
424
+ metadata: { set: { reviewed: "true", reviewer: "John Doe" } },
425
+ assetIds: { add: [234567890] },
426
+ labels: { add: [{ externalId: "approved" }] },
427
+ },
428
+ },
429
+ ]);
430
+ ```
431
+
432
+ ### client.files.delete(ids)
433
+
434
+ - **Description**: Deletes files
435
+ - **Parameters**:
436
+ - `ids` (IdEither[], required): File identifiers
437
+ - **Return Type**: Promise<{}>
438
+ - **Example**:
439
+
440
+ ```javascript
441
+ await client.files.delete([
442
+ { id: 8252999965991682 },
443
+ { externalId: "obsolete-manual" },
444
+ ]);
445
+ ```
446
+
447
+ ### Multipart Upload for Large Files
448
+
449
+ For files larger than 5GB, use multipart upload:
450
+
451
+ ```javascript
452
+ // 1. Initialize multipart upload
453
+ const uploadSession = await client.files.multipartUploadSession.create({
454
+ name: "large-dataset.csv",
455
+ mimeType: "text/csv",
456
+ });
457
+
458
+ // 2. Upload parts (5MB - 5GB each)
459
+ const uploadURLs = await client.files.multipartUploadSession.getUploadUrls({
460
+ id: uploadSession.id,
461
+ parts: 10, // Number of parts
462
+ });
463
+
464
+ // 3. Upload each part to its URL
465
+ for (let i = 0; i < uploadURLs.urls.length; i++) {
466
+ const partData = getFilePart(i); // Your logic to get file chunks
467
+ await uploadToUrl(uploadURLs.urls[i], partData);
468
+ }
469
+
470
+ // 4. Complete upload
471
+ const file = await client.files.multipartUploadSession.complete({
472
+ id: uploadSession.id,
473
+ partETags: etags, // ETags from each part upload
474
+ });
475
+ ```
476
+
477
+ ## Time Series API
478
+
479
+ Manages time series definitions for sensor data, measurements, and other time-based data.
480
+
481
+ ### client.timeseries.create(items)
482
+
483
+ - **Description**: Creates new time series
484
+ - **Parameters**:
485
+ - `items` (ExternalTimeseries[], required): Time series definitions
486
+ - **Return Type**: Promise<Timeseries[]>
487
+ - **Example**:
488
+
489
+ ```javascript
490
+ const timeseries = await client.timeseries.create([
491
+ {
492
+ externalId: "temperature-sensor-001",
493
+ name: "Temperature Sensor 001",
494
+ description: "Inlet temperature for pump P-001",
495
+ isString: false,
496
+ unit: "°C",
497
+ assetId: 123456789,
498
+ dataSetId: 987654321,
499
+ metadata: {
500
+ location: "inlet",
501
+ sensorType: "PT100",
502
+ calibrationDate: "2024-01-15",
503
+ },
504
+ },
505
+ {
506
+ externalId: "pump-status-001",
507
+ name: "Pump Status 001",
508
+ isString: true, // String time series
509
+ assetId: 123456789,
510
+ },
511
+ ]);
512
+ ```
513
+
514
+ ### client.timeseries.list(scope?)
515
+
516
+ - **Description**: Lists time series with filtering
517
+ - **Parameters**:
518
+ - `scope` (TimeseriesFilterQuery, optional): Filter options
519
+ - **Return Type**: CursorAndAsyncIterator<Timeseries>
520
+ - **Example**:
521
+
522
+ ```javascript
523
+ // List numeric time series for an asset
524
+ const numericSeries = await client.timeseries
525
+ .list({
526
+ filter: {
527
+ assetIds: [123456789],
528
+ isString: false,
529
+ },
530
+ })
531
+ .autoPagingToArray();
532
+
533
+ // List by unit
534
+ const temperatureSeries = await client.timeseries
535
+ .list({
536
+ filter: {
537
+ unit: "°C",
538
+ },
539
+ limit: 100,
540
+ })
541
+ .autoPagingToArray();
542
+ ```
543
+
544
+ ### client.timeseries.retrieve(ids, params?)
545
+
546
+ - **Description**: Retrieves specific time series
547
+ - **Parameters**:
548
+ - `ids` (IdEitherWithInstance[], required): Time series identifiers
549
+ - `params` (TimeseriesRetrieveParams, optional): Additional parameters
550
+ - **Return Type**: Promise<Timeseries[]>
551
+ - **Example**:
552
+
553
+ ```javascript
554
+ const timeseries = await client.timeseries.retrieve([
555
+ { id: 987654321 },
556
+ { externalId: "temperature-sensor-001" },
557
+ ]);
558
+ ```
559
+
560
+ ### client.timeseries.search(query)
561
+
562
+ - **Description**: Searches time series
563
+ - **Parameters**:
564
+ - `query` (TimeseriesSearchFilter, required): Search parameters
565
+ - **Return Type**: Promise<Timeseries[]>
566
+ - **Example**:
567
+
568
+ ```javascript
569
+ const results = await client.timeseries.search({
570
+ filter: {
571
+ isString: false,
572
+ assetIds: [123456789],
573
+ },
574
+ search: {
575
+ query: "temperature",
576
+ },
577
+ limit: 50,
578
+ });
579
+ ```
580
+
581
+ ### client.timeseries.update(changes)
582
+
583
+ - **Description**: Updates time series metadata
584
+ - **Parameters**:
585
+ - `changes` (TimeSeriesUpdate[], required): Update operations
586
+ - **Return Type**: Promise<Timeseries[]>
587
+ - **Example**:
588
+
589
+ ```javascript
590
+ const updated = await client.timeseries.update([
591
+ {
592
+ id: 987654321,
593
+ update: {
594
+ name: { set: "Updated Temperature Sensor" },
595
+ unit: { set: "K" }, // Change to Kelvin
596
+ metadata: { set: { calibrated: "2024-02-01" } },
597
+ },
598
+ },
599
+ ]);
600
+ ```
601
+
602
+ ### client.timeseries.delete(ids)
603
+
604
+ - **Description**: Deletes time series (and all data points)
605
+ - **Parameters**:
606
+ - `ids` (IdEither[], required): Time series identifiers
607
+ - **Return Type**: Promise<{}>
608
+ - **Example**:
609
+
610
+ ```javascript
611
+ await client.timeseries.delete([
612
+ { id: 987654321 },
613
+ { externalId: "obsolete-sensor" },
614
+ ]);
615
+ ```
616
+
617
+ ## Data Points API
618
+
619
+ Manages the actual time series data values.
620
+
621
+ ### client.datapoints.insert(items)
622
+
623
+ - **Description**: Inserts data points into time series
624
+ - **Parameters**:
625
+ - `items` (ExternalDatapointsQuery[], required): Data point batches
626
+ - **Return Type**: Promise<{}>
627
+ - **Example**:
628
+
629
+ ```javascript
630
+ await client.datapoints.insert([
631
+ {
632
+ externalId: "temperature-sensor-001",
633
+ datapoints: [
634
+ { timestamp: new Date("2024-01-01T12:00:00Z"), value: 25.5 },
635
+ { timestamp: new Date("2024-01-01T12:01:00Z"), value: 25.7 },
636
+ { timestamp: Date.now(), value: 26.1 },
637
+ ],
638
+ },
639
+ {
640
+ id: 987654321, // Can use ID instead of externalId
641
+ datapoints: [
642
+ { timestamp: 1704110400000, value: 101.3 }, // Unix timestamp in ms
643
+ ],
644
+ },
645
+ {
646
+ externalId: "pump-status-001",
647
+ datapoints: [
648
+ { timestamp: new Date(), value: "RUNNING" }, // String value
649
+ ],
650
+ },
651
+ ]);
652
+ ```
653
+
654
+ ### client.datapoints.retrieve(query)
655
+
656
+ - **Description**: Retrieves data points with optional aggregation
657
+ - **Parameters**:
658
+ - `query` (DatapointsMultiQuery, required): Query parameters
659
+ - **Return Type**: Promise<DatapointAggregates[] | Datapoints[]>
660
+ - **Example**:
661
+
662
+ ```javascript
663
+ // Get raw data points
664
+ const rawData = await client.datapoints.retrieve({
665
+ items: [
666
+ {
667
+ externalId: "temperature-sensor-001",
668
+ },
669
+ ],
670
+ start: "2024-01-01",
671
+ end: new Date(),
672
+ limit: 1000,
673
+ });
674
+
675
+ // Get aggregated data
676
+ const aggregatedData = await client.datapoints.retrieve({
677
+ items: [
678
+ {
679
+ externalId: "temperature-sensor-001",
680
+ aggregates: ["average", "max", "min", "count"],
681
+ granularity: "1h",
682
+ },
683
+ ],
684
+ start: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000), // 7 days ago
685
+ end: "now",
686
+ });
687
+
688
+ // Multiple time series with different aggregations
689
+ const multiData = await client.datapoints.retrieve({
690
+ items: [
691
+ {
692
+ externalId: "temperature-sensor-001",
693
+ aggregates: ["average"],
694
+ granularity: "1h",
695
+ },
696
+ {
697
+ externalId: "pressure-sensor-001",
698
+ aggregates: ["max", "min"],
699
+ granularity: "1h",
700
+ },
701
+ ],
702
+ start: "2024-01-01",
703
+ end: "2024-01-31",
704
+ timezone: "UTC",
705
+ });
706
+ ```
707
+
708
+ ### client.datapoints.retrieveLatest(items, params?)
709
+
710
+ - **Description**: Gets the latest data point before a given time
711
+ - **Parameters**:
712
+ - `items` (LatestDataBeforeRequest[], required): Query items
713
+ - `params` (LatestDataParams, optional): Additional parameters
714
+ - **Return Type**: Promise<Datapoints[]>
715
+ - **Example**:
716
+
717
+ ```javascript
718
+ const latestData = await client.datapoints.retrieveLatest([
719
+ {
720
+ externalId: "temperature-sensor-001",
721
+ before: "now",
722
+ },
723
+ {
724
+ id: 987654321,
725
+ before: new Date("2024-01-01"),
726
+ },
727
+ ]);
728
+
729
+ latestData.forEach((series) => {
730
+ const latest = series.datapoints[0];
731
+ console.log(
732
+ `Series ${series.externalId}: ${latest.value} at ${new Date(
733
+ latest.timestamp
734
+ )}`
735
+ );
736
+ });
737
+ ```
738
+
739
+ ### client.datapoints.delete(items)
740
+
741
+ - **Description**: Deletes data points from time series
742
+ - **Parameters**:
743
+ - `items` (DatapointsDeleteRequest[], required): Deletion ranges
744
+ - **Return Type**: Promise<{}>
745
+ - **Example**:
746
+
747
+ ```javascript
748
+ // Delete specific time range
749
+ await client.datapoints.delete([
750
+ {
751
+ externalId: "temperature-sensor-001",
752
+ inclusiveBegin: new Date("2024-01-01"),
753
+ exclusiveEnd: new Date("2024-01-02"),
754
+ },
755
+ ]);
756
+
757
+ // Delete all data points
758
+ await client.datapoints.delete([
759
+ {
760
+ id: 987654321,
761
+ // Omit time range to delete all
762
+ },
763
+ ]);
764
+ ```
765
+
766
+ ### Synthetic Time Series
767
+
768
+ Query calculated time series using expressions:
769
+
770
+ ```javascript
771
+ const synthetic = await client.timeseries.syntheticQuery([
772
+ {
773
+ expression: "ts{externalId='temperature-sensor-001'} * 1.8 + 32", // Convert C to F
774
+ start: "2024-01-01",
775
+ end: "2024-01-02",
776
+ limit: 100,
777
+ },
778
+ {
779
+ expression: "ts{externalId='flow-rate'} * ts{externalId='density'}", // Calculate mass flow
780
+ start: "2024-01-01",
781
+ end: "2024-01-02",
782
+ granularity: "1h",
783
+ aggregates: ["average"],
784
+ },
785
+ ]);
786
+ ```
787
+
788
+ ## Raw API
789
+
790
+ The Raw API provides flexible NoSQL storage for data that doesn't fit the standard resource types.
791
+
792
+ ### Database Operations
793
+
794
+ #### client.raw.createDatabases(items)
795
+
796
+ - **Description**: Creates raw databases
797
+ - **Parameters**:
798
+ - `items` (RawDBName[], required): Database names
799
+ - **Return Type**: Promise<RawDB[]>
800
+ - **Example**:
801
+
802
+ ```javascript
803
+ const databases = await client.raw.createDatabases([
804
+ { name: "sensor_configurations" },
805
+ { name: "maintenance_logs" },
806
+ ]);
807
+ ```
808
+
809
+ #### client.raw.listDatabases(scope?)
810
+
811
+ - **Description**: Lists raw databases
812
+ - **Parameters**:
813
+ - `scope` (ListRawDatabases, optional): List options
814
+ - **Return Type**: CursorAndAsyncIterator<RawDB>
815
+ - **Example**:
816
+
817
+ ```javascript
818
+ const databases = await client.raw.listDatabases().autoPagingToArray();
819
+ databases.forEach((db) => {
820
+ console.log(`Database: ${db.name}`);
821
+ });
822
+ ```
823
+
824
+ #### client.raw.deleteDatabases(items, params?)
825
+
826
+ - **Description**: Deletes databases and all their contents
827
+ - **Parameters**:
828
+ - `items` (RawDBName[], required): Database names
829
+ - `params` (RawDatabaseDeleteParams, optional): Delete options
830
+ - **Return Type**: Promise<{}>
831
+ - **Example**:
832
+
833
+ ```javascript
834
+ await client.raw.deleteDatabases([{ name: "obsolete_data" }], {
835
+ recursive: true, // Delete even if contains tables
836
+ });
837
+ ```
838
+
839
+ ### Table Operations
840
+
841
+ #### client.raw.createTables(databaseName, items, ensureParent?)
842
+
843
+ - **Description**: Creates tables in a database
844
+ - **Parameters**:
845
+ - `databaseName` (string, required): Database name
846
+ - `items` (RawDBTableName[], required): Table names
847
+ - `ensureParent` (boolean, optional): Create database if missing
848
+ - **Return Type**: Promise<RawDBTable[]>
849
+ - **Example**:
850
+
851
+ ```javascript
852
+ const tables = await client.raw.createTables(
853
+ "sensor_configurations",
854
+ [{ name: "temperature_sensors" }, { name: "pressure_sensors" }],
855
+ true // Create database if it doesn't exist
856
+ );
857
+ ```
858
+
859
+ #### client.raw.listTables(databaseName, scope?)
860
+
861
+ - **Description**: Lists tables in a database
862
+ - **Parameters**:
863
+ - `databaseName` (string, required): Database name
864
+ - `scope` (ListRawTables, optional): List options
865
+ - **Return Type**: CursorAndAsyncIterator<RawDBTable>
866
+ - **Example**:
867
+
868
+ ```javascript
869
+ const tables = await client.raw
870
+ .listTables("sensor_configurations")
871
+ .autoPagingToArray();
872
+ ```
873
+
874
+ #### client.raw.deleteTables(databaseName, items)
875
+
876
+ - **Description**: Deletes tables and all their rows
877
+ - **Parameters**:
878
+ - `databaseName` (string, required): Database name
879
+ - `items` (RawDBTableName[], required): Table names
880
+ - **Return Type**: Promise<{}>
881
+ - **Example**:
882
+
883
+ ```javascript
884
+ await client.raw.deleteTables("sensor_configurations", [
885
+ { name: "obsolete_table" },
886
+ ]);
887
+ ```
888
+
889
+ ### Row Operations
890
+
891
+ #### client.raw.insertRows(databaseName, tableName, items, ensureParent?)
892
+
893
+ - **Description**: Inserts or updates rows in a table
894
+ - **Parameters**:
895
+ - `databaseName` (string, required): Database name
896
+ - `tableName` (string, required): Table name
897
+ - `items` (RawDBRowInsert[], required): Rows to insert
898
+ - `ensureParent` (boolean, optional): Create table/database if missing
899
+ - **Return Type**: Promise<{}>
900
+ - **Example**:
901
+
902
+ ```javascript
903
+ await client.raw.insertRows(
904
+ "sensor_configurations",
905
+ "temperature_sensors",
906
+ [
907
+ {
908
+ key: "sensor-001",
909
+ columns: {
910
+ location: "Building A, Floor 2",
911
+ type: "PT100",
912
+ range_min: -50,
913
+ range_max: 200,
914
+ unit: "celsius",
915
+ calibration_date: "2024-01-15",
916
+ config: {
917
+ // Nested JSON
918
+ sampling_rate: 1000,
919
+ filter: "moving_average",
920
+ window_size: 10,
921
+ },
922
+ },
923
+ },
924
+ {
925
+ key: "sensor-002",
926
+ columns: {
927
+ location: "Building B, Floor 1",
928
+ type: "Thermocouple",
929
+ range_min: 0,
930
+ range_max: 1000,
931
+ unit: "celsius",
932
+ },
933
+ },
934
+ ],
935
+ true // Create table/database if missing
936
+ );
937
+ ```
938
+
939
+ #### client.raw.listRows(databaseName, tableName, options?)
940
+
941
+ - **Description**: Lists rows from a table with filtering
942
+ - **Parameters**:
943
+ - `databaseName` (string, required): Database name
944
+ - `tableName` (string, required): Table name
945
+ - `options` (ListRawRows, optional): Query options
946
+ - **Return Type**: CursorAndAsyncIterator<RawDBRow>
947
+ - **Example**:
948
+
949
+ ```javascript
950
+ // List all rows
951
+ const allRows = await client.raw
952
+ .listRows("sensor_configurations", "temperature_sensors")
953
+ .autoPagingToArray();
954
+
955
+ // Filter by columns
956
+ const filteredRows = await client.raw
957
+ .listRows("sensor_configurations", "temperature_sensors", {
958
+ columns: ["location", "type", "unit"],
959
+ limit: 100,
960
+ })
961
+ .autoPagingToArray();
962
+
963
+ // Filter by key range
964
+ const rangeRows = await client.raw
965
+ .listRows("maintenance_logs", "pump_maintenance", {
966
+ minLastUpdatedTime: new Date("2024-01-01"),
967
+ maxLastUpdatedTime: new Date("2024-01-31"),
968
+ })
969
+ .autoPagingToArray();
970
+ ```
971
+
972
+ #### client.raw.retrieveRows(databaseName, tableName, items)
973
+
974
+ - **Description**: Retrieves specific rows by key
975
+ - **Parameters**:
976
+ - `databaseName` (string, required): Database name
977
+ - `tableName` (string, required): Table name
978
+ - `items` (RawDBRowKey[], required): Row keys
979
+ - **Return Type**: Promise<RawDBRow[]>
980
+ - **Example**:
981
+
982
+ ```javascript
983
+ const rows = await client.raw.retrieveRows(
984
+ "sensor_configurations",
985
+ "temperature_sensors",
986
+ [{ key: "sensor-001" }, { key: "sensor-002" }]
987
+ );
988
+
989
+ rows.forEach((row) => {
990
+ console.log(`Sensor ${row.key}: ${JSON.stringify(row.columns)}`);
991
+ });
992
+ ```
993
+
994
+ #### client.raw.deleteRows(databaseName, tableName, items)
995
+
996
+ - **Description**: Deletes rows from a table
997
+ - **Parameters**:
998
+ - `databaseName` (string, required): Database name
999
+ - `tableName` (string, required): Table name
1000
+ - `items` (RawDBRowKey[], required): Row keys to delete
1001
+ - **Return Type**: Promise<{}>
1002
+ - **Example**:
1003
+
1004
+ ```javascript
1005
+ await client.raw.deleteRows("sensor_configurations", "temperature_sensors", [
1006
+ { key: "obsolete-sensor-001" },
1007
+ { key: "obsolete-sensor-002" },
1008
+ ]);
1009
+ ```
1010
+
1011
+ ## Units API
1012
+
1013
+ The Units API provides access to standardized units of measurement and unit systems.
1014
+
1015
+ ### client.units.list()
1016
+
1017
+ - **Description**: Lists all supported units
1018
+ - **Parameters**: None
1019
+ - **Return Type**: CursorAndAsyncIterator<Unit>
1020
+ - **Example**:
1021
+
1022
+ ```javascript
1023
+ const units = await client.units.list().autoPagingToArray();
1024
+
1025
+ // Group units by quantity
1026
+ const unitsByQuantity = {};
1027
+ units.forEach((unit) => {
1028
+ if (!unitsByQuantity[unit.quantity]) {
1029
+ unitsByQuantity[unit.quantity] = [];
1030
+ }
1031
+ unitsByQuantity[unit.quantity].push(unit);
1032
+ });
1033
+
1034
+ console.log("Temperature units:", unitsByQuantity["Temperature"]);
1035
+ ```
1036
+
1037
+ ### client.units.retrieve(ids)
1038
+
1039
+ - **Description**: Retrieves specific units
1040
+ - **Parameters**:
1041
+ - `ids` (ExternalId[], required): Unit external IDs
1042
+ - **Return Type**: Promise<Unit[]>
1043
+ - **Example**:
1044
+
1045
+ ```javascript
1046
+ const units = await client.units.retrieve([
1047
+ { externalId: "temperature:deg_c" },
1048
+ { externalId: "pressure:bar" },
1049
+ { externalId: "flow:m3/h" },
1050
+ ]);
1051
+
1052
+ units.forEach((unit) => {
1053
+ console.log(`${unit.name} (${unit.symbol})`);
1054
+ console.log(` Quantity: ${unit.quantity}`);
1055
+ console.log(` Aliases: ${unit.aliases?.join(", ")}`);
1056
+ });
1057
+ ```
1058
+
1059
+ ### client.units.listUnitSystems()
1060
+
1061
+ - **Description**: Lists all supported unit systems
1062
+ - **Parameters**: None
1063
+ - **Return Type**: Promise<UnitSystem[]>
1064
+ - **Example**:
1065
+
1066
+ ```javascript
1067
+ const unitSystems = await client.units.listUnitSystems();
1068
+
1069
+ unitSystems.forEach((system) => {
1070
+ console.log(`System: ${system.name}`);
1071
+ console.log(` Quantities: ${Object.keys(system.quantities).join(", ")}`);
1072
+ });
1073
+
1074
+ // Get SI units for each quantity
1075
+ const siSystem = unitSystems.find((s) => s.name === "SI");
1076
+ if (siSystem) {
1077
+ console.log("SI base units:");
1078
+ Object.entries(siSystem.quantities).forEach(([quantity, unit]) => {
1079
+ console.log(` ${quantity}: ${unit}`);
1080
+ });
1081
+ }
1082
+ ```
1083
+
1084
+ ## Data Models
1085
+
1086
+ ### 3D Model Structure
1087
+
1088
+ ```typescript
1089
+ interface Model3D {
1090
+ id: number;
1091
+ name: string;
1092
+ description?: string;
1093
+ createdTime: number;
1094
+ dataSetId?: number;
1095
+ metadata?: Record<string, string>;
1096
+ published: boolean;
1097
+ }
1098
+
1099
+ interface Revision3D {
1100
+ id: number;
1101
+ fileId: number;
1102
+ published: boolean;
1103
+ status: "Queued" | "Processing" | "Done" | "Failed";
1104
+ createdTime: number;
1105
+ assetMappingCount: number;
1106
+ metadata?: Record<string, string>;
1107
+ rotation?: [number, number, number];
1108
+ scale?: [number, number, number];
1109
+ translation?: [number, number, number];
1110
+ camera?: {
1111
+ target: [number, number, number];
1112
+ position: [number, number, number];
1113
+ };
1114
+ }
1115
+
1116
+ interface AssetMapping3D {
1117
+ nodeId: number;
1118
+ assetId: number;
1119
+ treeIndex?: number;
1120
+ subtreeSize?: number;
1121
+ }
1122
+ ```
1123
+
1124
+ ### File Structure
1125
+
1126
+ ```typescript
1127
+ interface FileInfo {
1128
+ id: number;
1129
+ externalId?: string;
1130
+ name: string;
1131
+ source?: string;
1132
+ mimeType?: string;
1133
+ metadata?: Record<string, string>;
1134
+ assetIds?: number[];
1135
+ dataSetId?: number;
1136
+ sourceCreatedTime?: number;
1137
+ sourceModifiedTime?: number;
1138
+ uploaded: boolean;
1139
+ uploadedTime?: number;
1140
+ createdTime: number;
1141
+ lastUpdatedTime: number;
1142
+ uploadUrl?: string;
1143
+ downloadUrl?: string;
1144
+ size?: number;
1145
+ }
1146
+ ```
1147
+
1148
+ ### Time Series Structure
1149
+
1150
+ ```typescript
1151
+ interface Timeseries {
1152
+ id: number;
1153
+ externalId?: string;
1154
+ name?: string;
1155
+ isString: boolean;
1156
+ metadata?: Record<string, string>;
1157
+ unit?: string;
1158
+ assetId?: number;
1159
+ isStep: boolean;
1160
+ description?: string;
1161
+ securityCategories?: number[];
1162
+ dataSetId?: number;
1163
+ createdTime: number;
1164
+ lastUpdatedTime: number;
1165
+ }
1166
+ ```
1167
+
1168
+ ### Data Point Structure
1169
+
1170
+ ```typescript
1171
+ interface Datapoint {
1172
+ timestamp: number | Date;
1173
+ value: number | string;
1174
+ }
1175
+
1176
+ interface DatapointAggregates {
1177
+ timestamp: number;
1178
+ average?: number;
1179
+ max?: number;
1180
+ min?: number;
1181
+ count?: number;
1182
+ sum?: number;
1183
+ interpolation?: number;
1184
+ stepInterpolation?: number;
1185
+ totalVariation?: number;
1186
+ continuousVariance?: number;
1187
+ discreteVariance?: number;
1188
+ }
1189
+ ```
1190
+
1191
+ ### Raw Storage Structure
1192
+
1193
+ ```typescript
1194
+ interface RawDB {
1195
+ name: string;
1196
+ }
1197
+
1198
+ interface RawDBTable {
1199
+ name: string;
1200
+ }
1201
+
1202
+ interface RawDBRow {
1203
+ key: string;
1204
+ columns: Record<string, any>;
1205
+ lastUpdatedTime: number;
1206
+ }
1207
+ ```
1208
+
1209
+ ### Unit Structure
1210
+
1211
+ ```typescript
1212
+ interface Unit {
1213
+ externalId: string;
1214
+ name: string;
1215
+ longName: string;
1216
+ symbol: string;
1217
+ aliases?: string[];
1218
+ quantity: string;
1219
+ conversion?: {
1220
+ multiplier: number;
1221
+ offset: number;
1222
+ };
1223
+ source?: string;
1224
+ sourceReference?: string;
1225
+ }
1226
+
1227
+ interface UnitSystem {
1228
+ name: string;
1229
+ quantities: Record<string, string>; // quantity -> unit externalId
1230
+ }
1231
+ ```
1232
+
1233
+ ## Error Handling
1234
+
1235
+ All APIs use the same error structure as other CDF APIs:
1236
+
1237
+ ```javascript
1238
+ try {
1239
+ await client.files.upload({ name: "test.txt" }, fileContent);
1240
+ } catch (error) {
1241
+ if (error instanceof CogniteError) {
1242
+ switch (error.status) {
1243
+ case 400:
1244
+ console.error("Invalid request:", error.errorMessage);
1245
+ break;
1246
+ case 401:
1247
+ console.error("Authentication failed");
1248
+ break;
1249
+ case 409:
1250
+ console.error("Conflict:", error.errorMessage);
1251
+ break;
1252
+ case 413:
1253
+ console.error("File too large");
1254
+ break;
1255
+ case 429:
1256
+ console.error("Rate limited, retry later");
1257
+ break;
1258
+ default:
1259
+ console.error(`Error ${error.status}: ${error.errorMessage}`);
1260
+ }
1261
+ }
1262
+ }
1263
+ ```
1264
+
1265
+ ## Code Example
1266
+
1267
+ Here's a comprehensive example using multiple APIs together:
1268
+
1269
+ ```javascript
1270
+ import { CogniteClient } from "@cognite/sdk";
1271
+ import fs from "fs";
1272
+
1273
+ async function industrialDataExample() {
1274
+ // 1. Initialize client
1275
+ const client = new CogniteClient({
1276
+ appId: "IndustrialDataApp",
1277
+ project: "my-project",
1278
+ oidcTokenProvider: async () => process.env.CDF_ACCESS_TOKEN,
1279
+ });
1280
+
1281
+ try {
1282
+ // 2. Create time series for sensor data
1283
+ console.log("Creating time series...");
1284
+ const timeseries = await client.timeseries.create([
1285
+ {
1286
+ externalId: "temp-sensor-tank-001",
1287
+ name: "Tank 001 Temperature",
1288
+ unit: "°C",
1289
+ description: "Temperature sensor in storage tank 001",
1290
+ metadata: {
1291
+ location: "Storage Area A",
1292
+ sensorType: "PT100",
1293
+ },
1294
+ },
1295
+ {
1296
+ externalId: "level-sensor-tank-001",
1297
+ name: "Tank 001 Level",
1298
+ unit: "m",
1299
+ description: "Level sensor in storage tank 001",
1300
+ },
1301
+ ]);
1302
+ console.log(`Created ${timeseries.length} time series`);
1303
+
1304
+ // 3. Insert historical data points
1305
+ console.log("Inserting data points...");
1306
+ const now = Date.now();
1307
+ const dataPoints = [];
1308
+ for (let i = 0; i < 24; i++) {
1309
+ dataPoints.push({
1310
+ timestamp: now - i * 3600000, // Hourly data
1311
+ value: 20 + Math.random() * 10, // 20-30°C
1312
+ });
1313
+ }
1314
+
1315
+ await client.datapoints.insert([
1316
+ {
1317
+ externalId: "temp-sensor-tank-001",
1318
+ datapoints: dataPoints,
1319
+ },
1320
+ {
1321
+ externalId: "level-sensor-tank-001",
1322
+ datapoints: dataPoints.map((dp) => ({
1323
+ timestamp: dp.timestamp,
1324
+ value: 3 + Math.random() * 2, // 3-5m
1325
+ })),
1326
+ },
1327
+ ]);
1328
+ console.log("Data points inserted");
1329
+
1330
+ // 4. Upload equipment documentation
1331
+ console.log("Uploading documentation...");
1332
+ const pdfContent = fs.readFileSync("tank-manual.pdf");
1333
+ const file = await client.files.upload(
1334
+ {
1335
+ name: "Tank 001 Operations Manual.pdf",
1336
+ externalId: "manual-tank-001",
1337
+ mimeType: "application/pdf",
1338
+ metadata: {
1339
+ documentType: "operations-manual",
1340
+ equipment: "tank-001",
1341
+ version: "2.0",
1342
+ },
1343
+ },
1344
+ pdfContent
1345
+ );
1346
+ console.log(`Uploaded file: ${file.name}`);
1347
+
1348
+ // 5. Create 3D model for the facility
1349
+ console.log("Creating 3D model...");
1350
+ const model3D = await client.models3D.create([
1351
+ {
1352
+ name: "Storage Facility 3D Model",
1353
+ description: "Complete 3D model of storage facility including tanks",
1354
+ metadata: {
1355
+ source: "Revit",
1356
+ lastUpdated: "2024-01-15",
1357
+ },
1358
+ },
1359
+ ]);
1360
+ console.log(`Created 3D model: ${model3D[0].name}`);
1361
+
1362
+ // 6. Store sensor configurations in Raw
1363
+ console.log("Storing sensor configurations...");
1364
+ await client.raw.createDatabases([{ name: "sensor_configs" }]);
1365
+ await client.raw.createTables("sensor_configs", [
1366
+ { name: "temperature_sensors" },
1367
+ ]);
1368
+
1369
+ await client.raw.insertRows("sensor_configs", "temperature_sensors", [
1370
+ {
1371
+ key: "temp-sensor-tank-001",
1372
+ columns: {
1373
+ type: "PT100",
1374
+ range: { min: -50, max: 200 },
1375
+ accuracy: 0.1,
1376
+ calibration: {
1377
+ lastDate: "2024-01-15",
1378
+ nextDate: "2025-01-15",
1379
+ certificate: "CERT-2024-0123",
1380
+ },
1381
+ alarms: {
1382
+ high: 35,
1383
+ highHigh: 40,
1384
+ low: 15,
1385
+ lowLow: 10,
1386
+ },
1387
+ },
1388
+ },
1389
+ ]);
1390
+ console.log("Sensor configuration stored");
1391
+
1392
+ // 7. Query aggregated data
1393
+ console.log("Retrieving aggregated temperature data...");
1394
+ const aggregatedData = await client.datapoints.retrieve({
1395
+ items: [
1396
+ {
1397
+ externalId: "temp-sensor-tank-001",
1398
+ aggregates: ["average", "max", "min"],
1399
+ granularity: "6h",
1400
+ },
1401
+ ],
1402
+ start: now - 24 * 3600000,
1403
+ end: now,
1404
+ });
1405
+
1406
+ console.log("Temperature statistics (6-hour aggregates):");
1407
+ aggregatedData[0].datapoints.forEach((dp) => {
1408
+ console.log(
1409
+ ` ${new Date(dp.timestamp).toISOString()}: ` +
1410
+ `Avg=${dp.average?.toFixed(1)}°C, ` +
1411
+ `Max=${dp.max?.toFixed(1)}°C, ` +
1412
+ `Min=${dp.min?.toFixed(1)}°C`
1413
+ );
1414
+ });
1415
+
1416
+ // 8. Search for related files
1417
+ console.log("\nSearching for tank documentation...");
1418
+ const documents = await client.files.search({
1419
+ search: {
1420
+ name: "tank",
1421
+ },
1422
+ filter: {
1423
+ mimeType: "application/pdf",
1424
+ },
1425
+ limit: 10,
1426
+ });
1427
+ console.log(`Found ${documents.length} tank-related documents`);
1428
+
1429
+ // 9. Get sensor configuration from Raw
1430
+ console.log("\nRetrieving sensor configuration...");
1431
+ const sensorConfig = await client.raw.retrieveRows(
1432
+ "sensor_configs",
1433
+ "temperature_sensors",
1434
+ [{ key: "temp-sensor-tank-001" }]
1435
+ );
1436
+
1437
+ if (sensorConfig.length > 0) {
1438
+ const config = sensorConfig[0].columns;
1439
+ console.log("Sensor Configuration:");
1440
+ console.log(` Type: ${config.type}`);
1441
+ console.log(` Range: ${config.range.min}°C to ${config.range.max}°C`);
1442
+ console.log(` High Alarm: ${config.alarms.high}°C`);
1443
+ console.log(` Next Calibration: ${config.calibration.nextDate}`);
1444
+ }
1445
+
1446
+ // 10. List available units
1447
+ console.log("\nAvailable temperature units:");
1448
+ const units = await client.units.list().autoPagingToArray();
1449
+ const tempUnits = units.filter((u) => u.quantity === "Temperature");
1450
+ tempUnits.forEach((unit) => {
1451
+ console.log(` ${unit.name} (${unit.symbol})`);
1452
+ });
1453
+ } catch (error) {
1454
+ if (error instanceof CogniteError) {
1455
+ console.error(`CDF Error ${error.status}: ${error.errorMessage}`);
1456
+ console.error(`Request ID: ${error.requestId}`);
1457
+ } else {
1458
+ console.error("Unexpected error:", error);
1459
+ }
1460
+ }
1461
+ }
1462
+
1463
+ // Run the example
1464
+ industrialDataExample();
1465
+ ```
1466
+
1467
+ This example demonstrates:
1468
+
1469
+ - Creating time series for sensor data
1470
+ - Inserting and retrieving data points with aggregation
1471
+ - Uploading and managing files
1472
+ - Working with 3D models
1473
+ - Using Raw storage for flexible data
1474
+ - Querying units of measurement
1475
+ - Error handling
1476
+
1477
+ ## Best Practices
1478
+
1479
+ 1. **Time Series Design**
1480
+
1481
+ - Use meaningful external IDs following a naming convention
1482
+ - Set appropriate units for automatic unit conversion
1483
+ - Use string time series for status/state data
1484
+ - Consider data density when setting up aggregations
1485
+
1486
+ 2. **Data Points Management**
1487
+
1488
+ - Batch insert data points for efficiency (up to 100,000 per request)
1489
+ - Use appropriate granularity for aggregations
1490
+ - Consider using synthetic time series for calculations
1491
+ - Store raw data and use aggregations for visualization
1492
+
1493
+ 3. **File Management**
1494
+
1495
+ - Use external IDs for files that need stable references
1496
+ - Add comprehensive metadata for searchability
1497
+ - Use multipart upload for files over 5GB
1498
+ - Link files to relevant assets
1499
+
1500
+ 4. **Raw Storage Usage**
1501
+
1502
+ - Use Raw for configuration data and flexible schemas
1503
+ - Design meaningful key structures for efficient queries
1504
+ - Consider data size limits (4MB per row)
1505
+ - Use columns parameter to retrieve only needed data
1506
+
1507
+ 5. **3D Models**
1508
+
1509
+ - Publish revisions only when ready for consumption
1510
+ - Use asset mappings to link 3D nodes to assets
1511
+ - Set appropriate transformation matrices for alignment
1512
+ - Add metadata for version tracking
1513
+
1514
+ 6. **Performance Optimization**
1515
+
1516
+ - Use cursor pagination for large result sets
1517
+ - Leverage filtering to reduce data transfer
1518
+ - Batch operations when possible
1519
+ - Cache frequently accessed metadata
1520
+
1521
+ 7. **Error Handling**
1522
+ - Implement exponential backoff for rate limits
1523
+ - Handle 409 conflicts for concurrent updates
1524
+ - Log request IDs for troubleshooting
1525
+ - Validate data before inserting