industrial-model 0.6.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 +372 -1
- package/dist/cognite-core/index.cjs +691 -0
- package/dist/cognite-core/index.cjs.map +1 -1
- package/dist/cognite-core/index.d.cts +6 -2
- package/dist/cognite-core/index.d.ts +6 -2
- package/dist/cognite-core/index.js +691 -0
- package/dist/cognite-core/index.js.map +1 -1
- package/dist/index.cjs +680 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -3
- package/dist/index.d.ts +13 -3
- package/dist/index.js +680 -0
- package/dist/index.js.map +1 -1
- package/dist/{types-DCP5GMi3.d.cts → types-BrD2jPB-.d.cts} +138 -11
- package/dist/{types-DCP5GMi3.d.ts → types-BrD2jPB-.d.ts} +138 -11
- package/package.json +1 -1
|
@@ -43,7 +43,99 @@ var CogniteSdkAdapter = class {
|
|
|
43
43
|
items: response.items
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
+
async applyInstances(request) {
|
|
47
|
+
const apply = this.client.instances.apply;
|
|
48
|
+
const response = await apply(request);
|
|
49
|
+
return {
|
|
50
|
+
items: response.items
|
|
51
|
+
};
|
|
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
|
+
}
|
|
46
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
|
+
}
|
|
47
139
|
|
|
48
140
|
// src/constants.ts
|
|
49
141
|
var NESTED_SEP = "|";
|
|
@@ -54,6 +146,15 @@ var MAX_DEPENDENCY_DEPTH = 3;
|
|
|
54
146
|
var AGGREGATE_LIMIT = 1e3;
|
|
55
147
|
var MAX_GROUP_BY = 5;
|
|
56
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
|
+
|
|
57
158
|
// src/utils/query.ts
|
|
58
159
|
function mapNodesAndEdges(queryResult, _query) {
|
|
59
160
|
return queryResult.items;
|
|
@@ -710,6 +811,63 @@ ${errors.map((error) => `- ${error}`).join("\n")}`
|
|
|
710
811
|
return [];
|
|
711
812
|
}
|
|
712
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
|
+
};
|
|
713
871
|
var nodeMetadataSchema = {
|
|
714
872
|
instanceType: zod.z.literal("node").optional(),
|
|
715
873
|
space: zod.z.string(),
|
|
@@ -796,6 +954,85 @@ ${result.error.issues.map((issue) => `- ${issue.path.map(String).join(".")}: ${i
|
|
|
796
954
|
return (isList ? zod.z.array(nestedSchema) : nestedSchema).optional();
|
|
797
955
|
}
|
|
798
956
|
};
|
|
957
|
+
var strictNodeIdSchema = zod.z.object({
|
|
958
|
+
space: zod.z.string().min(1),
|
|
959
|
+
externalId: zod.z.string().min(1)
|
|
960
|
+
}).strict();
|
|
961
|
+
var nodeIdLikeSchema = zod.z.object({
|
|
962
|
+
space: zod.z.string().min(1),
|
|
963
|
+
externalId: zod.z.string().min(1)
|
|
964
|
+
}).loose();
|
|
965
|
+
var optionsSchema = zod.z.object({
|
|
966
|
+
viewExternalId: zod.z.string().min(1),
|
|
967
|
+
items: zod.z.array(zod.z.record(zod.z.string(), zod.z.unknown())),
|
|
968
|
+
onEdgeCreation: zod.z.record(zod.z.string(), zod.z.function()).optional(),
|
|
969
|
+
replace: zod.z.boolean().optional(),
|
|
970
|
+
edgeMode: zod.z.enum(["append", "replace"]).optional()
|
|
971
|
+
}).strict();
|
|
972
|
+
function issuePath3(path) {
|
|
973
|
+
return path.length === 0 ? "upsert" : path.map(String).join(".");
|
|
974
|
+
}
|
|
975
|
+
function formatZodIssues3(error, path) {
|
|
976
|
+
return error.issues.map((issue) => `${issuePath3([...path, ...issue.path])}: ${issue.message}`);
|
|
977
|
+
}
|
|
978
|
+
function relationValueSchema(property) {
|
|
979
|
+
if (isReverseDirectRelation(property) && property.targetsList === true) {
|
|
980
|
+
return zod.z.never();
|
|
981
|
+
}
|
|
982
|
+
return zod.z.union([nodeIdLikeSchema, zod.z.array(nodeIdLikeSchema)]);
|
|
983
|
+
}
|
|
984
|
+
var UpsertValidator = class {
|
|
985
|
+
validate(options, rootView) {
|
|
986
|
+
const errors = [];
|
|
987
|
+
const optionsResult = optionsSchema.safeParse(options);
|
|
988
|
+
if (!optionsResult.success) {
|
|
989
|
+
errors.push(...formatZodIssues3(optionsResult.error, []));
|
|
990
|
+
}
|
|
991
|
+
if (options.viewExternalId !== rootView.externalId) {
|
|
992
|
+
errors.push(
|
|
993
|
+
`viewExternalId: expected "${rootView.externalId}", received "${options.viewExternalId}"`
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
for (const [index, item] of options.items.entries()) {
|
|
997
|
+
errors.push(
|
|
998
|
+
...this.validateItem(item, rootView, ["items", index])
|
|
999
|
+
);
|
|
1000
|
+
}
|
|
1001
|
+
if (errors.length > 0) {
|
|
1002
|
+
throw new Error(`Invalid upsert options:
|
|
1003
|
+
${errors.map((error) => `- ${error}`).join("\n")}`);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
validateItem(item, view, path) {
|
|
1007
|
+
const errors = [];
|
|
1008
|
+
const identityResult = strictNodeIdSchema.safeParse({
|
|
1009
|
+
space: item.space,
|
|
1010
|
+
externalId: item.externalId
|
|
1011
|
+
});
|
|
1012
|
+
if (!identityResult.success) {
|
|
1013
|
+
errors.push(...formatZodIssues3(identityResult.error, path));
|
|
1014
|
+
}
|
|
1015
|
+
for (const [name, value] of Object.entries(item)) {
|
|
1016
|
+
if (name === "space" || name === "externalId") continue;
|
|
1017
|
+
const property = view.properties[name];
|
|
1018
|
+
if (!property) {
|
|
1019
|
+
errors.push(`${issuePath3([...path, name])}: unknown view property`);
|
|
1020
|
+
continue;
|
|
1021
|
+
}
|
|
1022
|
+
if (isViewPropertyDefinition(property)) {
|
|
1023
|
+
const schema = property.type.type === "direct" ? property.type.list === true ? zod.z.array(nodeIdLikeSchema) : nodeIdLikeSchema : propertyValueSchema(property);
|
|
1024
|
+
const result = schema.safeParse(value);
|
|
1025
|
+
if (!result.success) errors.push(...formatZodIssues3(result.error, [...path, name]));
|
|
1026
|
+
continue;
|
|
1027
|
+
}
|
|
1028
|
+
if (isReverseDirectRelation(property) || isEdgeConnection(property)) {
|
|
1029
|
+
const result = relationValueSchema(property).safeParse(value);
|
|
1030
|
+
if (!result.success) errors.push(...formatZodIssues3(result.error, [...path, name]));
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
return errors;
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
799
1036
|
|
|
800
1037
|
// src/mappers/filter-mapper.ts
|
|
801
1038
|
var LEAF_OPS = /* @__PURE__ */ new Set([
|
|
@@ -1034,6 +1271,178 @@ var AggregateResultMapper = class {
|
|
|
1034
1271
|
}
|
|
1035
1272
|
};
|
|
1036
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
|
+
|
|
1037
1446
|
// src/mappers/sort-mapper.ts
|
|
1038
1447
|
var SortMapper = class {
|
|
1039
1448
|
map(sort, rootView) {
|
|
@@ -1363,6 +1772,216 @@ var QueryResultMapper = class {
|
|
|
1363
1772
|
}
|
|
1364
1773
|
};
|
|
1365
1774
|
|
|
1775
|
+
// src/mappers/upsert-mapper.ts
|
|
1776
|
+
var IDENTITY_KEYS = /* @__PURE__ */ new Set(["space", "externalId"]);
|
|
1777
|
+
var EDGE_QUERY_LIMIT = 1e3;
|
|
1778
|
+
var UpsertMapper = class {
|
|
1779
|
+
constructor(viewMapper, cognite) {
|
|
1780
|
+
this.viewMapper = viewMapper;
|
|
1781
|
+
this.cognite = cognite;
|
|
1782
|
+
this.validator = new UpsertValidator();
|
|
1783
|
+
}
|
|
1784
|
+
async map(options) {
|
|
1785
|
+
const rootView = await this.viewMapper.getView(options.viewExternalId);
|
|
1786
|
+
this.validator.validate(options, rootView);
|
|
1787
|
+
const edgeMode = options.edgeMode ?? "append";
|
|
1788
|
+
const mappedItems = options.items.map(
|
|
1789
|
+
(item) => this.mapItem(item, rootView, options.onEdgeCreation, edgeMode)
|
|
1790
|
+
);
|
|
1791
|
+
const items = mappedItems.flatMap((item) => item.writes);
|
|
1792
|
+
const edgeReplacements = mappedItems.flatMap((item) => item.edgeReplacements);
|
|
1793
|
+
const deleteItems = edgeMode === "replace" ? await this.mapEdgeReplacementDeletes(edgeReplacements) : [];
|
|
1794
|
+
return {
|
|
1795
|
+
items,
|
|
1796
|
+
...deleteItems.length > 0 ? { delete: deleteItems } : {},
|
|
1797
|
+
...options.replace === true ? { replace: true } : {}
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
mapItem(item, rootView, onEdgeCreation, edgeMode) {
|
|
1801
|
+
const node = { space: item.space, externalId: item.externalId };
|
|
1802
|
+
const nodeProperties = {};
|
|
1803
|
+
const inferredItems = [];
|
|
1804
|
+
const edgeReplacements = [];
|
|
1805
|
+
for (const [name, value] of Object.entries(item)) {
|
|
1806
|
+
if (IDENTITY_KEYS.has(name)) continue;
|
|
1807
|
+
const property = rootView.properties[name];
|
|
1808
|
+
if (!property) continue;
|
|
1809
|
+
if (isViewPropertyDefinition(property)) {
|
|
1810
|
+
nodeProperties[name] = normalizeViewPropertyValue(value, property);
|
|
1811
|
+
} else if (isReverseDirectRelation(property)) {
|
|
1812
|
+
inferredItems.push(...this.mapReverseDirectRelation(node, value, property));
|
|
1813
|
+
} else if (isEdgeConnection(property)) {
|
|
1814
|
+
const desiredEdges = this.mapEdgeConnection(node, name, value, property, onEdgeCreation);
|
|
1815
|
+
inferredItems.push(...desiredEdges);
|
|
1816
|
+
if (edgeMode === "replace") {
|
|
1817
|
+
edgeReplacements.push({ rootNode: node, propertyName: name, property, desiredEdges });
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
const applyNode = {
|
|
1822
|
+
instanceType: "node",
|
|
1823
|
+
...node
|
|
1824
|
+
};
|
|
1825
|
+
if (Object.keys(nodeProperties).length > 0) {
|
|
1826
|
+
applyNode.sources = [{ source: toViewReference(rootView), properties: nodeProperties }];
|
|
1827
|
+
}
|
|
1828
|
+
return { writes: [applyNode, ...inferredItems], edgeReplacements };
|
|
1829
|
+
}
|
|
1830
|
+
async mapEdgeReplacementDeletes(replacements) {
|
|
1831
|
+
const deletes = await Promise.all(
|
|
1832
|
+
replacements.map(async (replacement) => {
|
|
1833
|
+
const existingEdges = await this.queryExistingEdges(replacement);
|
|
1834
|
+
const desiredEdgeKeys = new Set(replacement.desiredEdges.map((edge) => instanceKey(edge)));
|
|
1835
|
+
return existingEdges.filter((edge) => !desiredEdgeKeys.has(instanceKey(edge))).map((edge) => ({
|
|
1836
|
+
instanceType: "edge",
|
|
1837
|
+
space: edge.space,
|
|
1838
|
+
externalId: edge.externalId
|
|
1839
|
+
}));
|
|
1840
|
+
})
|
|
1841
|
+
);
|
|
1842
|
+
return uniqueDeletes(deletes.flat());
|
|
1843
|
+
}
|
|
1844
|
+
async queryExistingEdges(replacement) {
|
|
1845
|
+
const rootKey = `${replacement.propertyName}Root`;
|
|
1846
|
+
const edgeKey = `${replacement.propertyName}Edges`;
|
|
1847
|
+
const direction = replacement.property.direction ?? "outwards";
|
|
1848
|
+
const query = {
|
|
1849
|
+
with: {
|
|
1850
|
+
[rootKey]: {
|
|
1851
|
+
nodes: {
|
|
1852
|
+
filter: {
|
|
1853
|
+
instanceReferences: [replacement.rootNode]
|
|
1854
|
+
}
|
|
1855
|
+
},
|
|
1856
|
+
limit: 1
|
|
1857
|
+
},
|
|
1858
|
+
[edgeKey]: {
|
|
1859
|
+
edges: {
|
|
1860
|
+
from: rootKey,
|
|
1861
|
+
maxDistance: 1,
|
|
1862
|
+
direction,
|
|
1863
|
+
filter: {
|
|
1864
|
+
equals: { property: ["edge", "type"], value: replacement.property.type }
|
|
1865
|
+
}
|
|
1866
|
+
},
|
|
1867
|
+
limit: EDGE_QUERY_LIMIT
|
|
1868
|
+
}
|
|
1869
|
+
},
|
|
1870
|
+
select: {
|
|
1871
|
+
[rootKey]: {},
|
|
1872
|
+
[edgeKey]: {}
|
|
1873
|
+
}
|
|
1874
|
+
};
|
|
1875
|
+
const edges = [];
|
|
1876
|
+
let cursor;
|
|
1877
|
+
do {
|
|
1878
|
+
const response = await this.cognite.queryInstances({
|
|
1879
|
+
...query,
|
|
1880
|
+
...cursor ? { cursors: { [edgeKey]: cursor } } : {}
|
|
1881
|
+
});
|
|
1882
|
+
edges.push(
|
|
1883
|
+
...(response.items[edgeKey] ?? []).filter(
|
|
1884
|
+
(item) => item.instanceType === "edge"
|
|
1885
|
+
)
|
|
1886
|
+
);
|
|
1887
|
+
cursor = response.nextCursor[edgeKey];
|
|
1888
|
+
} while (cursor);
|
|
1889
|
+
return edges;
|
|
1890
|
+
}
|
|
1891
|
+
mapReverseDirectRelation(node, value, property) {
|
|
1892
|
+
const targets = asNodeIdArray(value);
|
|
1893
|
+
return targets.map((target) => ({
|
|
1894
|
+
instanceType: "node",
|
|
1895
|
+
...target,
|
|
1896
|
+
sources: [
|
|
1897
|
+
{
|
|
1898
|
+
source: property.through.source,
|
|
1899
|
+
properties: {
|
|
1900
|
+
[property.through.identifier]: normalizeReverseDirectRelationValue(node, property)
|
|
1901
|
+
}
|
|
1902
|
+
}
|
|
1903
|
+
]
|
|
1904
|
+
}));
|
|
1905
|
+
}
|
|
1906
|
+
mapEdgeConnection(node, propertyName, value, property, onEdgeCreation) {
|
|
1907
|
+
const direction = property.direction ?? "outwards";
|
|
1908
|
+
return asNodeIdArray(value).map((target) => {
|
|
1909
|
+
const startNode = direction === "inwards" ? target : node;
|
|
1910
|
+
const endNode = direction === "inwards" ? node : target;
|
|
1911
|
+
const edgeType = toNodeId(property.type, `edge type for "${propertyName}"`);
|
|
1912
|
+
const createEdgeId = onEdgeCreation?.[propertyName];
|
|
1913
|
+
if (!createEdgeId) {
|
|
1914
|
+
throw new Error(
|
|
1915
|
+
`Invalid upsert options:
|
|
1916
|
+
- onEdgeCreation.${propertyName}: required when ingesting edge connection "${propertyName}"`
|
|
1917
|
+
);
|
|
1918
|
+
}
|
|
1919
|
+
const edgeId = createEdgeId({
|
|
1920
|
+
startNode,
|
|
1921
|
+
endNode,
|
|
1922
|
+
edgeType
|
|
1923
|
+
});
|
|
1924
|
+
assertNodeId(edgeId, `onEdgeCreation(${propertyName})`);
|
|
1925
|
+
return {
|
|
1926
|
+
instanceType: "edge",
|
|
1927
|
+
...edgeId,
|
|
1928
|
+
type: property.type,
|
|
1929
|
+
startNode,
|
|
1930
|
+
endNode
|
|
1931
|
+
};
|
|
1932
|
+
});
|
|
1933
|
+
}
|
|
1934
|
+
};
|
|
1935
|
+
function normalizeReverseDirectRelationValue(node, property) {
|
|
1936
|
+
return property.targetsList === true ? [node] : node;
|
|
1937
|
+
}
|
|
1938
|
+
function normalizeViewPropertyValue(value, property) {
|
|
1939
|
+
if (property.type.type !== "direct") return normalizePropertyValue(value);
|
|
1940
|
+
if (Array.isArray(value)) return value.map((item) => toNodeId(item));
|
|
1941
|
+
return toNodeId(value);
|
|
1942
|
+
}
|
|
1943
|
+
function normalizePropertyValue(value) {
|
|
1944
|
+
if (value instanceof Date) return value.toISOString();
|
|
1945
|
+
if (Array.isArray(value)) return value.map(normalizePropertyValue);
|
|
1946
|
+
if (isPlainObject(value)) {
|
|
1947
|
+
return Object.fromEntries(
|
|
1948
|
+
Object.entries(value).map(([key, nestedValue]) => [key, normalizePropertyValue(nestedValue)])
|
|
1949
|
+
);
|
|
1950
|
+
}
|
|
1951
|
+
return value;
|
|
1952
|
+
}
|
|
1953
|
+
function asNodeIdArray(value) {
|
|
1954
|
+
return Array.isArray(value) ? value.map((item) => toNodeId(item)) : [toNodeId(value)];
|
|
1955
|
+
}
|
|
1956
|
+
function toNodeId(value, label = "relation reference") {
|
|
1957
|
+
if (!isPlainObject(value) || typeof value.space !== "string" || typeof value.externalId !== "string") {
|
|
1958
|
+
throw new Error(`Invalid upsert options:
|
|
1959
|
+
- ${label}: expected a NodeId`);
|
|
1960
|
+
}
|
|
1961
|
+
return { space: value.space, externalId: value.externalId };
|
|
1962
|
+
}
|
|
1963
|
+
function instanceKey(instance) {
|
|
1964
|
+
return `${instance.space}\0${instance.externalId}`;
|
|
1965
|
+
}
|
|
1966
|
+
function uniqueDeletes(deletes) {
|
|
1967
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1968
|
+
return deletes.filter((item) => {
|
|
1969
|
+
const key = instanceKey(item);
|
|
1970
|
+
if (seen.has(key)) return false;
|
|
1971
|
+
seen.add(key);
|
|
1972
|
+
return true;
|
|
1973
|
+
});
|
|
1974
|
+
}
|
|
1975
|
+
function assertNodeId(value, label) {
|
|
1976
|
+
if (!isPlainObject(value) || typeof value.space !== "string" || typeof value.externalId !== "string") {
|
|
1977
|
+
throw new Error(`Invalid upsert options:
|
|
1978
|
+
- ${label}: expected a NodeId`);
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
function isPlainObject(value) {
|
|
1982
|
+
return value != null && typeof value === "object" && !Array.isArray(value);
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1366
1985
|
// src/mappers/view-mapper.ts
|
|
1367
1986
|
var ViewMapper = class {
|
|
1368
1987
|
constructor(cognite, dataModelId) {
|
|
@@ -1410,15 +2029,30 @@ var ViewMapper = class {
|
|
|
1410
2029
|
};
|
|
1411
2030
|
|
|
1412
2031
|
// src/client.ts
|
|
2032
|
+
var APPLY_ITEM_LIMIT = 1e3;
|
|
1413
2033
|
var IndustrialModelClient = class {
|
|
1414
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
|
+
};
|
|
1415
2046
|
const cognite = createCogniteAdapter(client);
|
|
1416
2047
|
this.cognite = cognite;
|
|
1417
2048
|
const viewMapper = new ViewMapper(cognite, dataModelId);
|
|
1418
2049
|
this.queryMapper = new QueryMapper(viewMapper, cognite);
|
|
1419
2050
|
this.aggregateMapper = new AggregateMapper(viewMapper, cognite);
|
|
2051
|
+
this.upsertMapper = new UpsertMapper(viewMapper, cognite);
|
|
1420
2052
|
this.aggregateResultMapper = new AggregateResultMapper();
|
|
1421
2053
|
this.resultMapper = new QueryResultMapper(viewMapper);
|
|
2054
|
+
this.datapointsMapper = new DatapointsMapper(cognite);
|
|
2055
|
+
this.filesMapper = new FilesMapper(cognite);
|
|
1422
2056
|
this.resultValidator = new QueryResultValidator(viewMapper);
|
|
1423
2057
|
this.validateResults = options.validateResults ?? false;
|
|
1424
2058
|
}
|
|
@@ -1430,6 +2064,52 @@ var IndustrialModelClient = class {
|
|
|
1430
2064
|
const execute = (options) => this.aggregateInternal(options);
|
|
1431
2065
|
return execute;
|
|
1432
2066
|
}
|
|
2067
|
+
upsert() {
|
|
2068
|
+
const execute = (options) => this.upsertInternal(options);
|
|
2069
|
+
return execute;
|
|
2070
|
+
}
|
|
2071
|
+
async delete(items) {
|
|
2072
|
+
this.deleteValidator.validateItems(items);
|
|
2073
|
+
const deleteItems = items.map((item) => ({
|
|
2074
|
+
instanceType: "node",
|
|
2075
|
+
space: item.space,
|
|
2076
|
+
externalId: item.externalId
|
|
2077
|
+
}));
|
|
2078
|
+
const response = await this.applyInstancesInChunks({
|
|
2079
|
+
items: [],
|
|
2080
|
+
delete: deleteItems
|
|
2081
|
+
});
|
|
2082
|
+
return { items: response.items };
|
|
2083
|
+
}
|
|
2084
|
+
async upsertInternal(options) {
|
|
2085
|
+
const cogniteRequest = await this.upsertMapper.map(options);
|
|
2086
|
+
const response = await this.applyInstancesInChunks(cogniteRequest);
|
|
2087
|
+
return { items: response.items };
|
|
2088
|
+
}
|
|
2089
|
+
async applyInstancesInChunks(request) {
|
|
2090
|
+
const deleteItems = request.delete ?? [];
|
|
2091
|
+
const totalItems = request.items.length + deleteItems.length;
|
|
2092
|
+
if (totalItems === 0) return { items: [] };
|
|
2093
|
+
if (totalItems <= APPLY_ITEM_LIMIT) {
|
|
2094
|
+
return this.cognite.applyInstances(request);
|
|
2095
|
+
}
|
|
2096
|
+
const responses = [];
|
|
2097
|
+
for (const deleteChunk of chunks(deleteItems, APPLY_ITEM_LIMIT)) {
|
|
2098
|
+
const response = await this.cognite.applyInstances({
|
|
2099
|
+
items: [],
|
|
2100
|
+
delete: deleteChunk
|
|
2101
|
+
});
|
|
2102
|
+
responses.push(...response.items);
|
|
2103
|
+
}
|
|
2104
|
+
for (const itemChunk of chunks(request.items, APPLY_ITEM_LIMIT)) {
|
|
2105
|
+
const response = await this.cognite.applyInstances({
|
|
2106
|
+
items: itemChunk,
|
|
2107
|
+
...request.replace === true ? { replace: true } : {}
|
|
2108
|
+
});
|
|
2109
|
+
responses.push(...response.items);
|
|
2110
|
+
}
|
|
2111
|
+
return { items: responses };
|
|
2112
|
+
}
|
|
1433
2113
|
async aggregateInternal(options) {
|
|
1434
2114
|
const cogniteRequest = await this.aggregateMapper.map(options);
|
|
1435
2115
|
const response = await this.cognite.aggregateInstances(cogniteRequest);
|
|
@@ -1508,6 +2188,17 @@ var CogniteCoreClient = class {
|
|
|
1508
2188
|
const execute = (options = {}) => aggregate({ ...options, viewExternalId });
|
|
1509
2189
|
return execute;
|
|
1510
2190
|
}
|
|
2191
|
+
upsert(viewExternalId) {
|
|
2192
|
+
const upsert = this.model.upsert();
|
|
2193
|
+
const execute = (options) => upsert({ ...options, viewExternalId });
|
|
2194
|
+
return execute;
|
|
2195
|
+
}
|
|
2196
|
+
delete(items) {
|
|
2197
|
+
return this.model.delete(items);
|
|
2198
|
+
}
|
|
2199
|
+
get datapoints() {
|
|
2200
|
+
return this.model.datapoints;
|
|
2201
|
+
}
|
|
1511
2202
|
};
|
|
1512
2203
|
|
|
1513
2204
|
exports.COGNITE_CORE_DATA_MODEL = COGNITE_CORE_DATA_MODEL;
|