industrial-model 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +177 -0
- package/dist/cognite-core/index.cjs +345 -20
- package/dist/cognite-core/index.cjs.map +1 -1
- package/dist/cognite-core/index.d.cts +2 -1
- package/dist/cognite-core/index.d.ts +2 -1
- package/dist/cognite-core/index.js +345 -20
- package/dist/cognite-core/index.js.map +1 -1
- package/dist/index.cjs +342 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -3
- package/dist/index.d.ts +8 -3
- package/dist/index.js +342 -20
- package/dist/index.js.map +1 -1
- package/dist/{types-2jjbs2i7.d.cts → types-BrD2jPB-.d.cts} +95 -19
- package/dist/{types-2jjbs2i7.d.ts → types-BrD2jPB-.d.ts} +95 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,6 +13,8 @@ TypeScript SDK for querying [Cognite Flexible Data Models (FDM)](https://docs.co
|
|
|
13
13
|
- **Pagination support** - use cursors manually or fetch all root pages with `limit: -1`.
|
|
14
14
|
- **Aggregation support** - count, group, list distinct values, and aggregate numeric properties.
|
|
15
15
|
- **Mutation support** - upsert model-shaped node patches and delete nodes by identity.
|
|
16
|
+
- **Datapoints support** - read, write, and delete time series datapoints through model-friendly option objects.
|
|
17
|
+
- **Files support** - upload files and retrieve pre-signed download URLs, keyed to model node identities.
|
|
16
18
|
- **Runtime validation option** - parse query results with Zod schemas derived from Cognite view metadata.
|
|
17
19
|
- **CJS and ESM builds** - works in Node.js and common bundler setups.
|
|
18
20
|
|
|
@@ -627,6 +629,122 @@ await core.delete([{ space: "asset-space", externalId: "pump-1" }]);
|
|
|
627
629
|
|
|
628
630
|
Deletes are sent through Cognite apply. When more than 1000 nodes are provided, the SDK splits them into multiple Cognite calls.
|
|
629
631
|
|
|
632
|
+
## Datapoints
|
|
633
|
+
|
|
634
|
+
Use `model.datapoints` for Cognite time series data. The public API talks in terms of `timeSeries`, ranges, and datapoint batches; the Cognite SDK `items` and `instanceId` payload shape stays internal.
|
|
635
|
+
|
|
636
|
+
```ts
|
|
637
|
+
const { items } = await model.datapoints.retrieve({
|
|
638
|
+
timeSeries: [{ space: "ts-space", externalId: "temperature", targetUnit: "degC" }],
|
|
639
|
+
start: new Date("2024-01-01T00:00:00.000Z"),
|
|
640
|
+
end: new Date("2024-01-02T00:00:00.000Z"),
|
|
641
|
+
limit: 100,
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
items[0]?.timeSeries.externalId;
|
|
645
|
+
items[0]?.datapoints;
|
|
646
|
+
items[0]?.cursor; // next cursor, or null
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
Pass `limit: -1` to follow datapoint cursors and return all pages for each requested time series.
|
|
650
|
+
|
|
651
|
+
```ts
|
|
652
|
+
const history = await model.datapoints.retrieve({
|
|
653
|
+
timeSeries: [{ space: "ts-space", externalId: "temperature" }],
|
|
654
|
+
start: new Date("2024-01-01T00:00:00.000Z"),
|
|
655
|
+
limit: -1,
|
|
656
|
+
});
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
Read the latest datapoint before a given timestamp:
|
|
660
|
+
|
|
661
|
+
```ts
|
|
662
|
+
const latest = await model.datapoints.latest({
|
|
663
|
+
timeSeries: [{ space: "ts-space", externalId: "temperature" }],
|
|
664
|
+
ignoreUnknownIds: true,
|
|
665
|
+
});
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
Write datapoints by passing an array of insert items directly:
|
|
669
|
+
|
|
670
|
+
```ts
|
|
671
|
+
await model.datapoints.insert([
|
|
672
|
+
{
|
|
673
|
+
timeSeries: { space: "ts-space", externalId: "temperature" },
|
|
674
|
+
datapoints: [{ timestamp: new Date(), value: 42 }],
|
|
675
|
+
},
|
|
676
|
+
]);
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
Delete datapoints by passing an array of ranges directly:
|
|
680
|
+
|
|
681
|
+
```ts
|
|
682
|
+
await model.datapoints.delete([
|
|
683
|
+
{
|
|
684
|
+
timeSeries: { space: "ts-space", externalId: "temperature" },
|
|
685
|
+
start: new Date("2024-01-01T00:00:00.000Z"),
|
|
686
|
+
end: new Date("2024-01-02T00:00:00.000Z"),
|
|
687
|
+
},
|
|
688
|
+
]);
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
## Files
|
|
692
|
+
|
|
693
|
+
Use `model.files` to upload files to Cognite and retrieve pre-signed download URLs. Both operations use `space` and `externalId` node identities as keys; the Cognite `instanceId` payload shape stays internal.
|
|
694
|
+
|
|
695
|
+
Upload a file and optionally pass the binary content as a second argument to complete the upload in one call. When content is provided, Cognite uploads it inline and `uploaded` is `true` on the result.
|
|
696
|
+
|
|
697
|
+
```ts
|
|
698
|
+
const result = await model.files.upload(
|
|
699
|
+
{
|
|
700
|
+
space: "file-space",
|
|
701
|
+
externalId: "report-2024",
|
|
702
|
+
name: "annual-report.pdf",
|
|
703
|
+
mimeType: "application/pdf",
|
|
704
|
+
directory: "/reports",
|
|
705
|
+
source: "erp",
|
|
706
|
+
metadata: { department: "finance", year: "2024" },
|
|
707
|
+
},
|
|
708
|
+
pdfContent, // Buffer, Blob, ArrayBuffer, ReadableStream, …
|
|
709
|
+
);
|
|
710
|
+
|
|
711
|
+
result.space; // "file-space"
|
|
712
|
+
result.externalId; // "report-2024"
|
|
713
|
+
result.name; // "annual-report.pdf"
|
|
714
|
+
result.uploaded; // true — content was provided
|
|
715
|
+
result.createdTime; // Date
|
|
716
|
+
result.lastUpdatedTime; // Date
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
Omit the content argument to receive a pre-signed `uploadUrl` instead. Use it to push the file binary from the client side without routing it through your server:
|
|
720
|
+
|
|
721
|
+
```ts
|
|
722
|
+
const result = await model.files.upload({
|
|
723
|
+
space: "file-space",
|
|
724
|
+
externalId: "report-2024",
|
|
725
|
+
name: "annual-report.pdf",
|
|
726
|
+
mimeType: "application/pdf",
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
result.uploaded; // false — content not yet uploaded
|
|
730
|
+
result.uploadUrl; // "https://storage.example.com/…" — use to PUT the file
|
|
731
|
+
```
|
|
732
|
+
|
|
733
|
+
Retrieve pre-signed download URLs for one or more files by node identity:
|
|
734
|
+
|
|
735
|
+
```ts
|
|
736
|
+
const urls = await model.files.getDownloadUrls([
|
|
737
|
+
{ space: "file-space", externalId: "report-2024" },
|
|
738
|
+
{ space: "file-space", externalId: "manual-v3" },
|
|
739
|
+
]);
|
|
740
|
+
|
|
741
|
+
urls[0]?.downloadUrl; // pre-signed URL ready to use
|
|
742
|
+
urls[0]?.space;
|
|
743
|
+
urls[0]?.externalId;
|
|
744
|
+
```
|
|
745
|
+
|
|
746
|
+
The returned array preserves the input order. Passing an empty array returns `[]` without calling Cognite.
|
|
747
|
+
|
|
630
748
|
## Aggregation
|
|
631
749
|
|
|
632
750
|
Use `aggregate()` when you need grouped counts, distinct values, or numeric summaries without loading every instance.
|
|
@@ -826,6 +944,15 @@ Deletes are view-independent:
|
|
|
826
944
|
await core.delete([{ space: "asset-space", externalId: "pump-1" }]);
|
|
827
945
|
```
|
|
828
946
|
|
|
947
|
+
`core.datapoints` exposes the same executor API as `model.datapoints` on `IndustrialModelClient`:
|
|
948
|
+
|
|
949
|
+
```ts
|
|
950
|
+
const { items } = await core.datapoints.retrieve({
|
|
951
|
+
timeSeries: [{ space: "ts-space", externalId: "temperature" }],
|
|
952
|
+
limit: 100,
|
|
953
|
+
});
|
|
954
|
+
```
|
|
955
|
+
|
|
829
956
|
All Cognite Core view types are exported from `industrial-model` and can be imported directly for use with `IndustrialModelClient` if needed:
|
|
830
957
|
|
|
831
958
|
```ts
|
|
@@ -987,6 +1114,10 @@ Same as `model.upsert<TModel>()(options)` on `IndustrialModelClient`, with the v
|
|
|
987
1114
|
|
|
988
1115
|
Same as `model.delete(items)` on `IndustrialModelClient`. Deletes nodes by `space` and `externalId`; no view name is required.
|
|
989
1116
|
|
|
1117
|
+
### `core.datapoints`
|
|
1118
|
+
|
|
1119
|
+
Same as `model.datapoints` on `IndustrialModelClient`. All four methods — `retrieve`, `latest`, `insert`, and `delete` — are available without a view name.
|
|
1120
|
+
|
|
990
1121
|
### `new IndustrialModelClient(client, dataModelId, options?)`
|
|
991
1122
|
|
|
992
1123
|
| Parameter | Type | Description |
|
|
@@ -1093,6 +1224,50 @@ Provide at least one of `groupBy` or `aggregate`. Omit `aggregate` to fetch dist
|
|
|
1093
1224
|
| `max` | `{ max: "volume" }` | Maximum numeric value. |
|
|
1094
1225
|
| `sum` | `{ sum: "volume" }` | Sum of a numeric property. |
|
|
1095
1226
|
|
|
1227
|
+
### `model.files.upload(fileInfo, content?)`
|
|
1228
|
+
|
|
1229
|
+
Uploads a file to Cognite. `fileInfo` fields:
|
|
1230
|
+
|
|
1231
|
+
| Field | Type | Description |
|
|
1232
|
+
| --- | --- | --- |
|
|
1233
|
+
| `space` | `string` | Node space. |
|
|
1234
|
+
| `externalId` | `string` | Node external ID. |
|
|
1235
|
+
| `name` | `string` | File name. |
|
|
1236
|
+
| `mimeType` | `string` | Optional MIME type. |
|
|
1237
|
+
| `directory` | `string` | Optional directory path within the project. |
|
|
1238
|
+
| `source` | `string` | Optional source system identifier. |
|
|
1239
|
+
| `metadata` | `Record<string, string>` | Optional key-value metadata. |
|
|
1240
|
+
|
|
1241
|
+
`content` accepts any value accepted by the Cognite SDK file upload (`Buffer`, `Blob`, `ArrayBuffer`, `ReadableStream`, …). When provided, the file is uploaded inline and `uploaded` is `true`. When omitted, Cognite returns a pre-signed `uploadUrl` for a separate upload and `uploaded` is `false`.
|
|
1242
|
+
|
|
1243
|
+
Returns `FileUploadResult`:
|
|
1244
|
+
|
|
1245
|
+
```ts
|
|
1246
|
+
type FileUploadResult = NodeId & {
|
|
1247
|
+
name: string;
|
|
1248
|
+
uploaded: boolean;
|
|
1249
|
+
mimeType?: string;
|
|
1250
|
+
directory?: string;
|
|
1251
|
+
source?: string;
|
|
1252
|
+
uploadedTime?: Date;
|
|
1253
|
+
createdTime: Date;
|
|
1254
|
+
lastUpdatedTime: Date;
|
|
1255
|
+
uploadUrl?: string;
|
|
1256
|
+
};
|
|
1257
|
+
```
|
|
1258
|
+
|
|
1259
|
+
### `model.files.getDownloadUrls(nodeIds)`
|
|
1260
|
+
|
|
1261
|
+
Retrieves one pre-signed download URL per node, in the same order as the input. Passing an empty array returns `[]` without calling Cognite.
|
|
1262
|
+
|
|
1263
|
+
Returns `FileDownloadUrl[]`:
|
|
1264
|
+
|
|
1265
|
+
```ts
|
|
1266
|
+
type FileDownloadUrl = NodeId & {
|
|
1267
|
+
downloadUrl: string;
|
|
1268
|
+
};
|
|
1269
|
+
```
|
|
1270
|
+
|
|
1096
1271
|
### Filter Operators
|
|
1097
1272
|
|
|
1098
1273
|
| Field type | Operators |
|
|
@@ -1132,6 +1307,8 @@ Logical combinators `AND`, `OR`, and `NOT` are supported at any nesting level, i
|
|
|
1132
1307
|
| `UpsertResult`, `UpsertResultItem` | Upsert output types. |
|
|
1133
1308
|
| `DeleteExecutor`, `DeleteResult`, `DeleteResultItem` | Delete helper and output types. |
|
|
1134
1309
|
| `EdgeCreationContext`, `EdgeCreationCallback`, `EdgeCreationCallbacks`, `EdgeMode` | Edge upsert helper types. |
|
|
1310
|
+
| `DatapointsExecutor`, `DatapointsRetrieveOptions`, `DatapointsLatestOptions`, `DatapointsLatestSeries`, `DatapointsInsertItem`, `DatapointsDeleteRange`, `DatapointsResult`, `DatapointSeriesResult`, `DatapointAggregate` | Datapoints types. |
|
|
1311
|
+
| `FilesExecutor`, `FileUploadInfo`, `FileUploadResult`, `FileDownloadUrl` | Files types. |
|
|
1135
1312
|
| `IndustrialModelClientOptions` | Client configuration options. |
|
|
1136
1313
|
|
|
1137
1314
|
**Cognite Core**
|
|
@@ -50,7 +50,92 @@ var CogniteSdkAdapter = class {
|
|
|
50
50
|
items: response.items
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
+
async retrieveDatapoints(options) {
|
|
54
|
+
const { items, ...rest } = options;
|
|
55
|
+
const sdkItems = items.map(({ space, externalId, ...itemRest }) => ({
|
|
56
|
+
...itemRest,
|
|
57
|
+
instanceId: { space, externalId }
|
|
58
|
+
}));
|
|
59
|
+
const response = await this.client.datapoints.retrieve({
|
|
60
|
+
...rest,
|
|
61
|
+
items: sdkItems
|
|
62
|
+
});
|
|
63
|
+
return { items: response.map(mapDatapointResult) };
|
|
64
|
+
}
|
|
65
|
+
async retrieveLatestDatapoints(items, options) {
|
|
66
|
+
const sdkItems = items.map(({ space, externalId, before }) => ({
|
|
67
|
+
instanceId: { space, externalId },
|
|
68
|
+
...before !== void 0 ? { before } : {}
|
|
69
|
+
}));
|
|
70
|
+
const response = await this.client.datapoints.retrieveLatest(
|
|
71
|
+
sdkItems,
|
|
72
|
+
options
|
|
73
|
+
);
|
|
74
|
+
return { items: response.map(mapDatapointResult) };
|
|
75
|
+
}
|
|
76
|
+
async insertDatapoints(items) {
|
|
77
|
+
const sdkItems = items.map(({ space, externalId, datapoints }) => ({
|
|
78
|
+
instanceId: { space, externalId },
|
|
79
|
+
datapoints
|
|
80
|
+
}));
|
|
81
|
+
await this.client.datapoints.insert(
|
|
82
|
+
sdkItems
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
async deleteDatapoints(items) {
|
|
86
|
+
const sdkItems = items.map(({ space, externalId, inclusiveBegin, exclusiveEnd }) => ({
|
|
87
|
+
instanceId: { space, externalId },
|
|
88
|
+
inclusiveBegin,
|
|
89
|
+
...exclusiveEnd !== void 0 ? { exclusiveEnd } : {}
|
|
90
|
+
}));
|
|
91
|
+
await this.client.datapoints.delete(
|
|
92
|
+
sdkItems
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
async uploadFile(fileInfo, content) {
|
|
96
|
+
const { instanceId, ...rest } = fileInfo;
|
|
97
|
+
const response = await this.client.files.upload(
|
|
98
|
+
{ ...rest, instanceId },
|
|
99
|
+
content,
|
|
100
|
+
false,
|
|
101
|
+
content !== void 0
|
|
102
|
+
);
|
|
103
|
+
return mapFileResult(response);
|
|
104
|
+
}
|
|
105
|
+
async getFileDownloadUrls(ids) {
|
|
106
|
+
const response = await this.client.files.getDownloadUrls(
|
|
107
|
+
ids
|
|
108
|
+
);
|
|
109
|
+
return response.map((item) => ({
|
|
110
|
+
...item.instanceId !== void 0 ? { instanceId: item.instanceId } : {},
|
|
111
|
+
downloadUrl: item.downloadUrl
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
53
114
|
};
|
|
115
|
+
function mapFileResult(item) {
|
|
116
|
+
return {
|
|
117
|
+
...item.instanceId !== void 0 ? { instanceId: item.instanceId } : {},
|
|
118
|
+
name: item.name,
|
|
119
|
+
uploaded: item.uploaded,
|
|
120
|
+
createdTime: item.createdTime,
|
|
121
|
+
lastUpdatedTime: item.lastUpdatedTime,
|
|
122
|
+
...item.uploadedTime !== void 0 ? { uploadedTime: item.uploadedTime } : {},
|
|
123
|
+
...item.mimeType !== void 0 ? { mimeType: item.mimeType } : {},
|
|
124
|
+
...item.directory !== void 0 ? { directory: item.directory } : {},
|
|
125
|
+
...item.source !== void 0 ? { source: item.source } : {},
|
|
126
|
+
...item.uploadUrl !== void 0 ? { uploadUrl: item.uploadUrl } : {}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function mapDatapointResult(item) {
|
|
130
|
+
return {
|
|
131
|
+
...item.instanceId?.space !== void 0 ? { space: item.instanceId.space } : {},
|
|
132
|
+
...item.instanceId?.externalId !== void 0 ? { externalId: item.instanceId.externalId } : {},
|
|
133
|
+
isString: item.isString ?? false,
|
|
134
|
+
...item.unit !== void 0 ? { unit: item.unit } : {},
|
|
135
|
+
datapoints: item.datapoints ?? [],
|
|
136
|
+
...item.nextCursor !== void 0 ? { nextCursor: item.nextCursor } : {}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
54
139
|
|
|
55
140
|
// src/constants.ts
|
|
56
141
|
var NESTED_SEP = "|";
|
|
@@ -61,6 +146,15 @@ var MAX_DEPENDENCY_DEPTH = 3;
|
|
|
61
146
|
var AGGREGATE_LIMIT = 1e3;
|
|
62
147
|
var MAX_GROUP_BY = 5;
|
|
63
148
|
|
|
149
|
+
// src/utils/array.ts
|
|
150
|
+
function chunks(items, size) {
|
|
151
|
+
const result = [];
|
|
152
|
+
for (let index = 0; index < items.length; index += size) {
|
|
153
|
+
result.push(items.slice(index, index + size));
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
|
|
64
158
|
// src/utils/query.ts
|
|
65
159
|
function mapNodesAndEdges(queryResult, _query) {
|
|
66
160
|
return queryResult.items;
|
|
@@ -717,6 +811,63 @@ ${errors.map((error) => `- ${error}`).join("\n")}`
|
|
|
717
811
|
return [];
|
|
718
812
|
}
|
|
719
813
|
};
|
|
814
|
+
var dateSchema2 = zod.z.date();
|
|
815
|
+
var nodeIdSchema2 = zod.z.object({ space: zod.z.string(), externalId: zod.z.string() }).loose();
|
|
816
|
+
var retrieveOptionsSchema = zod.z.object({
|
|
817
|
+
timeSeries: zod.z.array(nodeIdSchema2),
|
|
818
|
+
start: dateSchema2.optional(),
|
|
819
|
+
end: dateSchema2.optional()
|
|
820
|
+
}).loose();
|
|
821
|
+
var deleteRangeSchema = zod.z.object({
|
|
822
|
+
timeSeries: zod.z.object({ space: zod.z.string(), externalId: zod.z.string() }).loose(),
|
|
823
|
+
start: dateSchema2,
|
|
824
|
+
end: dateSchema2.optional()
|
|
825
|
+
}).loose();
|
|
826
|
+
function formatIssues(error, prefix) {
|
|
827
|
+
return error.issues.map((issue) => {
|
|
828
|
+
const parts = prefix ? [prefix, ...issue.path] : [...issue.path];
|
|
829
|
+
return `${parts.map(String).join(".")}: ${issue.message}`;
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
var DatapointsValidator = class {
|
|
833
|
+
validateRetrieve(options) {
|
|
834
|
+
const result = retrieveOptionsSchema.safeParse(options);
|
|
835
|
+
if (!result.success) {
|
|
836
|
+
const messages = formatIssues(result.error);
|
|
837
|
+
throw new Error(`Invalid datapoints options:
|
|
838
|
+
- ${messages.join("\n- ")}`);
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
validateDelete(ranges) {
|
|
842
|
+
const result = zod.z.array(deleteRangeSchema).safeParse(ranges);
|
|
843
|
+
if (!result.success) {
|
|
844
|
+
const messages = formatIssues(result.error, "ranges");
|
|
845
|
+
throw new Error(`Invalid datapoints options:
|
|
846
|
+
- ${messages.join("\n- ")}`);
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
};
|
|
850
|
+
var nodeIdSchema3 = zod.z.object({
|
|
851
|
+
space: zod.z.string().min(1),
|
|
852
|
+
externalId: zod.z.string().min(1)
|
|
853
|
+
}).loose();
|
|
854
|
+
var deleteItemsSchema = zod.z.array(nodeIdSchema3);
|
|
855
|
+
function formatIssues2(error, prefix) {
|
|
856
|
+
return error.issues.map((issue) => {
|
|
857
|
+
const parts = [prefix, ...issue.path];
|
|
858
|
+
return `${parts.map(String).join(".")}: ${issue.message}`;
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
var DeleteValidator = class {
|
|
862
|
+
validateItems(items) {
|
|
863
|
+
const result = deleteItemsSchema.safeParse(items);
|
|
864
|
+
if (!result.success) {
|
|
865
|
+
const messages = formatIssues2(result.error, "items");
|
|
866
|
+
throw new Error(`Invalid delete options:
|
|
867
|
+
- ${messages.join("\n- ")}`);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
};
|
|
720
871
|
var nodeMetadataSchema = {
|
|
721
872
|
instanceType: zod.z.literal("node").optional(),
|
|
722
873
|
space: zod.z.string(),
|
|
@@ -1120,6 +1271,178 @@ var AggregateResultMapper = class {
|
|
|
1120
1271
|
}
|
|
1121
1272
|
};
|
|
1122
1273
|
|
|
1274
|
+
// src/mappers/datapoints-mapper.ts
|
|
1275
|
+
var CHUNK_SIZE = 100;
|
|
1276
|
+
var DatapointsMapper = class {
|
|
1277
|
+
constructor(cognite) {
|
|
1278
|
+
this.cognite = cognite;
|
|
1279
|
+
this.validator = new DatapointsValidator();
|
|
1280
|
+
}
|
|
1281
|
+
async retrieve(options) {
|
|
1282
|
+
this.validator.validateRetrieve(options);
|
|
1283
|
+
const cogniteOptions = this.toCogniteOptions(options);
|
|
1284
|
+
const allPages = options.limit === -1;
|
|
1285
|
+
if (!allPages) {
|
|
1286
|
+
const result = await this.cognite.retrieveDatapoints(cogniteOptions);
|
|
1287
|
+
return this.mapResult(result.items, cogniteOptions.items, options.aggregate);
|
|
1288
|
+
}
|
|
1289
|
+
const accumulated = /* @__PURE__ */ new Map();
|
|
1290
|
+
const itemByKey = new Map(cogniteOptions.items.map((item) => [this.toKey(item), item]));
|
|
1291
|
+
let currentItems = cogniteOptions.items;
|
|
1292
|
+
while (currentItems.length > 0) {
|
|
1293
|
+
const result = await this.cognite.retrieveDatapoints({
|
|
1294
|
+
...cogniteOptions,
|
|
1295
|
+
items: currentItems
|
|
1296
|
+
});
|
|
1297
|
+
const nextItems = [];
|
|
1298
|
+
for (const resultItem of result.items) {
|
|
1299
|
+
const key = this.toKey(resultItem);
|
|
1300
|
+
let acc = accumulated.get(key);
|
|
1301
|
+
if (!acc) {
|
|
1302
|
+
acc = { ...resultItem, datapoints: [] };
|
|
1303
|
+
accumulated.set(key, acc);
|
|
1304
|
+
}
|
|
1305
|
+
acc.datapoints.push(...resultItem.datapoints);
|
|
1306
|
+
if (resultItem.nextCursor) {
|
|
1307
|
+
acc.nextCursor = resultItem.nextCursor;
|
|
1308
|
+
} else {
|
|
1309
|
+
delete acc.nextCursor;
|
|
1310
|
+
}
|
|
1311
|
+
if (resultItem.nextCursor) {
|
|
1312
|
+
const original = itemByKey.get(key);
|
|
1313
|
+
nextItems.push({
|
|
1314
|
+
...original,
|
|
1315
|
+
space: resultItem.space ?? original?.space ?? "",
|
|
1316
|
+
externalId: resultItem.externalId ?? original?.externalId ?? "",
|
|
1317
|
+
cursor: resultItem.nextCursor
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
currentItems = nextItems;
|
|
1322
|
+
}
|
|
1323
|
+
return this.mapResult(
|
|
1324
|
+
Array.from(accumulated.values()),
|
|
1325
|
+
cogniteOptions.items,
|
|
1326
|
+
options.aggregate
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
async retrieveLatest(options) {
|
|
1330
|
+
const items = options.timeSeries.map(
|
|
1331
|
+
({ space, externalId, before }) => ({
|
|
1332
|
+
space,
|
|
1333
|
+
externalId,
|
|
1334
|
+
...before !== void 0 ? { before } : {}
|
|
1335
|
+
})
|
|
1336
|
+
);
|
|
1337
|
+
const latestOptions = options.ignoreUnknownIds !== void 0 ? { ignoreUnknownIds: options.ignoreUnknownIds } : void 0;
|
|
1338
|
+
const result = await this.cognite.retrieveLatestDatapoints(items, latestOptions);
|
|
1339
|
+
return this.mapResult(result.items, items);
|
|
1340
|
+
}
|
|
1341
|
+
async insert(items) {
|
|
1342
|
+
const cogniteItems = items.map(({ timeSeries, datapoints }) => ({
|
|
1343
|
+
space: timeSeries.space,
|
|
1344
|
+
externalId: timeSeries.externalId,
|
|
1345
|
+
datapoints
|
|
1346
|
+
}));
|
|
1347
|
+
for (const chunk of chunks(cogniteItems, CHUNK_SIZE)) {
|
|
1348
|
+
await this.cognite.insertDatapoints(chunk);
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
async delete(ranges) {
|
|
1352
|
+
this.validator.validateDelete(ranges);
|
|
1353
|
+
const cogniteItems = ranges.map(({ timeSeries, start, end }) => ({
|
|
1354
|
+
space: timeSeries.space,
|
|
1355
|
+
externalId: timeSeries.externalId,
|
|
1356
|
+
inclusiveBegin: start,
|
|
1357
|
+
...end !== void 0 ? { exclusiveEnd: end } : {}
|
|
1358
|
+
}));
|
|
1359
|
+
for (const chunk of chunks(cogniteItems, CHUNK_SIZE)) {
|
|
1360
|
+
await this.cognite.deleteDatapoints(chunk);
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
toKey(item) {
|
|
1364
|
+
return `${item.space ?? ""}:${item.externalId ?? ""}`;
|
|
1365
|
+
}
|
|
1366
|
+
toCogniteOptions(options) {
|
|
1367
|
+
const { timeSeries, aggregate, ...rest } = options;
|
|
1368
|
+
return {
|
|
1369
|
+
...rest,
|
|
1370
|
+
...aggregate !== void 0 ? { aggregates: [aggregate] } : {},
|
|
1371
|
+
items: timeSeries.map(({ space, externalId }) => ({ space, externalId }))
|
|
1372
|
+
};
|
|
1373
|
+
}
|
|
1374
|
+
mapResult(items, requestedItems, aggregate) {
|
|
1375
|
+
const requestedByKey = new Map(requestedItems.map((item) => [this.toKey(item), item]));
|
|
1376
|
+
const mappedItems = items.filter((item) => !item.isString).map((item) => {
|
|
1377
|
+
const requested = requestedByKey.get(this.toKey(item));
|
|
1378
|
+
const datapoints = aggregate !== void 0 ? item.datapoints.map((dp) => ({
|
|
1379
|
+
timestamp: dp.timestamp,
|
|
1380
|
+
value: dp[aggregate] ?? 0
|
|
1381
|
+
})) : item.datapoints;
|
|
1382
|
+
return {
|
|
1383
|
+
timeSeries: {
|
|
1384
|
+
space: item.space ?? requested?.space ?? "",
|
|
1385
|
+
externalId: item.externalId ?? requested?.externalId ?? ""
|
|
1386
|
+
},
|
|
1387
|
+
...item.unit !== void 0 ? { unit: item.unit } : {},
|
|
1388
|
+
datapoints,
|
|
1389
|
+
cursor: item.nextCursor ?? null
|
|
1390
|
+
};
|
|
1391
|
+
});
|
|
1392
|
+
return { items: mappedItems };
|
|
1393
|
+
}
|
|
1394
|
+
};
|
|
1395
|
+
|
|
1396
|
+
// src/mappers/files-mapper.ts
|
|
1397
|
+
var FilesMapper = class {
|
|
1398
|
+
constructor(cognite) {
|
|
1399
|
+
this.cognite = cognite;
|
|
1400
|
+
}
|
|
1401
|
+
async upload(fileInfo, content) {
|
|
1402
|
+
const { space, externalId, ...rest } = fileInfo;
|
|
1403
|
+
const result = await this.cognite.uploadFile(
|
|
1404
|
+
{ instanceId: { space, externalId }, ...rest },
|
|
1405
|
+
content
|
|
1406
|
+
);
|
|
1407
|
+
return this.mapUploadResult(result, { space, externalId });
|
|
1408
|
+
}
|
|
1409
|
+
async getDownloadUrls(nodeIds) {
|
|
1410
|
+
if (nodeIds.length === 0) return [];
|
|
1411
|
+
const ids = nodeIds.map(({ space, externalId }) => ({ instanceId: { space, externalId } }));
|
|
1412
|
+
const result = await this.cognite.getFileDownloadUrls(ids);
|
|
1413
|
+
return result.map(
|
|
1414
|
+
(item, i) => this.mapDownloadUrl(item, nodeIds[i] ?? { space: "", externalId: "" })
|
|
1415
|
+
);
|
|
1416
|
+
}
|
|
1417
|
+
toNodeId(item, fallback) {
|
|
1418
|
+
return {
|
|
1419
|
+
space: item.instanceId?.space ?? fallback.space,
|
|
1420
|
+
externalId: item.instanceId?.externalId ?? fallback.externalId
|
|
1421
|
+
};
|
|
1422
|
+
}
|
|
1423
|
+
mapUploadResult(item, fallback) {
|
|
1424
|
+
const nodeId = this.toNodeId(item, fallback);
|
|
1425
|
+
return {
|
|
1426
|
+
...nodeId,
|
|
1427
|
+
name: item.name,
|
|
1428
|
+
uploaded: item.uploaded,
|
|
1429
|
+
createdTime: item.createdTime,
|
|
1430
|
+
lastUpdatedTime: item.lastUpdatedTime,
|
|
1431
|
+
...item.uploadedTime !== void 0 ? { uploadedTime: item.uploadedTime } : {},
|
|
1432
|
+
...item.mimeType !== void 0 ? { mimeType: item.mimeType } : {},
|
|
1433
|
+
...item.directory !== void 0 ? { directory: item.directory } : {},
|
|
1434
|
+
...item.source !== void 0 ? { source: item.source } : {},
|
|
1435
|
+
...item.uploadUrl !== void 0 ? { uploadUrl: item.uploadUrl } : {}
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
mapDownloadUrl(item, fallback) {
|
|
1439
|
+
return {
|
|
1440
|
+
...this.toNodeId(item, fallback),
|
|
1441
|
+
downloadUrl: item.downloadUrl
|
|
1442
|
+
};
|
|
1443
|
+
}
|
|
1444
|
+
};
|
|
1445
|
+
|
|
1123
1446
|
// src/mappers/sort-mapper.ts
|
|
1124
1447
|
var SortMapper = class {
|
|
1125
1448
|
map(sort, rootView) {
|
|
@@ -1709,6 +2032,17 @@ var ViewMapper = class {
|
|
|
1709
2032
|
var APPLY_ITEM_LIMIT = 1e3;
|
|
1710
2033
|
var IndustrialModelClient = class {
|
|
1711
2034
|
constructor(client, dataModelId, options = {}) {
|
|
2035
|
+
this.deleteValidator = new DeleteValidator();
|
|
2036
|
+
this.files = {
|
|
2037
|
+
upload: (fileInfo, content) => this.filesMapper.upload(fileInfo, content),
|
|
2038
|
+
getDownloadUrls: (nodeIds) => this.filesMapper.getDownloadUrls(nodeIds)
|
|
2039
|
+
};
|
|
2040
|
+
this.datapoints = {
|
|
2041
|
+
retrieve: (options) => this.datapointsMapper.retrieve(options),
|
|
2042
|
+
latest: (options) => this.datapointsMapper.retrieveLatest(options),
|
|
2043
|
+
insert: (items) => this.datapointsMapper.insert(items),
|
|
2044
|
+
delete: (ranges) => this.datapointsMapper.delete(ranges)
|
|
2045
|
+
};
|
|
1712
2046
|
const cognite = createCogniteAdapter(client);
|
|
1713
2047
|
this.cognite = cognite;
|
|
1714
2048
|
const viewMapper = new ViewMapper(cognite, dataModelId);
|
|
@@ -1717,6 +2051,8 @@ var IndustrialModelClient = class {
|
|
|
1717
2051
|
this.upsertMapper = new UpsertMapper(viewMapper, cognite);
|
|
1718
2052
|
this.aggregateResultMapper = new AggregateResultMapper();
|
|
1719
2053
|
this.resultMapper = new QueryResultMapper(viewMapper);
|
|
2054
|
+
this.datapointsMapper = new DatapointsMapper(cognite);
|
|
2055
|
+
this.filesMapper = new FilesMapper(cognite);
|
|
1720
2056
|
this.resultValidator = new QueryResultValidator(viewMapper);
|
|
1721
2057
|
this.validateResults = options.validateResults ?? false;
|
|
1722
2058
|
}
|
|
@@ -1733,14 +2069,12 @@ var IndustrialModelClient = class {
|
|
|
1733
2069
|
return execute;
|
|
1734
2070
|
}
|
|
1735
2071
|
async delete(items) {
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
};
|
|
1743
|
-
});
|
|
2072
|
+
this.deleteValidator.validateItems(items);
|
|
2073
|
+
const deleteItems = items.map((item) => ({
|
|
2074
|
+
instanceType: "node",
|
|
2075
|
+
space: item.space,
|
|
2076
|
+
externalId: item.externalId
|
|
2077
|
+
}));
|
|
1744
2078
|
const response = await this.applyInstancesInChunks({
|
|
1745
2079
|
items: [],
|
|
1746
2080
|
delete: deleteItems
|
|
@@ -1832,18 +2166,6 @@ var IndustrialModelClient = class {
|
|
|
1832
2166
|
return appendNodesAndEdges(result, nestedResults);
|
|
1833
2167
|
}
|
|
1834
2168
|
};
|
|
1835
|
-
function chunks(items, size) {
|
|
1836
|
-
const result = [];
|
|
1837
|
-
for (let index = 0; index < items.length; index += size) {
|
|
1838
|
-
result.push(items.slice(index, index + size));
|
|
1839
|
-
}
|
|
1840
|
-
return result;
|
|
1841
|
-
}
|
|
1842
|
-
function assertNodeId2(value) {
|
|
1843
|
-
if (value == null || typeof value !== "object" || Array.isArray(value) || typeof value.space !== "string" || value.space?.length === 0 || typeof value.externalId !== "string" || value.externalId?.length === 0) {
|
|
1844
|
-
throw new Error("Invalid delete options:\n- items: expected NodeId values");
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1847
2169
|
|
|
1848
2170
|
// src/cognite-core/client.ts
|
|
1849
2171
|
var COGNITE_CORE_DATA_MODEL = {
|
|
@@ -1874,6 +2196,9 @@ var CogniteCoreClient = class {
|
|
|
1874
2196
|
delete(items) {
|
|
1875
2197
|
return this.model.delete(items);
|
|
1876
2198
|
}
|
|
2199
|
+
get datapoints() {
|
|
2200
|
+
return this.model.datapoints;
|
|
2201
|
+
}
|
|
1877
2202
|
};
|
|
1878
2203
|
|
|
1879
2204
|
exports.COGNITE_CORE_DATA_MODEL = COGNITE_CORE_DATA_MODEL;
|