@twin.org/entity-storage-connector-cosmosdb 0.0.3-next.13 → 0.0.3-next.14
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 +1 -1
- package/dist/es/cosmosDbEntityStorageConnector.js +235 -34
- package/dist/es/cosmosDbEntityStorageConnector.js.map +1 -1
- package/dist/types/cosmosDbEntityStorageConnector.d.ts +31 -3
- package/docs/changelog.md +16 -0
- package/docs/reference/classes/CosmosDbEntityStorageConnector.md +159 -15
- package/locales/en.json +3 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@ To perform testing of this component it may be necessary to launch a local insta
|
|
|
14
14
|
|
|
15
15
|
```shell
|
|
16
16
|
docker pull mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest
|
|
17
|
-
docker run --publish 8081:8081 --name twin-entity-storage-cosmos
|
|
17
|
+
docker run --publish 8081:8081 --detach --name twin-entity-storage-cosmos mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
## Examples
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// Copyright 2024 IOTA Stiftung.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0.
|
|
3
|
-
import { BulkOperationType, CosmosClient,
|
|
3
|
+
import { BulkOperationType, CosmosClient, PartitionKeyKind } from "@azure/cosmos";
|
|
4
4
|
import { ContextIdHelper, ContextIdStore } from "@twin.org/context";
|
|
5
5
|
import { BaseError, Coerce, ComponentFactory, GeneralError, Guards, HealthStatus, Is, ObjectHelper } from "@twin.org/core";
|
|
6
6
|
import { ComparisonOperator, EntitySchemaFactory, EntitySchemaHelper, LogicalOperator, SortDirection } from "@twin.org/entity";
|
|
7
|
+
import { EntityHelper } from "@twin.org/entity-storage-models";
|
|
7
8
|
/**
|
|
8
9
|
* Class for performing entity storage operations using Cosmos DB.
|
|
9
10
|
*/
|
|
@@ -27,6 +28,11 @@ export class CosmosDbEntityStorageConnector {
|
|
|
27
28
|
* @internal
|
|
28
29
|
*/
|
|
29
30
|
static _PARTITION_KEY_VALUE = "root";
|
|
31
|
+
/**
|
|
32
|
+
* The name for the schema.
|
|
33
|
+
* @internal
|
|
34
|
+
*/
|
|
35
|
+
_entitySchemaName;
|
|
30
36
|
/**
|
|
31
37
|
* The schema for the entity.
|
|
32
38
|
* @internal
|
|
@@ -70,13 +76,13 @@ export class CosmosDbEntityStorageConnector {
|
|
|
70
76
|
Guards.stringValue(CosmosDbEntityStorageConnector.CLASS_NAME, "options.config.databaseId", options.config.databaseId);
|
|
71
77
|
Guards.stringValue(CosmosDbEntityStorageConnector.CLASS_NAME, "options.config.containerId", options.config.containerId);
|
|
72
78
|
this._entitySchema = EntitySchemaFactory.get(options.entitySchema);
|
|
79
|
+
this._entitySchemaName = options.entitySchema;
|
|
73
80
|
this._partitionContextIds = options.partitionContextIds;
|
|
74
81
|
this._primaryKey = EntitySchemaHelper.getPrimaryKey(this._entitySchema);
|
|
75
82
|
this._config = options.config;
|
|
76
83
|
this._client = new CosmosClient({
|
|
77
84
|
endpoint: this._config.endpoint,
|
|
78
|
-
key: this._config.key
|
|
79
|
-
diagnosticLevel: CosmosDbDiagnosticLevel.debug
|
|
85
|
+
key: this._config.key
|
|
80
86
|
});
|
|
81
87
|
this._container = this._client
|
|
82
88
|
.database(this._config.databaseId)
|
|
@@ -245,9 +251,14 @@ export class CosmosDbEntityStorageConnector {
|
|
|
245
251
|
.read();
|
|
246
252
|
return this.itemToEntity(item);
|
|
247
253
|
}
|
|
254
|
+
const conditionValues = [];
|
|
248
255
|
const whereQuery = [
|
|
249
256
|
`c.${CosmosDbEntityStorageConnector._PARTITION_KEY} = @partitionKey`
|
|
250
257
|
];
|
|
258
|
+
conditionValues.push({
|
|
259
|
+
name: "@partitionKey",
|
|
260
|
+
value: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE
|
|
261
|
+
});
|
|
251
262
|
// With a secondary index
|
|
252
263
|
if (Is.stringValue(secondaryIndex)) {
|
|
253
264
|
const secIndex = secondaryIndex.toString();
|
|
@@ -256,24 +267,20 @@ export class CosmosDbEntityStorageConnector {
|
|
|
256
267
|
else {
|
|
257
268
|
whereQuery.push(`c.${this._primaryKey.property} = @id`);
|
|
258
269
|
}
|
|
270
|
+
conditionValues.push({ name: "@id", value: id });
|
|
259
271
|
// With conditions
|
|
260
272
|
if (Is.arrayValue(conditions)) {
|
|
261
273
|
for (const c of conditions) {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
274
|
+
whereQuery.push(`c.${c.property} = @${c.property}`);
|
|
275
|
+
conditionValues.push({
|
|
276
|
+
name: `@${c.property}`,
|
|
277
|
+
value: c.value
|
|
278
|
+
});
|
|
266
279
|
}
|
|
267
280
|
}
|
|
268
281
|
const query = {
|
|
269
282
|
query: `SELECT * FROM c WHERE ${whereQuery.join(" AND ")}`,
|
|
270
|
-
parameters:
|
|
271
|
-
{ name: "@id", value: id },
|
|
272
|
-
{
|
|
273
|
-
name: "@partitionKey",
|
|
274
|
-
value: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE
|
|
275
|
-
}
|
|
276
|
-
]
|
|
283
|
+
parameters: conditionValues
|
|
277
284
|
};
|
|
278
285
|
const { resources: items } = await this._container.items.query(query).fetchAll();
|
|
279
286
|
if (items.length === 1) {
|
|
@@ -366,8 +373,27 @@ export class CosmosDbEntityStorageConnector {
|
|
|
366
373
|
async empty() {
|
|
367
374
|
const contextIds = await ContextIdStore.getContextIds();
|
|
368
375
|
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
376
|
+
const pk = partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE;
|
|
369
377
|
try {
|
|
370
|
-
|
|
378
|
+
let continuationToken;
|
|
379
|
+
do {
|
|
380
|
+
const feedOptions = { maxItemCount: 100, continuationToken };
|
|
381
|
+
const { resources, continuationToken: nextToken } = await this._container.items
|
|
382
|
+
.query({
|
|
383
|
+
query: `SELECT c.id FROM c WHERE c.${CosmosDbEntityStorageConnector._PARTITION_KEY} = @pk`,
|
|
384
|
+
parameters: [{ name: "@pk", value: pk }]
|
|
385
|
+
}, feedOptions)
|
|
386
|
+
.fetchNext();
|
|
387
|
+
continuationToken = nextToken;
|
|
388
|
+
if (Is.arrayValue(resources)) {
|
|
389
|
+
const operations = resources.map(r => ({
|
|
390
|
+
operationType: BulkOperationType.Delete,
|
|
391
|
+
id: r.id,
|
|
392
|
+
partitionKey: pk
|
|
393
|
+
}));
|
|
394
|
+
await this._container.items.executeBulkOperations(operations);
|
|
395
|
+
}
|
|
396
|
+
} while (Is.stringValue(continuationToken));
|
|
371
397
|
}
|
|
372
398
|
catch (err) {
|
|
373
399
|
throw new GeneralError(CosmosDbEntityStorageConnector.CLASS_NAME, "emptyFailed", undefined, err);
|
|
@@ -432,8 +458,6 @@ export class CosmosDbEntityStorageConnector {
|
|
|
432
458
|
*/
|
|
433
459
|
async teardown(nodeLoggingComponentType) {
|
|
434
460
|
const nodeLogging = ComponentFactory.getIfExists(nodeLoggingComponentType);
|
|
435
|
-
const contextIds = await ContextIdStore.getContextIds();
|
|
436
|
-
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
437
461
|
await nodeLogging?.log({
|
|
438
462
|
level: "info",
|
|
439
463
|
source: CosmosDbEntityStorageConnector.CLASS_NAME,
|
|
@@ -442,8 +466,10 @@ export class CosmosDbEntityStorageConnector {
|
|
|
442
466
|
data: { containerId: this._config.containerId }
|
|
443
467
|
});
|
|
444
468
|
try {
|
|
445
|
-
await this.
|
|
446
|
-
|
|
469
|
+
if (await this.containerExists()) {
|
|
470
|
+
await this._container.delete();
|
|
471
|
+
await this.waitForContainerNotExists();
|
|
472
|
+
}
|
|
447
473
|
await nodeLogging?.log({
|
|
448
474
|
level: "info",
|
|
449
475
|
source: CosmosDbEntityStorageConnector.CLASS_NAME,
|
|
@@ -505,7 +531,7 @@ export class CosmosDbEntityStorageConnector {
|
|
|
505
531
|
if (queryClause.length > 0) {
|
|
506
532
|
queryClause = ` AND ${queryClause}`;
|
|
507
533
|
}
|
|
508
|
-
sql = `SELECT ${properties ? properties.map(p => `c.${p}`).join(", ") : "*"} FROM c WHERE c.
|
|
534
|
+
sql = `SELECT ${properties ? properties.map(p => `c.${p}`).join(", ") : "*"} FROM c WHERE c.${CosmosDbEntityStorageConnector._PARTITION_KEY} = @partitionId ${queryClause} ${orderByClause}`;
|
|
509
535
|
const querySpecs = {
|
|
510
536
|
query: sql,
|
|
511
537
|
parameters: [
|
|
@@ -521,9 +547,23 @@ export class CosmosDbEntityStorageConnector {
|
|
|
521
547
|
continuationToken: cursor
|
|
522
548
|
};
|
|
523
549
|
const feedResponse = await this._container.items.query(querySpecs, feedOptions).fetchNext();
|
|
550
|
+
// CosmosDB returns a continuation token even on the last page, so peek ahead
|
|
551
|
+
// to confirm there are actually more results before exposing the cursor.
|
|
552
|
+
let resultCursor;
|
|
553
|
+
if (feedResponse.resources.length >= returnSize && feedResponse.continuationToken) {
|
|
554
|
+
const peekResponse = await this._container.items
|
|
555
|
+
.query(querySpecs, {
|
|
556
|
+
maxItemCount: 1,
|
|
557
|
+
continuationToken: feedResponse.continuationToken
|
|
558
|
+
})
|
|
559
|
+
.fetchNext();
|
|
560
|
+
if (peekResponse.resources.length > 0) {
|
|
561
|
+
resultCursor = feedResponse.continuationToken;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
524
564
|
return {
|
|
525
565
|
entities: feedResponse.resources.map(i => this.itemToEntity(i)),
|
|
526
|
-
cursor:
|
|
566
|
+
cursor: resultCursor
|
|
527
567
|
};
|
|
528
568
|
}
|
|
529
569
|
catch (err) {
|
|
@@ -532,19 +572,29 @@ export class CosmosDbEntityStorageConnector {
|
|
|
532
572
|
}
|
|
533
573
|
/**
|
|
534
574
|
* Count all the entities which match the conditions.
|
|
575
|
+
* @param conditions The optional conditions to match for the entities.
|
|
535
576
|
* @returns The total count of entities in the storage.
|
|
536
577
|
*/
|
|
537
|
-
async count() {
|
|
578
|
+
async count(conditions) {
|
|
538
579
|
try {
|
|
539
580
|
const contextIds = await ContextIdStore.getContextIds();
|
|
540
581
|
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
582
|
+
const attributeNames = {};
|
|
583
|
+
const attributeValues = {};
|
|
584
|
+
let queryClause = Is.empty(conditions)
|
|
585
|
+
? ""
|
|
586
|
+
: this.buildQueryParameters("", conditions, attributeNames, attributeValues);
|
|
587
|
+
if (queryClause.length > 0) {
|
|
588
|
+
queryClause = ` AND ${queryClause}`;
|
|
589
|
+
}
|
|
541
590
|
const querySpec = {
|
|
542
|
-
query:
|
|
591
|
+
query: `SELECT VALUE COUNT(1) FROM c WHERE c.${CosmosDbEntityStorageConnector._PARTITION_KEY} = @partitionId${queryClause}`,
|
|
543
592
|
parameters: [
|
|
544
593
|
{
|
|
545
594
|
name: "@partitionId",
|
|
546
595
|
value: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE
|
|
547
|
-
}
|
|
596
|
+
},
|
|
597
|
+
...Object.keys(attributeValues).map(key => ({ name: `@${key}`, value: attributeValues[key] }))
|
|
548
598
|
]
|
|
549
599
|
};
|
|
550
600
|
const { resources } = await this._container.items.query(querySpec).fetchAll();
|
|
@@ -554,6 +604,122 @@ export class CosmosDbEntityStorageConnector {
|
|
|
554
604
|
throw new GeneralError(CosmosDbEntityStorageConnector.CLASS_NAME, "countFailed", undefined, err);
|
|
555
605
|
}
|
|
556
606
|
}
|
|
607
|
+
/**
|
|
608
|
+
* Get a unique list of all the context ids from the storage.
|
|
609
|
+
* @returns The list of unique context ids.
|
|
610
|
+
*/
|
|
611
|
+
async getPartitionContextIds() {
|
|
612
|
+
const partitionContextIds = this._partitionContextIds;
|
|
613
|
+
if (!Is.arrayValue(partitionContextIds)) {
|
|
614
|
+
return [];
|
|
615
|
+
}
|
|
616
|
+
try {
|
|
617
|
+
const { resources: partitionIds } = await this._container.items
|
|
618
|
+
.query({
|
|
619
|
+
query: `SELECT DISTINCT VALUE c.${CosmosDbEntityStorageConnector._PARTITION_KEY} FROM c`
|
|
620
|
+
})
|
|
621
|
+
.fetchAll();
|
|
622
|
+
return partitionIds
|
|
623
|
+
.filter(id => Is.stringValue(id))
|
|
624
|
+
.map(id => ContextIdHelper.shortSplit(partitionContextIds, id));
|
|
625
|
+
}
|
|
626
|
+
catch (err) {
|
|
627
|
+
throw new GeneralError(CosmosDbEntityStorageConnector.CLASS_NAME, "getPartitionContextIdsFailed", undefined, err);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Create the target connector for performing the migration using a temporary container.
|
|
632
|
+
* @param newEntitySchema The name of the new entity schema to create the connector for.
|
|
633
|
+
* @returns Connector for performing the migration.
|
|
634
|
+
*/
|
|
635
|
+
async createTargetConnector(newEntitySchema) {
|
|
636
|
+
const migrationContainerId = `${this._config.containerId}Migration${Date.now()}`;
|
|
637
|
+
return new CosmosDbEntityStorageConnector({
|
|
638
|
+
entitySchema: newEntitySchema,
|
|
639
|
+
config: { ...this._config, containerId: migrationContainerId },
|
|
640
|
+
partitionContextIds: this._partitionContextIds
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Finalize the migration by tearing down the old container and replacing it with the target container.
|
|
645
|
+
* @param targetConnector The target connector to finalize the migration with.
|
|
646
|
+
* @param options The options to control how the migration is finalized.
|
|
647
|
+
* @param loggingComponentType The optional component type to use for logging.
|
|
648
|
+
* @returns The final connector pointing at the original container id.
|
|
649
|
+
*/
|
|
650
|
+
async finalizeMigration(targetConnector, options, loggingComponentType) {
|
|
651
|
+
// There is no rename operation in DynamoDB so we have to create a new table with the original name and copy the data over
|
|
652
|
+
// Teardown the existing table with the original name to free up the name for the new table
|
|
653
|
+
await this.teardown(loggingComponentType);
|
|
654
|
+
// Create a new connector with the original table name but with the new schema
|
|
655
|
+
// and copy the data from the migration table to the new table using batch operations
|
|
656
|
+
const finalConnector = new CosmosDbEntityStorageConnector({
|
|
657
|
+
entitySchema: targetConnector._entitySchemaName,
|
|
658
|
+
config: this._config,
|
|
659
|
+
partitionContextIds: this._partitionContextIds
|
|
660
|
+
});
|
|
661
|
+
if (await finalConnector.bootstrap(loggingComponentType)) {
|
|
662
|
+
// Since there is no rename, we need to copy the data from the migration table to the new table
|
|
663
|
+
const partitions = await targetConnector.getPartitionContextIds();
|
|
664
|
+
const batchSize = options?.batchSize ?? CosmosDbEntityStorageConnector._DEFAULT_LIMIT;
|
|
665
|
+
await this.bulkCopy(targetConnector, finalConnector, partitions, batchSize);
|
|
666
|
+
await targetConnector.teardown(loggingComponentType);
|
|
667
|
+
return finalConnector;
|
|
668
|
+
}
|
|
669
|
+
throw new GeneralError(CosmosDbEntityStorageConnector.CLASS_NAME, "finalizeMigrationFailedBootstrap");
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Cleanup the migration if a migration fails or needs to be aborted.
|
|
673
|
+
* @param targetConnector The target connector to cleanup.
|
|
674
|
+
* @param options The options to control how the migration is cleaned up.
|
|
675
|
+
* @param loggingComponentType The optional component type to use for logging.
|
|
676
|
+
*/
|
|
677
|
+
async cleanupMigration(targetConnector, options, loggingComponentType) {
|
|
678
|
+
// If something failed the only thing to cleanup is the migration table
|
|
679
|
+
await targetConnector?.teardown?.(loggingComponentType);
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Copy all entities from sourceConnector to destConnector, paging through each partition.
|
|
683
|
+
* @param sourceConnector The connector to read entities from.
|
|
684
|
+
* @param destConnector The connector to write entities to.
|
|
685
|
+
* @param partitions The partition list returned by getPartitionContextIds.
|
|
686
|
+
* @param batchSize The number of entities to read per page.
|
|
687
|
+
* @internal
|
|
688
|
+
*/
|
|
689
|
+
async bulkCopy(sourceConnector, destConnector, partitions, batchSize) {
|
|
690
|
+
let partitionList;
|
|
691
|
+
if (Is.arrayValue(partitions)) {
|
|
692
|
+
partitionList = partitions;
|
|
693
|
+
}
|
|
694
|
+
else if (Is.arrayValue(sourceConnector._partitionContextIds)) {
|
|
695
|
+
partitionList = [];
|
|
696
|
+
}
|
|
697
|
+
else {
|
|
698
|
+
partitionList = [{}];
|
|
699
|
+
}
|
|
700
|
+
for (let i = 0; i < partitionList.length; i++) {
|
|
701
|
+
const partitionKey = ContextIdHelper.combinedContextKey(partitionList[i], sourceConnector._partitionContextIds) ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE;
|
|
702
|
+
let continuationToken;
|
|
703
|
+
do {
|
|
704
|
+
const feedOptions = { maxItemCount: batchSize, continuationToken };
|
|
705
|
+
const { resources, continuationToken: nextToken } = await sourceConnector._container.items
|
|
706
|
+
.query({
|
|
707
|
+
query: `SELECT * FROM c WHERE c.${CosmosDbEntityStorageConnector._PARTITION_KEY} = @partitionId`,
|
|
708
|
+
parameters: [{ name: "@partitionId", value: partitionKey }]
|
|
709
|
+
}, feedOptions)
|
|
710
|
+
.fetchNext();
|
|
711
|
+
continuationToken = nextToken;
|
|
712
|
+
if (Is.arrayValue(resources)) {
|
|
713
|
+
const operations = resources.map(({ _rid, _self, _ts, _etag, _attachments, ...rest }) => ({
|
|
714
|
+
operationType: BulkOperationType.Upsert,
|
|
715
|
+
partitionKey,
|
|
716
|
+
resourceBody: rest
|
|
717
|
+
}));
|
|
718
|
+
await destConnector._container.items.executeBulkOperations(operations);
|
|
719
|
+
}
|
|
720
|
+
} while (Is.stringValue(continuationToken));
|
|
721
|
+
}
|
|
722
|
+
}
|
|
557
723
|
/**
|
|
558
724
|
* Create an SQL condition clause.
|
|
559
725
|
* @param objectPath The path for the nested object.
|
|
@@ -626,7 +792,27 @@ export class CosmosDbEntityStorageConnector {
|
|
|
626
792
|
propName = attributeName;
|
|
627
793
|
attributeName = `(${arrAttributeNames.map(name => `@${name}`).join(", ")})`;
|
|
628
794
|
}
|
|
795
|
+
else if (Is.object(comparator.value) &&
|
|
796
|
+
(comparator.comparison === ComparisonOperator.Equals ||
|
|
797
|
+
comparator.comparison === ComparisonOperator.NotEquals)) {
|
|
798
|
+
// CosmosDB SQL does not support object equality with =; expand to per-property comparisons.
|
|
799
|
+
const op = comparator.comparison === ComparisonOperator.Equals ? "=" : "<>";
|
|
800
|
+
const join = comparator.comparison === ComparisonOperator.Equals ? " AND " : " OR ";
|
|
801
|
+
const clauses = [];
|
|
802
|
+
for (const [key, val] of Object.entries(comparator.value)) {
|
|
803
|
+
const paramName = `${propName}${key}`;
|
|
804
|
+
attributeValues[paramName] = val;
|
|
805
|
+
clauses.push(`c.${attributeName}.${key} ${op} @${paramName}`);
|
|
806
|
+
}
|
|
807
|
+
return clauses.length === 1 ? clauses[0] : `(${clauses.join(join)})`;
|
|
808
|
+
}
|
|
629
809
|
else {
|
|
810
|
+
// Avoid parameter name conflicts by ensuring unique parameter names in the query
|
|
811
|
+
let counter = 1;
|
|
812
|
+
while (propName in attributeValues) {
|
|
813
|
+
propName = `${attributeName.replace(/\./g, "").replace(/@/g, "")}${counter}`;
|
|
814
|
+
counter++;
|
|
815
|
+
}
|
|
630
816
|
attributeValues[propName] = comparator.value;
|
|
631
817
|
}
|
|
632
818
|
const matches = attributeName.split(".").length;
|
|
@@ -657,13 +843,13 @@ export class CosmosDbEntityStorageConnector {
|
|
|
657
843
|
}
|
|
658
844
|
else if (typeof attributeValues[propName] === "object" &&
|
|
659
845
|
comparator.comparison === ComparisonOperator.Includes) {
|
|
660
|
-
return `
|
|
846
|
+
return `ARRAY_CONTAINS(c.${attributeName}, @${propName}, true)`;
|
|
661
847
|
}
|
|
662
848
|
else if (comparator.comparison === ComparisonOperator.Includes) {
|
|
663
|
-
return `
|
|
849
|
+
return `CONTAINS(c.${attributeName}, @${propName})`;
|
|
664
850
|
}
|
|
665
851
|
else if (comparator.comparison === ComparisonOperator.NotIncludes) {
|
|
666
|
-
return `
|
|
852
|
+
return `NOT CONTAINS(c.${attributeName}, @${propName})`;
|
|
667
853
|
}
|
|
668
854
|
else if (comparator.comparison === ComparisonOperator.In) {
|
|
669
855
|
return `c.${propName} IN ${attributeName}`;
|
|
@@ -750,13 +936,14 @@ export class CosmosDbEntityStorageConnector {
|
|
|
750
936
|
* @internal
|
|
751
937
|
*/
|
|
752
938
|
itemToEntity(item) {
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
939
|
+
return EntityHelper.unPrepareEntity(item, [
|
|
940
|
+
CosmosDbEntityStorageConnector._PARTITION_KEY,
|
|
941
|
+
"_attachments",
|
|
942
|
+
"_etag",
|
|
943
|
+
"_rid",
|
|
944
|
+
"_self",
|
|
945
|
+
"_ts"
|
|
946
|
+
]);
|
|
760
947
|
}
|
|
761
948
|
/**
|
|
762
949
|
* Check if the database exists.
|
|
@@ -817,5 +1004,19 @@ export class CosmosDbEntityStorageConnector {
|
|
|
817
1004
|
await new Promise(resolve => setTimeout(resolve, 250));
|
|
818
1005
|
}
|
|
819
1006
|
}
|
|
1007
|
+
/**
|
|
1008
|
+
* Wait for a container to not exist.
|
|
1009
|
+
* @returns Nothing.
|
|
1010
|
+
* @internal
|
|
1011
|
+
*/
|
|
1012
|
+
async waitForContainerNotExists() {
|
|
1013
|
+
for (let attempt = 0; attempt < 20; attempt++) {
|
|
1014
|
+
const containerExists = await this.containerExists();
|
|
1015
|
+
if (!containerExists) {
|
|
1016
|
+
break;
|
|
1017
|
+
}
|
|
1018
|
+
await new Promise(resolve => setTimeout(resolve, 250));
|
|
1019
|
+
}
|
|
1020
|
+
}
|
|
820
1021
|
}
|
|
821
1022
|
//# sourceMappingURL=cosmosDbEntityStorageConnector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cosmosDbEntityStorageConnector.js","sourceRoot":"","sources":["../../src/cosmosDbEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\tBulkOperationType,\n\ttype Container,\n\tCosmosClient,\n\tCosmosDbDiagnosticLevel,\n\ttype FeedOptions,\n\ttype ItemDefinition,\n\ttype OperationInput,\n\tPartitionKeyKind,\n\ttype Resource,\n\ttype SqlParameter,\n\ttype SqlQuerySpec\n} from \"@azure/cosmos\";\nimport { ContextIdHelper, ContextIdStore } from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tCoerce,\n\tComponentFactory,\n\tGeneralError,\n\tGuards,\n\tHealthStatus,\n\ttype IHealth,\n\tIs,\n\tObjectHelper\n} from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\ttype EntitySchemaPropertyType,\n\ttype IComparator,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tLogicalOperator,\n\tSortDirection\n} from \"@twin.org/entity\";\nimport type { IEntityStorageConnector } from \"@twin.org/entity-storage-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { ICosmosDbEntityStorageConnectorConfig } from \"./models/ICosmosDbEntityStorageConnectorConfig.js\";\nimport type { ICosmosDbEntityStorageConnectorConstructorOptions } from \"./models/ICosmosDbEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations using Cosmos DB.\n */\nexport class CosmosDbEntityStorageConnector<T = unknown> implements IEntityStorageConnector<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<CosmosDbEntityStorageConnector>();\n\n\t/**\n\t * Limit the number of entities when finding.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_LIMIT: number = 40;\n\n\t/**\n\t * Partition id field name.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY: string = \"partitionId\";\n\n\t/**\n\t * Partition id field value.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY_VALUE: string = \"root\";\n\n\t/**\n\t * The schema for the entity.\n\t * @internal\n\t */\n\tprivate readonly _entitySchema: IEntitySchema<T>;\n\n\t/**\n\t * The keys to use from the context ids to create partitions.\n\t * @internal\n\t */\n\tprivate readonly _partitionContextIds?: string[];\n\n\t/**\n\t * The primary key.\n\t * @internal\n\t */\n\tprivate readonly _primaryKey: IEntitySchemaProperty<T>;\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: ICosmosDbEntityStorageConnectorConfig;\n\n\t/**\n\t * The Cosmos DB client.\n\t * @internal\n\t */\n\tprivate readonly _client: CosmosClient;\n\n\t/**\n\t * Container user for the data storage.\n\t * @internal\n\t */\n\tprivate readonly _container: Container;\n\n\t/**\n\t * Create a new instance of CosmosDbEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: ICosmosDbEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(CosmosDbEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<ICosmosDbEntityStorageConnectorConfig>(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.endpoint),\n\t\t\toptions.config.endpoint\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.key),\n\t\t\toptions.config.key\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.databaseId),\n\t\t\toptions.config.databaseId\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.containerId),\n\t\t\toptions.config.containerId\n\t\t);\n\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\n\t\tthis._primaryKey = EntitySchemaHelper.getPrimaryKey<T>(this._entitySchema);\n\n\t\tthis._config = options.config;\n\n\t\tthis._client = new CosmosClient({\n\t\t\tendpoint: this._config.endpoint,\n\t\t\tkey: this._config.key,\n\t\t\tdiagnosticLevel: CosmosDbDiagnosticLevel.debug\n\t\t});\n\n\t\tthis._container = this._client\n\t\t\t.database(this._config.databaseId)\n\t\t\t.container(this._config.containerId);\n\t}\n\n\t/**\n\t * Initialize the Cosmos DB environment.\n\t * @param nodeLoggingComponentType Optional type of the logging component.\n\t * @returns A promise that resolves to a boolean indicating success.\n\t */\n\tpublic async bootstrap(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\t// Create the database if it does not exist\n\t\ttry {\n\t\t\tconst databaseExists = await this.databaseExists();\n\n\t\t\tif (databaseExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"databaseExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdatabaseId: this._config.databaseId\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"databaseCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdatabaseId: this._config.databaseId\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tawait this._client.databases.create({\n\t\t\t\t\tid: this._config.databaseId\n\t\t\t\t});\n\n\t\t\t\tawait this.waitForDatabaseExists();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"databaseCreateFailed\",\n\t\t\t\terror: BaseError.fromError(error),\n\t\t\t\tdata: {\n\t\t\t\t\tdatabaseId: this._config.databaseId\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\n\t\t// Create the container if it does not exist\n\t\ttry {\n\t\t\tconst containerExists = await this.containerExists();\n\n\t\t\tif (containerExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"containerExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcontainerId: this._config.containerId\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"containerCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcontainerId: this._config.containerId\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tawait this._client.database(this._config.databaseId).containers.create(\n\t\t\t\t\t{\n\t\t\t\t\t\tid: this._config.containerId,\n\t\t\t\t\t\tpartitionKey: {\n\t\t\t\t\t\t\tkind: PartitionKeyKind.Hash,\n\t\t\t\t\t\t\tpaths: [`/${CosmosDbEntityStorageConnector._PARTITION_KEY}`]\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{ offerThroughput: this._config.offerThroughput }\n\t\t\t\t);\n\n\t\t\t\tawait this.waitForContainerExists();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"containerCreateFailed\",\n\t\t\t\terror: BaseError.fromError(error),\n\t\t\t\tdata: {\n\t\t\t\t\tcontainerId: this._config.containerId\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn CosmosDbEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Returns the health status of the component.\n\t * @returns The health status of the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\ttry {\n\t\t\tawait this._client\n\t\t\t\t.database(this._config.databaseId)\n\t\t\t\t.container(this._config.containerId)\n\t\t\t\t.read();\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tdata: { databaseId: this._config.databaseId, containerId: this._config.containerId }\n\t\t\t\t}\n\t\t\t];\n\t\t} catch {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Error,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tmessage: \"connectionFailed\",\n\t\t\t\t\tdata: { databaseId: this._config.databaseId, containerId: this._config.containerId }\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * Get an entity from Cosmos DB.\n\t * @param id The id of the entity to get, or the index value if secondaryIndex is set.\n\t * @param secondaryIndex Get the item using a secondary index.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The object if it can be found or undefined.\n\t */\n\tpublic async get(\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<T | undefined> {\n\t\tGuards.stringValue(CosmosDbEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\t// No secondary index or conditions\n\t\t\tif (Is.empty(secondaryIndex) && !Is.arrayValue(conditions)) {\n\t\t\t\tconst { resource: item } = await this._container\n\t\t\t\t\t.item(id, partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE)\n\t\t\t\t\t.read<ItemDefinition>();\n\t\t\t\treturn this.itemToEntity(item);\n\t\t\t}\n\n\t\t\tconst whereQuery: string[] = [\n\t\t\t\t`c.${CosmosDbEntityStorageConnector._PARTITION_KEY} = @partitionKey`\n\t\t\t];\n\n\t\t\t// With a secondary index\n\t\t\tif (Is.stringValue(secondaryIndex)) {\n\t\t\t\tconst secIndex = secondaryIndex.toString();\n\t\t\t\twhereQuery.push(`c.${secIndex} = @id`);\n\t\t\t} else {\n\t\t\t\twhereQuery.push(`c.${this._primaryKey.property as string} = @id`);\n\t\t\t}\n\n\t\t\t// With conditions\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tfor (const c of conditions) {\n\t\t\t\t\tconst schemaProp = this._entitySchema.properties?.find(p => p.property === c.property);\n\t\t\t\t\twhereQuery.push(\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n\t\t\t\t\t\t`c.${String(c.property)} = ${this.propertyToDbValue(c.value, schemaProp?.type)}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst query: SqlQuerySpec = {\n\t\t\t\tquery: `SELECT * FROM c WHERE ${whereQuery.join(\" AND \")}`,\n\t\t\t\tparameters: [\n\t\t\t\t\t{ name: \"@id\", value: id },\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"@partitionKey\",\n\t\t\t\t\t\tvalue: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t};\n\n\t\t\tconst { resources: items } = await this._container.items.query(query).fetchAll();\n\n\t\t\tif (items.length === 1) {\n\t\t\t\treturn this.itemToEntity(items[0]);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorCode(err, \"NotFound\")) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"containerDoesNotExist\",\n\t\t\t\t\t{\n\t\t\t\t\t\tcontainerId: this._config.containerId\n\t\t\t\t\t},\n\t\t\t\t\terr\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"getFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Set an entity.\n\t * @param entity The entity to set.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The id of the entity.\n\t */\n\tpublic async set(entity: T, conditions?: { property: keyof T; value: unknown }[]): Promise<void> {\n\t\tGuards.object<T>(CosmosDbEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tEntitySchemaHelper.validateEntity(entity, this.getSchema());\n\n\t\tconst id = entity[this._primaryKey.property] as string;\n\n\t\ttry {\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tconst item = this._container.item(\n\t\t\t\t\tid,\n\t\t\t\t\tpartitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t);\n\t\t\t\tconst { resource: itemData } = await item.read<ItemDefinition>();\n\t\t\t\tif (Is.notEmpty(itemData) && !this.verifyConditions(conditions, itemData as T)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait this._container.items.upsert({\n\t\t\t\tid,\n\t\t\t\t[CosmosDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\tpartitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\t...entity\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tif (BaseError.isAggregateError(err)) {\n\t\t\t\tconst errors = BaseError.fromAggregate(err);\n\t\t\t\tif (BaseError.someErrorCode(errors, \"ResourceNotFoundException\")) {\n\t\t\t\t\tthrow new GeneralError(\n\t\t\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\t\"containerDoesNotExist\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontainerId: this._config.containerId\n\t\t\t\t\t\t},\n\t\t\t\t\t\terr\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Set multiple entities in a batch.\n\t * @param entities The entities to set.\n\t * @returns Nothing.\n\t */\n\tpublic async setBatch(entities: T[]): Promise<void> {\n\t\tGuards.arrayValue(CosmosDbEntityStorageConnector.CLASS_NAME, nameof(entities), entities);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tfor (const entity of entities) {\n\t\t\tEntitySchemaHelper.validateEntity(entity, this.getSchema());\n\t\t}\n\n\t\ttry {\n\t\t\tawait this._container.items.executeBulkOperations(\n\t\t\t\tentities.map(\n\t\t\t\t\tentity =>\n\t\t\t\t\t\t({\n\t\t\t\t\t\t\toperationType: BulkOperationType.Upsert,\n\t\t\t\t\t\t\tpartitionKey: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\t\t\t\tresourceBody: {\n\t\t\t\t\t\t\t\tid: entity[this._primaryKey.property] as string,\n\t\t\t\t\t\t\t\t[CosmosDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\t\t\t\tpartitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\t\t\t\t\t...(entity as { [key: string]: unknown })\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}) as OperationInput\n\t\t\t\t)\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setBatchFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Empty all entities from the storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tawait this._container.deleteAllItemsForPartitionKey(\n\t\t\t\tpartitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"emptyFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Remove the entity.\n\t * @param id The id of the entity to remove.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns Nothing.\n\t */\n\tpublic async remove(\n\t\tid: string,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<void> {\n\t\tGuards.stringValue(CosmosDbEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst item = this._container.item(\n\t\t\t\tid,\n\t\t\t\tpartitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t);\n\t\t\tconst { resource: itemData } = await item.read<ItemDefinition>();\n\t\t\tif (Is.notEmpty(itemData)) {\n\t\t\t\tif (Is.arrayValue(conditions) && !this.verifyConditions(conditions, itemData as T)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tawait item.delete();\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\tBaseError.fromError(err) &&\n\t\t\t\tIs.object<{ body?: { code?: string } }>(err) &&\n\t\t\t\terr.body?.code === \"NotFound\"\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Remove multiple entities by id.\n\t * @param ids The ids of the entities to remove.\n\t * @returns Nothing.\n\t */\n\tpublic async removeBatch(ids: string[]): Promise<void> {\n\t\tGuards.arrayValue(CosmosDbEntityStorageConnector.CLASS_NAME, nameof(ids), ids);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst operations: OperationInput[] = ids.map(id => ({\n\t\t\t\toperationType: BulkOperationType.Delete,\n\t\t\t\tid,\n\t\t\t\tpartitionKey: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t}));\n\n\t\t\tawait this._container.items.executeBulkOperations(operations);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeBatchFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Teardown the storage by deleting the underlying container.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the teardown process was successful.\n\t */\n\tpublic async teardown(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"containerDeleting\",\n\t\t\tdata: { containerId: this._config.containerId }\n\t\t});\n\n\t\ttry {\n\t\t\tawait this._container.deleteAllItemsForPartitionKey(\n\t\t\t\tpartitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t);\n\t\t\tawait this._container.delete();\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"containerDeleted\",\n\t\t\t\tdata: { containerId: this._config.containerId }\n\t\t\t});\n\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"teardownFailed\",\n\t\t\t\terror: BaseError.fromError(err)\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Find all the entities which match the conditions.\n\t * @param conditions The conditions to match for the entities.\n\t * @param sortProperties The optional sort order.\n\t * @param properties The optional properties to return, defaults to all.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t */\n\tpublic async query(\n\t\tconditions?: EntityCondition<T>,\n\t\tsortProperties?: { property: keyof T; sortDirection: SortDirection }[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{ entities: Partial<T>[]; cursor?: string }> {\n\t\tlet sql = \"\";\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst returnSize = limit ?? CosmosDbEntityStorageConnector._DEFAULT_LIMIT;\n\n\t\t\tlet orderByClause: string = \"\";\n\t\t\tif (Array.isArray(sortProperties)) {\n\t\t\t\tif (sortProperties.length > 1) {\n\t\t\t\t\tthrow new GeneralError(CosmosDbEntityStorageConnector.CLASS_NAME, \"sortSingle\");\n\t\t\t\t}\n\t\t\t\tfor (const sortProperty of sortProperties) {\n\t\t\t\t\tconst propertySchema = this._entitySchema.properties?.find(\n\t\t\t\t\t\te => e.property === sortProperty.property\n\t\t\t\t\t);\n\t\t\t\t\tif (\n\t\t\t\t\t\t!propertySchema ||\n\t\t\t\t\t\t(!propertySchema.isPrimary &&\n\t\t\t\t\t\t\t!propertySchema.isSecondary &&\n\t\t\t\t\t\t\t!propertySchema.sortDirection)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new GeneralError(CosmosDbEntityStorageConnector.CLASS_NAME, \"sortNotIndexed\", {\n\t\t\t\t\t\t\tproperty: sortProperty.property\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tconst direction = sortProperty.sortDirection === SortDirection.Ascending ? \"asc\" : \"desc\";\n\t\t\t\t\torderByClause = `ORDER BY c.${String(sortProperty.property)} ${direction}`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst attributeNames: { [id: string]: string } = {};\n\t\t\tconst attributeValues: { [id: string]: unknown } = {};\n\t\t\tlet queryClause = this.buildQueryParameters(\"\", conditions, attributeNames, attributeValues);\n\n\t\t\tif (queryClause.length > 0) {\n\t\t\t\tqueryClause = ` AND ${queryClause}`;\n\t\t\t}\n\n\t\t\tsql = `SELECT ${properties ? properties.map(p => `c.${p as string}`).join(\", \") : \"*\"} FROM c WHERE c.partitionId = @partitionId ${queryClause} ${orderByClause}`;\n\t\t\tconst querySpecs: SqlQuerySpec = {\n\t\t\t\tquery: sql,\n\t\t\t\tparameters: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"@partitionId\",\n\t\t\t\t\t\tvalue: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t},\n\t\t\t\t\t...Object.keys(attributeValues).map(\n\t\t\t\t\t\tkey => ({ name: `@${key}`, value: attributeValues[key] }) as SqlParameter\n\t\t\t\t\t)\n\t\t\t\t]\n\t\t\t};\n\n\t\t\tconst feedOptions: FeedOptions = {\n\t\t\t\tmaxItemCount: returnSize,\n\t\t\t\tcontinuationToken: cursor\n\t\t\t};\n\n\t\t\tconst feedResponse = await this._container.items.query(querySpecs, feedOptions).fetchNext();\n\n\t\t\treturn {\n\t\t\t\tentities: feedResponse.resources.map(i => this.itemToEntity(i)),\n\t\t\t\tcursor: feedResponse.continuationToken\n\t\t\t};\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"queryFailed\",\n\t\t\t\t{ sql },\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Count all the entities which match the conditions.\n\t * @returns The total count of entities in the storage.\n\t */\n\tpublic async count(): Promise<number> {\n\t\ttry {\n\t\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\t\tconst partitionKey = ContextIdHelper.combinedContextKey(\n\t\t\t\tcontextIds,\n\t\t\t\tthis._partitionContextIds\n\t\t\t);\n\n\t\t\tconst querySpec: SqlQuerySpec = {\n\t\t\t\tquery: \"SELECT VALUE COUNT(1) FROM c WHERE c.partitionId = @partitionId\",\n\t\t\t\tparameters: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"@partitionId\",\n\t\t\t\t\t\tvalue: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t};\n\t\t\tconst { resources } = await this._container.items.query(querySpec).fetchAll();\n\t\t\treturn resources[0] ?? 0;\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"countFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Create an SQL condition clause.\n\t * @param objectPath The path for the nested object.\n\t * @param condition The conditions to create the query from.\n\t * @param attributeNames The attribute names to use in the query.\n\t * @param attributeValues The attribute values to use in the query.\n\t * @returns The condition clause.\n\t * @internal\n\t */\n\tprivate buildQueryParameters(\n\t\tobjectPath: string,\n\t\tcondition: EntityCondition<T> | undefined,\n\t\tattributeNames: { [id: string]: string },\n\t\tattributeValues: { [id: string]: unknown }\n\t): string {\n\t\t// If no conditions are defined then return empty string\n\t\tif (Is.undefined(condition)) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (\"conditions\" in condition) {\n\t\t\tif (condition.conditions.length === 0) {\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t\t// It's a group of comparisons, so check the individual items and combine with the logical operator\n\t\t\tconst joinConditions: string[] = condition.conditions.map(c =>\n\t\t\t\tthis.buildQueryParameters(objectPath, c, attributeNames, attributeValues)\n\t\t\t);\n\n\t\t\tconst logicalOperator = this.mapConditionalOperator(condition.logicalOperator);\n\t\t\tconst queryClause = joinConditions\n\t\t\t\t.filter(j => j.length > 0)\n\t\t\t\t.map(j => j)\n\t\t\t\t.join(` ${logicalOperator} `);\n\n\t\t\treturn Is.stringValue(queryClause) ? ` (${queryClause}) ` : \"\";\n\t\t}\n\n\t\tconst schemaProp = this._entitySchema.properties?.find(p => p.property === condition.property);\n\n\t\t// It's a single value so just create the property comparison for the condition\n\t\tconst comparison = this.mapComparisonOperator(\n\t\t\tobjectPath,\n\t\t\tcondition,\n\t\t\tschemaProp?.type,\n\t\t\tattributeNames,\n\t\t\tattributeValues\n\t\t);\n\n\t\treturn comparison;\n\t}\n\n\t/**\n\t * Map the framework comparison operators to those in CosmosDB.\n\t * @param objectPath The prefix to use for the condition.\n\t * @param comparator The operator to map.\n\t * @param type The type of the property.\n\t * @param attributeValues The attribute values to use in the query.\n\t * @returns The comparison expression.\n\t * @throws GeneralError if the comparison operator is not supported.\n\t * @internal\n\t */\n\tprivate mapComparisonOperator(\n\t\tobjectPath: string,\n\t\tcomparator: IComparator,\n\t\ttype: EntitySchemaPropertyType | undefined,\n\t\tattributeNames: { [id: string]: string },\n\t\tattributeValues: { [id: string]: unknown }\n\t): string {\n\t\tlet prop = objectPath;\n\t\tif (prop.length > 0) {\n\t\t\tprop += \".\";\n\t\t}\n\t\tprop += comparator.property;\n\n\t\tlet attributeName = this.populateAttributeNames(prop, attributeNames);\n\t\tlet propName = `${attributeName.replace(/\\./g, \"\").replace(/@/g, \"\")}`;\n\n\t\tif (\n\t\t\t(comparator.comparison === ComparisonOperator.Equals ||\n\t\t\t\tcomparator.comparison === ComparisonOperator.NotEquals) &&\n\t\t\t(comparator.value === null || comparator.value === undefined)\n\t\t) {\n\t\t\t// Cosmos DB SQL null semantics mirror standard SQL: any comparison using = or <>\n\t\t\t// against null evaluates to UNKNOWN, not TRUE, so no rows are returned.\n\t\t\t// IS_NULL() and IS_DEFINED() must be used instead (no bound parameter needed).\n\t\t\tif (comparator.comparison === ComparisonOperator.Equals) {\n\t\t\t\treturn `(IS_NULL(c.${attributeName}) OR NOT IS_DEFINED(c.${attributeName}))`;\n\t\t\t}\n\t\t\treturn `(IS_DEFINED(c.${attributeName}) AND NOT IS_NULL(c.${attributeName}))`;\n\t\t} else if (Is.array(comparator.value)) {\n\t\t\tconst dbValues = comparator.value.map(v => this.propertyToDbValue(v, type));\n\t\t\tconst arrAttributeNames = [];\n\t\t\tfor (let i = 0; i < dbValues.length; i++) {\n\t\t\t\tconst arrAttributeName = `${propName}${i}`;\n\t\t\t\tattributeValues[arrAttributeName] = dbValues[i];\n\t\t\t\tarrAttributeNames.push(arrAttributeName);\n\t\t\t}\n\t\t\tpropName = attributeName;\n\t\t\tattributeName = `(${arrAttributeNames.map(name => `@${name}`).join(\", \")})`;\n\t\t} else {\n\t\t\tattributeValues[propName] = comparator.value;\n\t\t}\n\n\t\tconst matches = attributeName.split(\".\").length;\n\t\tif (matches && comparator.comparison === ComparisonOperator.Equals) {\n\t\t\tattributeName = attributeName\n\t\t\t\t.split(\".\")\n\t\t\t\t.map(part => `[\"${part}\"]`)\n\t\t\t\t.join(\"\");\n\t\t\treturn `c${attributeName} = @${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.Equals) {\n\t\t\treturn `c.${attributeName} = @${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.NotEquals) {\n\t\t\treturn `c.${attributeName} <> @${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.GreaterThan) {\n\t\t\treturn `c.${attributeName} > @${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.LessThan) {\n\t\t\treturn `c.${attributeName} < @${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.GreaterThanOrEqual) {\n\t\t\treturn `c.${attributeName} >= @${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.LessThanOrEqual) {\n\t\t\treturn `c.${attributeName} <= @${propName}`;\n\t\t} else if (\n\t\t\ttypeof attributeValues[propName] === \"object\" &&\n\t\t\tcomparator.comparison === ComparisonOperator.Includes\n\t\t) {\n\t\t\treturn `array_contains(c.${attributeName}, @${propName})`;\n\t\t} else if (comparator.comparison === ComparisonOperator.Includes) {\n\t\t\treturn `contains(c.${attributeName}, @${propName})`;\n\t\t} else if (comparator.comparison === ComparisonOperator.NotIncludes) {\n\t\t\treturn `notContains(c.${attributeName}, @${propName})`;\n\t\t} else if (comparator.comparison === ComparisonOperator.In) {\n\t\t\treturn `c.${propName} IN ${attributeName}`;\n\t\t}\n\n\t\tthrow new GeneralError(CosmosDbEntityStorageConnector.CLASS_NAME, \"comparisonNotSupported\", {\n\t\t\tcomparison: comparator.comparison\n\t\t});\n\t}\n\n\t/**\n\t * Format a value to insert into DB.\n\t * @param value The value to format.\n\t * @param type The type for the property.\n\t * @returns The value after conversion.\n\t * @internal\n\t */\n\tprivate propertyToDbValue(value: unknown, type?: EntitySchemaPropertyType): unknown {\n\t\tif (Is.object(value)) {\n\t\t\tconst map: { [id: string]: unknown } = {};\n\t\t\tfor (const key in value) {\n\t\t\t\tmap[key] = this.propertyToDbValue(value[key]);\n\t\t\t}\n\t\t\treturn map;\n\t\t}\n\n\t\tif (type === \"string\") {\n\t\t\treturn `${Coerce.string(value)}`;\n\t\t} else if (type === \"integer\" || type === \"number\") {\n\t\t\treturn Coerce.string(value) ?? \"\";\n\t\t} else if (type === \"boolean\") {\n\t\t\treturn Coerce.boolean(value) ?? false;\n\t\t}\n\n\t\treturn Coerce.string(value) ?? \"\";\n\t}\n\n\t/**\n\t * Create a unique name for the attribute.\n\t * @param name The name to create a unique name for.\n\t * @param attributeNames The attribute names to use in the query.\n\t * @returns The unique name.\n\t * @internal\n\t */\n\tprivate populateAttributeNames(name: string, attributeNames: { [id: string]: string }): string {\n\t\tconst parts = name.split(\".\");\n\t\tconst attributeNameParts: string[] = [];\n\n\t\tfor (const part of parts) {\n\t\t\tconst hashPart = `${part}`;\n\t\t\tif (Is.empty(attributeNames[hashPart])) {\n\t\t\t\tattributeNames[hashPart] = part;\n\t\t\t}\n\t\t\tattributeNameParts.push(hashPart);\n\t\t}\n\n\t\treturn attributeNameParts.join(\".\");\n\t}\n\n\t/**\n\t * Map the framework conditional operators to those in CosmosDB.\n\t * @param operator The operator to map.\n\t * @returns The conditional operator.\n\t * @throws GeneralError if the conditional operator is not supported.\n\t * @internal\n\t */\n\tprivate mapConditionalOperator(operator?: LogicalOperator): string {\n\t\tif ((operator ?? LogicalOperator.And) === LogicalOperator.And) {\n\t\t\treturn \"AND\";\n\t\t} else if (operator === LogicalOperator.Or) {\n\t\t\treturn \"OR\";\n\t\t}\n\n\t\tthrow new GeneralError(CosmosDbEntityStorageConnector.CLASS_NAME, \"conditionalNotSupported\", {\n\t\t\toperator\n\t\t});\n\t}\n\n\t/**\n\t * Verify the conditions for the entity.\n\t * @param conditions The conditions to verify.\n\t * @internal\n\t */\n\tprivate verifyConditions(\n\t\tconditions: { property: keyof T; value: unknown }[],\n\t\tobj: { [key in keyof T]: unknown }\n\t): boolean {\n\t\treturn conditions.every(\n\t\t\tcondition => ObjectHelper.propertyGet(obj, condition.property as string) === condition.value\n\t\t);\n\t}\n\n\t/**\n\t * Convert an entity to an item.\n\t * @param item The item to convert.\n\t * @returns The entity.\n\t * @internal\n\t */\n\tprivate itemToEntity(item: (ItemDefinition & Resource) | undefined): T {\n\t\tObjectHelper.propertyDelete(item, \"partitionId\");\n\t\tObjectHelper.propertyDelete(item, \"_attachments\");\n\t\tObjectHelper.propertyDelete(item, \"_etag\");\n\t\tObjectHelper.propertyDelete(item, \"_rid\");\n\t\tObjectHelper.propertyDelete(item, \"_self\");\n\t\tObjectHelper.propertyDelete(item, \"_ts\");\n\t\treturn item as T;\n\t}\n\n\t/**\n\t * Check if the database exists.\n\t * @returns True if the database exists, false otherwise.\n\t * @internal\n\t */\n\tprivate async databaseExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst { resources: databaseList } = await this._client.databases.readAll().fetchAll();\n\n\t\t\treturn databaseList.some((db: Resource) => db.id === this._config.databaseId);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a database to exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForDatabaseExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst databaseExists = await this.databaseExists();\n\t\t\tif (databaseExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Check if the container exists.\n\t * @returns True if the container exists, false otherwise.\n\t * @internal\n\t */\n\tprivate async containerExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst { resources: containers } = await this._client\n\t\t\t\t.database(this._config.databaseId)\n\t\t\t\t.containers.readAll()\n\t\t\t\t.fetchAll();\n\n\t\t\treturn containers.some((c: Resource) => c.id === this._config.containerId);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a container to exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForContainerExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst containerExists = await this.containerExists();\n\t\t\tif (containerExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cosmosDbEntityStorageConnector.js","sourceRoot":"","sources":["../../src/cosmosDbEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\tBulkOperationType,\n\ttype Container,\n\tCosmosClient,\n\ttype FeedOptions,\n\ttype ItemDefinition,\n\ttype JSONValue,\n\ttype OperationInput,\n\tPartitionKeyKind,\n\ttype Resource,\n\ttype SqlParameter,\n\ttype SqlQuerySpec\n} from \"@azure/cosmos\";\nimport { ContextIdHelper, ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tCoerce,\n\tComponentFactory,\n\tGeneralError,\n\tGuards,\n\tHealthStatus,\n\ttype IHealth,\n\tIs,\n\tObjectHelper\n} from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\ttype EntitySchemaPropertyType,\n\ttype IComparator,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tLogicalOperator,\n\tSortDirection\n} from \"@twin.org/entity\";\nimport {\n\tEntityHelper,\n\ttype IEntityStorageConnector,\n\ttype IEntityStorageMigrationConnector,\n\ttype IMigrationOptions\n} from \"@twin.org/entity-storage-models\";\nimport type { ILoggingComponent } from \"@twin.org/logging-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport type { ICosmosDbEntityStorageConnectorConfig } from \"./models/ICosmosDbEntityStorageConnectorConfig.js\";\nimport type { ICosmosDbEntityStorageConnectorConstructorOptions } from \"./models/ICosmosDbEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations using Cosmos DB.\n */\nexport class CosmosDbEntityStorageConnector<\n\tT = unknown\n> implements IEntityStorageMigrationConnector<T> {\n\t/**\n\t * Runtime name for the class.\n\t */\n\tpublic static readonly CLASS_NAME: string = nameof<CosmosDbEntityStorageConnector>();\n\n\t/**\n\t * Limit the number of entities when finding.\n\t * @internal\n\t */\n\tprivate static readonly _DEFAULT_LIMIT: number = 40;\n\n\t/**\n\t * Partition id field name.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY: string = \"partitionId\";\n\n\t/**\n\t * Partition id field value.\n\t * @internal\n\t */\n\tprivate static readonly _PARTITION_KEY_VALUE: string = \"root\";\n\n\t/**\n\t * The name for the schema.\n\t * @internal\n\t */\n\tprivate readonly _entitySchemaName: string;\n\n\t/**\n\t * The schema for the entity.\n\t * @internal\n\t */\n\tprivate readonly _entitySchema: IEntitySchema<T>;\n\n\t/**\n\t * The keys to use from the context ids to create partitions.\n\t * @internal\n\t */\n\tprivate readonly _partitionContextIds?: string[];\n\n\t/**\n\t * The primary key.\n\t * @internal\n\t */\n\tprivate readonly _primaryKey: IEntitySchemaProperty<T>;\n\n\t/**\n\t * The configuration for the connector.\n\t * @internal\n\t */\n\tprivate readonly _config: ICosmosDbEntityStorageConnectorConfig;\n\n\t/**\n\t * The Cosmos DB client.\n\t * @internal\n\t */\n\tprivate readonly _client: CosmosClient;\n\n\t/**\n\t * Container user for the data storage.\n\t * @internal\n\t */\n\tprivate readonly _container: Container;\n\n\t/**\n\t * Create a new instance of CosmosDbEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: ICosmosDbEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(CosmosDbEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<ICosmosDbEntityStorageConnectorConfig>(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.endpoint),\n\t\t\toptions.config.endpoint\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.key),\n\t\t\toptions.config.key\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.databaseId),\n\t\t\toptions.config.databaseId\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.containerId),\n\t\t\toptions.config.containerId\n\t\t);\n\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._entitySchemaName = options.entitySchema;\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\n\t\tthis._primaryKey = EntitySchemaHelper.getPrimaryKey<T>(this._entitySchema);\n\n\t\tthis._config = options.config;\n\n\t\tthis._client = new CosmosClient({\n\t\t\tendpoint: this._config.endpoint,\n\t\t\tkey: this._config.key\n\t\t});\n\n\t\tthis._container = this._client\n\t\t\t.database(this._config.databaseId)\n\t\t\t.container(this._config.containerId);\n\t}\n\n\t/**\n\t * Initialize the Cosmos DB environment.\n\t * @param nodeLoggingComponentType Optional type of the logging component.\n\t * @returns A promise that resolves to a boolean indicating success.\n\t */\n\tpublic async bootstrap(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\t// Create the database if it does not exist\n\t\ttry {\n\t\t\tconst databaseExists = await this.databaseExists();\n\n\t\t\tif (databaseExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"databaseExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdatabaseId: this._config.databaseId\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"databaseCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tdatabaseId: this._config.databaseId\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tawait this._client.databases.create({\n\t\t\t\t\tid: this._config.databaseId\n\t\t\t\t});\n\n\t\t\t\tawait this.waitForDatabaseExists();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"databaseCreateFailed\",\n\t\t\t\terror: BaseError.fromError(error),\n\t\t\t\tdata: {\n\t\t\t\t\tdatabaseId: this._config.databaseId\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\n\t\t// Create the container if it does not exist\n\t\ttry {\n\t\t\tconst containerExists = await this.containerExists();\n\n\t\t\tif (containerExists) {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"containerExists\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcontainerId: this._config.containerId\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"containerCreating\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcontainerId: this._config.containerId\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tawait this._client.database(this._config.databaseId).containers.create(\n\t\t\t\t\t{\n\t\t\t\t\t\tid: this._config.containerId,\n\t\t\t\t\t\tpartitionKey: {\n\t\t\t\t\t\t\tkind: PartitionKeyKind.Hash,\n\t\t\t\t\t\t\tpaths: [`/${CosmosDbEntityStorageConnector._PARTITION_KEY}`]\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{ offerThroughput: this._config.offerThroughput }\n\t\t\t\t);\n\n\t\t\t\tawait this.waitForContainerExists();\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"containerCreateFailed\",\n\t\t\t\terror: BaseError.fromError(error),\n\t\t\t\tdata: {\n\t\t\t\t\tcontainerId: this._config.containerId\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Returns the class name of the component.\n\t * @returns The class name of the component.\n\t */\n\tpublic className(): string {\n\t\treturn CosmosDbEntityStorageConnector.CLASS_NAME;\n\t}\n\n\t/**\n\t * Returns the health status of the component.\n\t * @returns The health status of the component.\n\t */\n\tpublic async health(): Promise<IHealth[]> {\n\t\ttry {\n\t\t\tawait this._client\n\t\t\t\t.database(this._config.databaseId)\n\t\t\t\t.container(this._config.containerId)\n\t\t\t\t.read();\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tdata: { databaseId: this._config.databaseId, containerId: this._config.containerId }\n\t\t\t\t}\n\t\t\t];\n\t\t} catch {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Error,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tmessage: \"connectionFailed\",\n\t\t\t\t\tdata: { databaseId: this._config.databaseId, containerId: this._config.containerId }\n\t\t\t\t}\n\t\t\t];\n\t\t}\n\t}\n\n\t/**\n\t * Get the schema for the entities.\n\t * @returns The schema for the entities.\n\t */\n\tpublic getSchema(): IEntitySchema {\n\t\treturn this._entitySchema as IEntitySchema;\n\t}\n\n\t/**\n\t * Get an entity from Cosmos DB.\n\t * @param id The id of the entity to get, or the index value if secondaryIndex is set.\n\t * @param secondaryIndex Get the item using a secondary index.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The object if it can be found or undefined.\n\t */\n\tpublic async get(\n\t\tid: string,\n\t\tsecondaryIndex?: keyof T,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<T | undefined> {\n\t\tGuards.stringValue(CosmosDbEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\t// No secondary index or conditions\n\t\t\tif (Is.empty(secondaryIndex) && !Is.arrayValue(conditions)) {\n\t\t\t\tconst { resource: item } = await this._container\n\t\t\t\t\t.item(id, partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE)\n\t\t\t\t\t.read<ItemDefinition>();\n\t\t\t\treturn this.itemToEntity(item);\n\t\t\t}\n\n\t\t\tconst conditionValues: SqlParameter[] = [];\n\n\t\t\tconst whereQuery: string[] = [\n\t\t\t\t`c.${CosmosDbEntityStorageConnector._PARTITION_KEY} = @partitionKey`\n\t\t\t];\n\t\t\tconditionValues.push({\n\t\t\t\tname: \"@partitionKey\",\n\t\t\t\tvalue: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t});\n\n\t\t\t// With a secondary index\n\t\t\tif (Is.stringValue(secondaryIndex)) {\n\t\t\t\tconst secIndex = secondaryIndex.toString();\n\t\t\t\twhereQuery.push(`c.${secIndex} = @id`);\n\t\t\t} else {\n\t\t\t\twhereQuery.push(`c.${this._primaryKey.property as string} = @id`);\n\t\t\t}\n\t\t\tconditionValues.push({ name: \"@id\", value: id });\n\n\t\t\t// With conditions\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tfor (const c of conditions) {\n\t\t\t\t\twhereQuery.push(`c.${c.property as string} = @${c.property as string}`);\n\t\t\t\t\tconditionValues.push({\n\t\t\t\t\t\tname: `@${c.property as string}`,\n\t\t\t\t\t\tvalue: c.value as JSONValue\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst query: SqlQuerySpec = {\n\t\t\t\tquery: `SELECT * FROM c WHERE ${whereQuery.join(\" AND \")}`,\n\t\t\t\tparameters: conditionValues\n\t\t\t};\n\n\t\t\tconst { resources: items } = await this._container.items.query(query).fetchAll();\n\n\t\t\tif (items.length === 1) {\n\t\t\t\treturn this.itemToEntity(items[0]);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorCode(err, \"NotFound\")) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"containerDoesNotExist\",\n\t\t\t\t\t{\n\t\t\t\t\t\tcontainerId: this._config.containerId\n\t\t\t\t\t},\n\t\t\t\t\terr\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"getFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Set an entity.\n\t * @param entity The entity to set.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The id of the entity.\n\t */\n\tpublic async set(entity: T, conditions?: { property: keyof T; value: unknown }[]): Promise<void> {\n\t\tGuards.object<T>(CosmosDbEntityStorageConnector.CLASS_NAME, nameof(entity), entity);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tEntitySchemaHelper.validateEntity(entity, this.getSchema());\n\n\t\tconst id = entity[this._primaryKey.property] as string;\n\n\t\ttry {\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tconst item = this._container.item(\n\t\t\t\t\tid,\n\t\t\t\t\tpartitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t);\n\t\t\t\tconst { resource: itemData } = await item.read<ItemDefinition>();\n\t\t\t\tif (Is.notEmpty(itemData) && !this.verifyConditions(conditions, itemData as T)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait this._container.items.upsert({\n\t\t\t\tid,\n\t\t\t\t[CosmosDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\tpartitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\t...entity\n\t\t\t});\n\t\t} catch (err) {\n\t\t\tif (BaseError.isAggregateError(err)) {\n\t\t\t\tconst errors = BaseError.fromAggregate(err);\n\t\t\t\tif (BaseError.someErrorCode(errors, \"ResourceNotFoundException\")) {\n\t\t\t\t\tthrow new GeneralError(\n\t\t\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\t\"containerDoesNotExist\",\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tcontainerId: this._config.containerId\n\t\t\t\t\t\t},\n\t\t\t\t\t\terr\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Set multiple entities in a batch.\n\t * @param entities The entities to set.\n\t * @returns Nothing.\n\t */\n\tpublic async setBatch(entities: T[]): Promise<void> {\n\t\tGuards.arrayValue(CosmosDbEntityStorageConnector.CLASS_NAME, nameof(entities), entities);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tfor (const entity of entities) {\n\t\t\tEntitySchemaHelper.validateEntity(entity, this.getSchema());\n\t\t}\n\n\t\ttry {\n\t\t\tawait this._container.items.executeBulkOperations(\n\t\t\t\tentities.map(\n\t\t\t\t\tentity =>\n\t\t\t\t\t\t({\n\t\t\t\t\t\t\toperationType: BulkOperationType.Upsert,\n\t\t\t\t\t\t\tpartitionKey: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\t\t\t\tresourceBody: {\n\t\t\t\t\t\t\t\tid: entity[this._primaryKey.property] as string,\n\t\t\t\t\t\t\t\t[CosmosDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\t\t\t\tpartitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\t\t\t\t\t...(entity as { [key: string]: unknown })\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}) as OperationInput\n\t\t\t\t)\n\t\t\t);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"setBatchFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Empty all entities from the storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\t\tconst pk = partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE;\n\n\t\ttry {\n\t\t\tlet continuationToken: string | undefined;\n\t\t\tdo {\n\t\t\t\tconst feedOptions: FeedOptions = { maxItemCount: 100, continuationToken };\n\t\t\t\tconst { resources, continuationToken: nextToken } = await this._container.items\n\t\t\t\t\t.query<{ id: string }>(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tquery: `SELECT c.id FROM c WHERE c.${CosmosDbEntityStorageConnector._PARTITION_KEY} = @pk`,\n\t\t\t\t\t\t\tparameters: [{ name: \"@pk\", value: pk }]\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfeedOptions\n\t\t\t\t\t)\n\t\t\t\t\t.fetchNext();\n\n\t\t\t\tcontinuationToken = nextToken;\n\n\t\t\t\tif (Is.arrayValue(resources)) {\n\t\t\t\t\tconst operations: OperationInput[] = resources.map(r => ({\n\t\t\t\t\t\toperationType: BulkOperationType.Delete,\n\t\t\t\t\t\tid: r.id,\n\t\t\t\t\t\tpartitionKey: pk\n\t\t\t\t\t}));\n\t\t\t\t\tawait this._container.items.executeBulkOperations(operations);\n\t\t\t\t}\n\t\t\t} while (Is.stringValue(continuationToken));\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"emptyFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Remove the entity.\n\t * @param id The id of the entity to remove.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns Nothing.\n\t */\n\tpublic async remove(\n\t\tid: string,\n\t\tconditions?: { property: keyof T; value: unknown }[]\n\t): Promise<void> {\n\t\tGuards.stringValue(CosmosDbEntityStorageConnector.CLASS_NAME, nameof(id), id);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst item = this._container.item(\n\t\t\t\tid,\n\t\t\t\tpartitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t);\n\t\t\tconst { resource: itemData } = await item.read<ItemDefinition>();\n\t\t\tif (Is.notEmpty(itemData)) {\n\t\t\t\tif (Is.arrayValue(conditions) && !this.verifyConditions(conditions, itemData as T)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tawait item.delete();\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (\n\t\t\t\tBaseError.fromError(err) &&\n\t\t\t\tIs.object<{ body?: { code?: string } }>(err) &&\n\t\t\t\terr.body?.code === \"NotFound\"\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeFailed\",\n\t\t\t\t{\n\t\t\t\t\tid\n\t\t\t\t},\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Remove multiple entities by id.\n\t * @param ids The ids of the entities to remove.\n\t * @returns Nothing.\n\t */\n\tpublic async removeBatch(ids: string[]): Promise<void> {\n\t\tGuards.arrayValue(CosmosDbEntityStorageConnector.CLASS_NAME, nameof(ids), ids);\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst operations: OperationInput[] = ids.map(id => ({\n\t\t\t\toperationType: BulkOperationType.Delete,\n\t\t\t\tid,\n\t\t\t\tpartitionKey: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t}));\n\n\t\t\tawait this._container.items.executeBulkOperations(operations);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"removeBatchFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Teardown the storage by deleting the underlying container.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the teardown process was successful.\n\t */\n\tpublic async teardown(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tawait nodeLogging?.log({\n\t\t\tlevel: \"info\",\n\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"containerDeleting\",\n\t\t\tdata: { containerId: this._config.containerId }\n\t\t});\n\n\t\ttry {\n\t\t\tif (await this.containerExists()) {\n\t\t\t\tawait this._container.delete();\n\t\t\t\tawait this.waitForContainerNotExists();\n\t\t\t}\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"containerDeleted\",\n\t\t\t\tdata: { containerId: this._config.containerId }\n\t\t\t});\n\n\t\t\treturn true;\n\t\t} catch (err) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"error\",\n\t\t\t\tsource: CosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"teardownFailed\",\n\t\t\t\terror: BaseError.fromError(err)\n\t\t\t});\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Find all the entities which match the conditions.\n\t * @param conditions The conditions to match for the entities.\n\t * @param sortProperties The optional sort order.\n\t * @param properties The optional properties to return, defaults to all.\n\t * @param cursor The cursor to request the next chunk of entities.\n\t * @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.\n\t * @returns All the entities for the storage matching the conditions,\n\t * and a cursor which can be used to request more entities.\n\t */\n\tpublic async query(\n\t\tconditions?: EntityCondition<T>,\n\t\tsortProperties?: { property: keyof T; sortDirection: SortDirection }[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{ entities: Partial<T>[]; cursor?: string }> {\n\t\tlet sql = \"\";\n\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\ttry {\n\t\t\tconst returnSize = limit ?? CosmosDbEntityStorageConnector._DEFAULT_LIMIT;\n\n\t\t\tlet orderByClause: string = \"\";\n\t\t\tif (Array.isArray(sortProperties)) {\n\t\t\t\tif (sortProperties.length > 1) {\n\t\t\t\t\tthrow new GeneralError(CosmosDbEntityStorageConnector.CLASS_NAME, \"sortSingle\");\n\t\t\t\t}\n\t\t\t\tfor (const sortProperty of sortProperties) {\n\t\t\t\t\tconst propertySchema = this._entitySchema.properties?.find(\n\t\t\t\t\t\te => e.property === sortProperty.property\n\t\t\t\t\t);\n\t\t\t\t\tif (\n\t\t\t\t\t\t!propertySchema ||\n\t\t\t\t\t\t(!propertySchema.isPrimary &&\n\t\t\t\t\t\t\t!propertySchema.isSecondary &&\n\t\t\t\t\t\t\t!propertySchema.sortDirection)\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new GeneralError(CosmosDbEntityStorageConnector.CLASS_NAME, \"sortNotIndexed\", {\n\t\t\t\t\t\t\tproperty: sortProperty.property\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tconst direction = sortProperty.sortDirection === SortDirection.Ascending ? \"asc\" : \"desc\";\n\t\t\t\t\torderByClause = `ORDER BY c.${String(sortProperty.property)} ${direction}`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst attributeNames: { [id: string]: string } = {};\n\t\t\tconst attributeValues: { [id: string]: unknown } = {};\n\t\t\tlet queryClause = this.buildQueryParameters(\"\", conditions, attributeNames, attributeValues);\n\n\t\t\tif (queryClause.length > 0) {\n\t\t\t\tqueryClause = ` AND ${queryClause}`;\n\t\t\t}\n\n\t\t\tsql = `SELECT ${properties ? properties.map(p => `c.${p as string}`).join(\", \") : \"*\"} FROM c WHERE c.${CosmosDbEntityStorageConnector._PARTITION_KEY} = @partitionId ${queryClause} ${orderByClause}`;\n\t\t\tconst querySpecs: SqlQuerySpec = {\n\t\t\t\tquery: sql,\n\t\t\t\tparameters: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"@partitionId\",\n\t\t\t\t\t\tvalue: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t},\n\t\t\t\t\t...Object.keys(attributeValues).map(\n\t\t\t\t\t\tkey => ({ name: `@${key}`, value: attributeValues[key] }) as SqlParameter\n\t\t\t\t\t)\n\t\t\t\t]\n\t\t\t};\n\n\t\t\tconst feedOptions: FeedOptions = {\n\t\t\t\tmaxItemCount: returnSize,\n\t\t\t\tcontinuationToken: cursor\n\t\t\t};\n\n\t\t\tconst feedResponse = await this._container.items.query(querySpecs, feedOptions).fetchNext();\n\n\t\t\t// CosmosDB returns a continuation token even on the last page, so peek ahead\n\t\t\t// to confirm there are actually more results before exposing the cursor.\n\t\t\tlet resultCursor: string | undefined;\n\t\t\tif (feedResponse.resources.length >= returnSize && feedResponse.continuationToken) {\n\t\t\t\tconst peekResponse = await this._container.items\n\t\t\t\t\t.query(querySpecs, {\n\t\t\t\t\t\tmaxItemCount: 1,\n\t\t\t\t\t\tcontinuationToken: feedResponse.continuationToken\n\t\t\t\t\t})\n\t\t\t\t\t.fetchNext();\n\t\t\t\tif (peekResponse.resources.length > 0) {\n\t\t\t\t\tresultCursor = feedResponse.continuationToken;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tentities: feedResponse.resources.map(i => this.itemToEntity(i)),\n\t\t\t\tcursor: resultCursor\n\t\t\t};\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"queryFailed\",\n\t\t\t\t{ sql },\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Count all the entities which match the conditions.\n\t * @param conditions The optional conditions to match for the entities.\n\t * @returns The total count of entities in the storage.\n\t */\n\tpublic async count(conditions?: EntityCondition<T>): Promise<number> {\n\t\ttry {\n\t\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\t\tconst partitionKey = ContextIdHelper.combinedContextKey(\n\t\t\t\tcontextIds,\n\t\t\t\tthis._partitionContextIds\n\t\t\t);\n\n\t\t\tconst attributeNames: { [id: string]: string } = {};\n\t\t\tconst attributeValues: { [id: string]: unknown } = {};\n\t\t\tlet queryClause = Is.empty(conditions)\n\t\t\t\t? \"\"\n\t\t\t\t: this.buildQueryParameters(\"\", conditions, attributeNames, attributeValues);\n\n\t\t\tif (queryClause.length > 0) {\n\t\t\t\tqueryClause = ` AND ${queryClause}`;\n\t\t\t}\n\n\t\t\tconst querySpec: SqlQuerySpec = {\n\t\t\t\tquery: `SELECT VALUE COUNT(1) FROM c WHERE c.${CosmosDbEntityStorageConnector._PARTITION_KEY} = @partitionId${queryClause}`,\n\t\t\t\tparameters: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"@partitionId\",\n\t\t\t\t\t\tvalue: partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t},\n\t\t\t\t\t...Object.keys(attributeValues).map(\n\t\t\t\t\t\tkey => ({ name: `@${key}`, value: attributeValues[key] }) as SqlParameter\n\t\t\t\t\t)\n\t\t\t\t]\n\t\t\t};\n\t\t\tconst { resources } = await this._container.items.query(querySpec).fetchAll();\n\t\t\treturn resources[0] ?? 0;\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"countFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Get a unique list of all the context ids from the storage.\n\t * @returns The list of unique context ids.\n\t */\n\tpublic async getPartitionContextIds(): Promise<IContextIds[]> {\n\t\tconst partitionContextIds = this._partitionContextIds;\n\t\tif (!Is.arrayValue(partitionContextIds)) {\n\t\t\treturn [];\n\t\t}\n\t\ttry {\n\t\t\tconst { resources: partitionIds } = await this._container.items\n\t\t\t\t.query<string>({\n\t\t\t\t\tquery: `SELECT DISTINCT VALUE c.${CosmosDbEntityStorageConnector._PARTITION_KEY} FROM c`\n\t\t\t\t})\n\t\t\t\t.fetchAll();\n\t\t\treturn partitionIds\n\t\t\t\t.filter(id => Is.stringValue(id))\n\t\t\t\t.map(id => ContextIdHelper.shortSplit(partitionContextIds, id));\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"getPartitionContextIdsFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Create the target connector for performing the migration using a temporary container.\n\t * @param newEntitySchema The name of the new entity schema to create the connector for.\n\t * @returns Connector for performing the migration.\n\t */\n\tpublic async createTargetConnector<U>(\n\t\tnewEntitySchema: string\n\t): Promise<IEntityStorageConnector<U>> {\n\t\tconst migrationContainerId = `${this._config.containerId}Migration${Date.now()}`;\n\t\treturn new CosmosDbEntityStorageConnector<U>({\n\t\t\tentitySchema: newEntitySchema,\n\t\t\tconfig: { ...this._config, containerId: migrationContainerId },\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\t}\n\n\t/**\n\t * Finalize the migration by tearing down the old container and replacing it with the target container.\n\t * @param targetConnector The target connector to finalize the migration with.\n\t * @param options The options to control how the migration is finalized.\n\t * @param loggingComponentType The optional component type to use for logging.\n\t * @returns The final connector pointing at the original container id.\n\t */\n\tpublic async finalizeMigration<U>(\n\t\ttargetConnector: CosmosDbEntityStorageConnector<U>,\n\t\toptions?: IMigrationOptions<T, U>,\n\t\tloggingComponentType?: string\n\t): Promise<CosmosDbEntityStorageConnector<U>> {\n\t\t// There is no rename operation in DynamoDB so we have to create a new table with the original name and copy the data over\n\n\t\t// Teardown the existing table with the original name to free up the name for the new table\n\t\tawait this.teardown(loggingComponentType);\n\n\t\t// Create a new connector with the original table name but with the new schema\n\t\t// and copy the data from the migration table to the new table using batch operations\n\t\tconst finalConnector = new CosmosDbEntityStorageConnector<U>({\n\t\t\tentitySchema: targetConnector._entitySchemaName,\n\t\t\tconfig: this._config,\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\t\tif (await finalConnector.bootstrap(loggingComponentType)) {\n\t\t\t// Since there is no rename, we need to copy the data from the migration table to the new table\n\t\t\tconst partitions = await targetConnector.getPartitionContextIds();\n\t\t\tconst batchSize = options?.batchSize ?? CosmosDbEntityStorageConnector._DEFAULT_LIMIT;\n\t\t\tawait this.bulkCopy(targetConnector, finalConnector, partitions, batchSize);\n\n\t\t\tawait targetConnector.teardown(loggingComponentType);\n\n\t\t\treturn finalConnector;\n\t\t}\n\n\t\tthrow new GeneralError(\n\t\t\tCosmosDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\"finalizeMigrationFailedBootstrap\"\n\t\t);\n\t}\n\n\t/**\n\t * Cleanup the migration if a migration fails or needs to be aborted.\n\t * @param targetConnector The target connector to cleanup.\n\t * @param options The options to control how the migration is cleaned up.\n\t * @param loggingComponentType The optional component type to use for logging.\n\t */\n\tpublic async cleanupMigration<U>(\n\t\ttargetConnector: IEntityStorageConnector<U> | undefined,\n\t\toptions?: IMigrationOptions<T, U>,\n\t\tloggingComponentType?: string\n\t): Promise<void> {\n\t\t// If something failed the only thing to cleanup is the migration table\n\t\tawait targetConnector?.teardown?.(loggingComponentType);\n\t}\n\n\t/**\n\t * Copy all entities from sourceConnector to destConnector, paging through each partition.\n\t * @param sourceConnector The connector to read entities from.\n\t * @param destConnector The connector to write entities to.\n\t * @param partitions The partition list returned by getPartitionContextIds.\n\t * @param batchSize The number of entities to read per page.\n\t * @internal\n\t */\n\tprivate async bulkCopy<U>(\n\t\tsourceConnector: CosmosDbEntityStorageConnector<U>,\n\t\tdestConnector: CosmosDbEntityStorageConnector<U>,\n\t\tpartitions: IContextIds[],\n\t\tbatchSize: number\n\t): Promise<void> {\n\t\tlet partitionList: IContextIds[];\n\t\tif (Is.arrayValue(partitions)) {\n\t\t\tpartitionList = partitions;\n\t\t} else if (Is.arrayValue(sourceConnector._partitionContextIds)) {\n\t\t\tpartitionList = [];\n\t\t} else {\n\t\t\tpartitionList = [{}];\n\t\t}\n\n\t\tfor (let i = 0; i < partitionList.length; i++) {\n\t\t\tconst partitionKey =\n\t\t\t\tContextIdHelper.combinedContextKey(\n\t\t\t\t\tpartitionList[i],\n\t\t\t\t\tsourceConnector._partitionContextIds\n\t\t\t\t) ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE;\n\n\t\t\tlet continuationToken: string | undefined;\n\t\t\tdo {\n\t\t\t\tconst feedOptions: FeedOptions = { maxItemCount: batchSize, continuationToken };\n\t\t\t\tconst { resources, continuationToken: nextToken } = await sourceConnector._container.items\n\t\t\t\t\t.query<ItemDefinition & Resource>(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tquery: `SELECT * FROM c WHERE c.${CosmosDbEntityStorageConnector._PARTITION_KEY} = @partitionId`,\n\t\t\t\t\t\t\tparameters: [{ name: \"@partitionId\", value: partitionKey }]\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfeedOptions\n\t\t\t\t\t)\n\t\t\t\t\t.fetchNext();\n\n\t\t\t\tcontinuationToken = nextToken;\n\n\t\t\t\tif (Is.arrayValue(resources)) {\n\t\t\t\t\tconst operations: OperationInput[] = resources.map(\n\t\t\t\t\t\t({ _rid, _self, _ts, _etag, _attachments, ...rest }) => ({\n\t\t\t\t\t\t\toperationType: BulkOperationType.Upsert,\n\t\t\t\t\t\t\tpartitionKey,\n\t\t\t\t\t\t\tresourceBody: rest\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\tawait destConnector._container.items.executeBulkOperations(operations);\n\t\t\t\t}\n\t\t\t} while (Is.stringValue(continuationToken));\n\t\t}\n\t}\n\n\t/**\n\t * Create an SQL condition clause.\n\t * @param objectPath The path for the nested object.\n\t * @param condition The conditions to create the query from.\n\t * @param attributeNames The attribute names to use in the query.\n\t * @param attributeValues The attribute values to use in the query.\n\t * @returns The condition clause.\n\t * @internal\n\t */\n\tprivate buildQueryParameters(\n\t\tobjectPath: string,\n\t\tcondition: EntityCondition<T> | undefined,\n\t\tattributeNames: { [id: string]: string },\n\t\tattributeValues: { [id: string]: unknown }\n\t): string {\n\t\t// If no conditions are defined then return empty string\n\t\tif (Is.undefined(condition)) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tif (\"conditions\" in condition) {\n\t\t\tif (condition.conditions.length === 0) {\n\t\t\t\treturn \"\";\n\t\t\t}\n\t\t\t// It's a group of comparisons, so check the individual items and combine with the logical operator\n\t\t\tconst joinConditions: string[] = condition.conditions.map(c =>\n\t\t\t\tthis.buildQueryParameters(objectPath, c, attributeNames, attributeValues)\n\t\t\t);\n\n\t\t\tconst logicalOperator = this.mapConditionalOperator(condition.logicalOperator);\n\t\t\tconst queryClause = joinConditions\n\t\t\t\t.filter(j => j.length > 0)\n\t\t\t\t.map(j => j)\n\t\t\t\t.join(` ${logicalOperator} `);\n\n\t\t\treturn Is.stringValue(queryClause) ? ` (${queryClause}) ` : \"\";\n\t\t}\n\n\t\tconst schemaProp = this._entitySchema.properties?.find(p => p.property === condition.property);\n\n\t\t// It's a single value so just create the property comparison for the condition\n\t\tconst comparison = this.mapComparisonOperator(\n\t\t\tobjectPath,\n\t\t\tcondition,\n\t\t\tschemaProp?.type,\n\t\t\tattributeNames,\n\t\t\tattributeValues\n\t\t);\n\n\t\treturn comparison;\n\t}\n\n\t/**\n\t * Map the framework comparison operators to those in CosmosDB.\n\t * @param objectPath The prefix to use for the condition.\n\t * @param comparator The operator to map.\n\t * @param type The type of the property.\n\t * @param attributeValues The attribute values to use in the query.\n\t * @returns The comparison expression.\n\t * @throws GeneralError if the comparison operator is not supported.\n\t * @internal\n\t */\n\tprivate mapComparisonOperator(\n\t\tobjectPath: string,\n\t\tcomparator: IComparator,\n\t\ttype: EntitySchemaPropertyType | undefined,\n\t\tattributeNames: { [id: string]: string },\n\t\tattributeValues: { [id: string]: unknown }\n\t): string {\n\t\tlet prop = objectPath;\n\t\tif (prop.length > 0) {\n\t\t\tprop += \".\";\n\t\t}\n\t\tprop += comparator.property;\n\n\t\tlet attributeName = this.populateAttributeNames(prop, attributeNames);\n\t\tlet propName = `${attributeName.replace(/\\./g, \"\").replace(/@/g, \"\")}`;\n\n\t\tif (\n\t\t\t(comparator.comparison === ComparisonOperator.Equals ||\n\t\t\t\tcomparator.comparison === ComparisonOperator.NotEquals) &&\n\t\t\t(comparator.value === null || comparator.value === undefined)\n\t\t) {\n\t\t\t// Cosmos DB SQL null semantics mirror standard SQL: any comparison using = or <>\n\t\t\t// against null evaluates to UNKNOWN, not TRUE, so no rows are returned.\n\t\t\t// IS_NULL() and IS_DEFINED() must be used instead (no bound parameter needed).\n\t\t\tif (comparator.comparison === ComparisonOperator.Equals) {\n\t\t\t\treturn `(IS_NULL(c.${attributeName}) OR NOT IS_DEFINED(c.${attributeName}))`;\n\t\t\t}\n\t\t\treturn `(IS_DEFINED(c.${attributeName}) AND NOT IS_NULL(c.${attributeName}))`;\n\t\t} else if (Is.array(comparator.value)) {\n\t\t\tconst dbValues = comparator.value.map(v => this.propertyToDbValue(v, type));\n\t\t\tconst arrAttributeNames = [];\n\t\t\tfor (let i = 0; i < dbValues.length; i++) {\n\t\t\t\tconst arrAttributeName = `${propName}${i}`;\n\t\t\t\tattributeValues[arrAttributeName] = dbValues[i];\n\t\t\t\tarrAttributeNames.push(arrAttributeName);\n\t\t\t}\n\t\t\tpropName = attributeName;\n\t\t\tattributeName = `(${arrAttributeNames.map(name => `@${name}`).join(\", \")})`;\n\t\t} else if (\n\t\t\tIs.object(comparator.value) &&\n\t\t\t(comparator.comparison === ComparisonOperator.Equals ||\n\t\t\t\tcomparator.comparison === ComparisonOperator.NotEquals)\n\t\t) {\n\t\t\t// CosmosDB SQL does not support object equality with =; expand to per-property comparisons.\n\t\t\tconst op = comparator.comparison === ComparisonOperator.Equals ? \"=\" : \"<>\";\n\t\t\tconst join = comparator.comparison === ComparisonOperator.Equals ? \" AND \" : \" OR \";\n\t\t\tconst clauses: string[] = [];\n\t\t\tfor (const [key, val] of Object.entries(comparator.value)) {\n\t\t\t\tconst paramName = `${propName}${key}`;\n\t\t\t\tattributeValues[paramName] = val;\n\t\t\t\tclauses.push(`c.${attributeName}.${key} ${op} @${paramName}`);\n\t\t\t}\n\t\t\treturn clauses.length === 1 ? clauses[0] : `(${clauses.join(join)})`;\n\t\t} else {\n\t\t\t// Avoid parameter name conflicts by ensuring unique parameter names in the query\n\t\t\tlet counter = 1;\n\t\t\twhile (propName in attributeValues) {\n\t\t\t\tpropName = `${attributeName.replace(/\\./g, \"\").replace(/@/g, \"\")}${counter}`;\n\t\t\t\tcounter++;\n\t\t\t}\n\t\t\tattributeValues[propName] = comparator.value;\n\t\t}\n\n\t\tconst matches = attributeName.split(\".\").length;\n\t\tif (matches && comparator.comparison === ComparisonOperator.Equals) {\n\t\t\tattributeName = attributeName\n\t\t\t\t.split(\".\")\n\t\t\t\t.map(part => `[\"${part}\"]`)\n\t\t\t\t.join(\"\");\n\t\t\treturn `c${attributeName} = @${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.Equals) {\n\t\t\treturn `c.${attributeName} = @${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.NotEquals) {\n\t\t\treturn `c.${attributeName} <> @${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.GreaterThan) {\n\t\t\treturn `c.${attributeName} > @${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.LessThan) {\n\t\t\treturn `c.${attributeName} < @${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.GreaterThanOrEqual) {\n\t\t\treturn `c.${attributeName} >= @${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.LessThanOrEqual) {\n\t\t\treturn `c.${attributeName} <= @${propName}`;\n\t\t} else if (\n\t\t\ttypeof attributeValues[propName] === \"object\" &&\n\t\t\tcomparator.comparison === ComparisonOperator.Includes\n\t\t) {\n\t\t\treturn `ARRAY_CONTAINS(c.${attributeName}, @${propName}, true)`;\n\t\t} else if (comparator.comparison === ComparisonOperator.Includes) {\n\t\t\treturn `CONTAINS(c.${attributeName}, @${propName})`;\n\t\t} else if (comparator.comparison === ComparisonOperator.NotIncludes) {\n\t\t\treturn `NOT CONTAINS(c.${attributeName}, @${propName})`;\n\t\t} else if (comparator.comparison === ComparisonOperator.In) {\n\t\t\treturn `c.${propName} IN ${attributeName}`;\n\t\t}\n\n\t\tthrow new GeneralError(CosmosDbEntityStorageConnector.CLASS_NAME, \"comparisonNotSupported\", {\n\t\t\tcomparison: comparator.comparison\n\t\t});\n\t}\n\n\t/**\n\t * Format a value to insert into DB.\n\t * @param value The value to format.\n\t * @param type The type for the property.\n\t * @returns The value after conversion.\n\t * @internal\n\t */\n\tprivate propertyToDbValue(value: unknown, type?: EntitySchemaPropertyType): unknown {\n\t\tif (Is.object(value)) {\n\t\t\tconst map: { [id: string]: unknown } = {};\n\t\t\tfor (const key in value) {\n\t\t\t\tmap[key] = this.propertyToDbValue(value[key]);\n\t\t\t}\n\t\t\treturn map;\n\t\t}\n\n\t\tif (type === \"string\") {\n\t\t\treturn `${Coerce.string(value)}`;\n\t\t} else if (type === \"integer\" || type === \"number\") {\n\t\t\treturn Coerce.string(value) ?? \"\";\n\t\t} else if (type === \"boolean\") {\n\t\t\treturn Coerce.boolean(value) ?? false;\n\t\t}\n\n\t\treturn Coerce.string(value) ?? \"\";\n\t}\n\n\t/**\n\t * Create a unique name for the attribute.\n\t * @param name The name to create a unique name for.\n\t * @param attributeNames The attribute names to use in the query.\n\t * @returns The unique name.\n\t * @internal\n\t */\n\tprivate populateAttributeNames(name: string, attributeNames: { [id: string]: string }): string {\n\t\tconst parts = name.split(\".\");\n\t\tconst attributeNameParts: string[] = [];\n\n\t\tfor (const part of parts) {\n\t\t\tconst hashPart = `${part}`;\n\t\t\tif (Is.empty(attributeNames[hashPart])) {\n\t\t\t\tattributeNames[hashPart] = part;\n\t\t\t}\n\t\t\tattributeNameParts.push(hashPart);\n\t\t}\n\n\t\treturn attributeNameParts.join(\".\");\n\t}\n\n\t/**\n\t * Map the framework conditional operators to those in CosmosDB.\n\t * @param operator The operator to map.\n\t * @returns The conditional operator.\n\t * @throws GeneralError if the conditional operator is not supported.\n\t * @internal\n\t */\n\tprivate mapConditionalOperator(operator?: LogicalOperator): string {\n\t\tif ((operator ?? LogicalOperator.And) === LogicalOperator.And) {\n\t\t\treturn \"AND\";\n\t\t} else if (operator === LogicalOperator.Or) {\n\t\t\treturn \"OR\";\n\t\t}\n\n\t\tthrow new GeneralError(CosmosDbEntityStorageConnector.CLASS_NAME, \"conditionalNotSupported\", {\n\t\t\toperator\n\t\t});\n\t}\n\n\t/**\n\t * Verify the conditions for the entity.\n\t * @param conditions The conditions to verify.\n\t * @internal\n\t */\n\tprivate verifyConditions(\n\t\tconditions: { property: keyof T; value: unknown }[],\n\t\tobj: { [key in keyof T]: unknown }\n\t): boolean {\n\t\treturn conditions.every(\n\t\t\tcondition => ObjectHelper.propertyGet(obj, condition.property as string) === condition.value\n\t\t);\n\t}\n\n\t/**\n\t * Convert an entity to an item.\n\t * @param item The item to convert.\n\t * @returns The entity.\n\t * @internal\n\t */\n\tprivate itemToEntity(item: (ItemDefinition & Resource) | undefined): T {\n\t\treturn EntityHelper.unPrepareEntity<T>(item as T, [\n\t\t\tCosmosDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\"_attachments\",\n\t\t\t\"_etag\",\n\t\t\t\"_rid\",\n\t\t\t\"_self\",\n\t\t\t\"_ts\"\n\t\t]);\n\t}\n\n\t/**\n\t * Check if the database exists.\n\t * @returns True if the database exists, false otherwise.\n\t * @internal\n\t */\n\tprivate async databaseExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst { resources: databaseList } = await this._client.databases.readAll().fetchAll();\n\n\t\t\treturn databaseList.some((db: Resource) => db.id === this._config.databaseId);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a database to exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForDatabaseExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst databaseExists = await this.databaseExists();\n\t\t\tif (databaseExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Check if the container exists.\n\t * @returns True if the container exists, false otherwise.\n\t * @internal\n\t */\n\tprivate async containerExists(): Promise<boolean> {\n\t\ttry {\n\t\t\tconst { resources: containers } = await this._client\n\t\t\t\t.database(this._config.databaseId)\n\t\t\t\t.containers.readAll()\n\t\t\t\t.fetchAll();\n\n\t\t\treturn containers.some((c: Resource) => c.id === this._config.containerId);\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a container to exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForContainerExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst containerExists = await this.containerExists();\n\t\t\tif (containerExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n\n\t/**\n\t * Wait for a container to not exist.\n\t * @returns Nothing.\n\t * @internal\n\t */\n\tprivate async waitForContainerNotExists(): Promise<void> {\n\t\tfor (let attempt = 0; attempt < 20; attempt++) {\n\t\t\tconst containerExists = await this.containerExists();\n\t\t\tif (!containerExists) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tawait new Promise(resolve => setTimeout(resolve, 250));\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import { type IContextIds } from "@twin.org/context";
|
|
1
2
|
import { type IHealth } from "@twin.org/core";
|
|
2
3
|
import { type EntityCondition, type IEntitySchema, SortDirection } from "@twin.org/entity";
|
|
3
|
-
import type
|
|
4
|
+
import { type IEntityStorageConnector, type IEntityStorageMigrationConnector, type IMigrationOptions } from "@twin.org/entity-storage-models";
|
|
4
5
|
import type { ICosmosDbEntityStorageConnectorConstructorOptions } from "./models/ICosmosDbEntityStorageConnectorConstructorOptions.js";
|
|
5
6
|
/**
|
|
6
7
|
* Class for performing entity storage operations using Cosmos DB.
|
|
7
8
|
*/
|
|
8
|
-
export declare class CosmosDbEntityStorageConnector<T = unknown> implements
|
|
9
|
+
export declare class CosmosDbEntityStorageConnector<T = unknown> implements IEntityStorageMigrationConnector<T> {
|
|
9
10
|
/**
|
|
10
11
|
* Runtime name for the class.
|
|
11
12
|
*/
|
|
@@ -109,7 +110,34 @@ export declare class CosmosDbEntityStorageConnector<T = unknown> implements IEnt
|
|
|
109
110
|
}>;
|
|
110
111
|
/**
|
|
111
112
|
* Count all the entities which match the conditions.
|
|
113
|
+
* @param conditions The optional conditions to match for the entities.
|
|
112
114
|
* @returns The total count of entities in the storage.
|
|
113
115
|
*/
|
|
114
|
-
count(): Promise<number>;
|
|
116
|
+
count(conditions?: EntityCondition<T>): Promise<number>;
|
|
117
|
+
/**
|
|
118
|
+
* Get a unique list of all the context ids from the storage.
|
|
119
|
+
* @returns The list of unique context ids.
|
|
120
|
+
*/
|
|
121
|
+
getPartitionContextIds(): Promise<IContextIds[]>;
|
|
122
|
+
/**
|
|
123
|
+
* Create the target connector for performing the migration using a temporary container.
|
|
124
|
+
* @param newEntitySchema The name of the new entity schema to create the connector for.
|
|
125
|
+
* @returns Connector for performing the migration.
|
|
126
|
+
*/
|
|
127
|
+
createTargetConnector<U>(newEntitySchema: string): Promise<IEntityStorageConnector<U>>;
|
|
128
|
+
/**
|
|
129
|
+
* Finalize the migration by tearing down the old container and replacing it with the target container.
|
|
130
|
+
* @param targetConnector The target connector to finalize the migration with.
|
|
131
|
+
* @param options The options to control how the migration is finalized.
|
|
132
|
+
* @param loggingComponentType The optional component type to use for logging.
|
|
133
|
+
* @returns The final connector pointing at the original container id.
|
|
134
|
+
*/
|
|
135
|
+
finalizeMigration<U>(targetConnector: CosmosDbEntityStorageConnector<U>, options?: IMigrationOptions<T, U>, loggingComponentType?: string): Promise<CosmosDbEntityStorageConnector<U>>;
|
|
136
|
+
/**
|
|
137
|
+
* Cleanup the migration if a migration fails or needs to be aborted.
|
|
138
|
+
* @param targetConnector The target connector to cleanup.
|
|
139
|
+
* @param options The options to control how the migration is cleaned up.
|
|
140
|
+
* @param loggingComponentType The optional component type to use for logging.
|
|
141
|
+
*/
|
|
142
|
+
cleanupMigration<U>(targetConnector: IEntityStorageConnector<U> | undefined, options?: IMigrationOptions<T, U>, loggingComponentType?: string): Promise<void>;
|
|
115
143
|
}
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.3-next.14](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-cosmosdb-v0.0.3-next.13...entity-storage-connector-cosmosdb-v0.0.3-next.14) (2026-05-19)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* adding schema migration functionality to all the connectors ([#85](https://github.com/iotaledger/twin-entity-storage/issues/85)) ([fd1555a](https://github.com/iotaledger/twin-entity-storage/commit/fd1555a34380158214a577586dafae821e72a578))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/entity-storage-models bumped from 0.0.3-next.13 to 0.0.3-next.14
|
|
16
|
+
* devDependencies
|
|
17
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.3-next.13 to 0.0.3-next.14
|
|
18
|
+
|
|
3
19
|
## [0.0.3-next.13](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-cosmosdb-v0.0.3-next.12...entity-storage-connector-cosmosdb-v0.0.3-next.13) (2026-05-13)
|
|
4
20
|
|
|
5
21
|
|
|
@@ -10,7 +10,7 @@ Class for performing entity storage operations using Cosmos DB.
|
|
|
10
10
|
|
|
11
11
|
## Implements
|
|
12
12
|
|
|
13
|
-
- `
|
|
13
|
+
- `IEntityStorageMigrationConnector`\<`T`\>
|
|
14
14
|
|
|
15
15
|
## Constructors
|
|
16
16
|
|
|
@@ -64,7 +64,7 @@ A promise that resolves to a boolean indicating success.
|
|
|
64
64
|
|
|
65
65
|
#### Implementation of
|
|
66
66
|
|
|
67
|
-
`
|
|
67
|
+
`IEntityStorageMigrationConnector.bootstrap`
|
|
68
68
|
|
|
69
69
|
***
|
|
70
70
|
|
|
@@ -82,7 +82,7 @@ The class name of the component.
|
|
|
82
82
|
|
|
83
83
|
#### Implementation of
|
|
84
84
|
|
|
85
|
-
`
|
|
85
|
+
`IEntityStorageMigrationConnector.className`
|
|
86
86
|
|
|
87
87
|
***
|
|
88
88
|
|
|
@@ -100,7 +100,7 @@ The health status of the component.
|
|
|
100
100
|
|
|
101
101
|
#### Implementation of
|
|
102
102
|
|
|
103
|
-
`
|
|
103
|
+
`IEntityStorageMigrationConnector.health`
|
|
104
104
|
|
|
105
105
|
***
|
|
106
106
|
|
|
@@ -118,7 +118,7 @@ The schema for the entities.
|
|
|
118
118
|
|
|
119
119
|
#### Implementation of
|
|
120
120
|
|
|
121
|
-
`
|
|
121
|
+
`IEntityStorageMigrationConnector.getSchema`
|
|
122
122
|
|
|
123
123
|
***
|
|
124
124
|
|
|
@@ -156,7 +156,7 @@ The object if it can be found or undefined.
|
|
|
156
156
|
|
|
157
157
|
#### Implementation of
|
|
158
158
|
|
|
159
|
-
`
|
|
159
|
+
`IEntityStorageMigrationConnector.get`
|
|
160
160
|
|
|
161
161
|
***
|
|
162
162
|
|
|
@@ -188,7 +188,7 @@ The id of the entity.
|
|
|
188
188
|
|
|
189
189
|
#### Implementation of
|
|
190
190
|
|
|
191
|
-
`
|
|
191
|
+
`IEntityStorageMigrationConnector.set`
|
|
192
192
|
|
|
193
193
|
***
|
|
194
194
|
|
|
@@ -214,7 +214,7 @@ Nothing.
|
|
|
214
214
|
|
|
215
215
|
#### Implementation of
|
|
216
216
|
|
|
217
|
-
`
|
|
217
|
+
`IEntityStorageMigrationConnector.setBatch`
|
|
218
218
|
|
|
219
219
|
***
|
|
220
220
|
|
|
@@ -232,7 +232,7 @@ Nothing.
|
|
|
232
232
|
|
|
233
233
|
#### Implementation of
|
|
234
234
|
|
|
235
|
-
`
|
|
235
|
+
`IEntityStorageMigrationConnector.empty`
|
|
236
236
|
|
|
237
237
|
***
|
|
238
238
|
|
|
@@ -264,7 +264,7 @@ Nothing.
|
|
|
264
264
|
|
|
265
265
|
#### Implementation of
|
|
266
266
|
|
|
267
|
-
`
|
|
267
|
+
`IEntityStorageMigrationConnector.remove`
|
|
268
268
|
|
|
269
269
|
***
|
|
270
270
|
|
|
@@ -290,7 +290,7 @@ Nothing.
|
|
|
290
290
|
|
|
291
291
|
#### Implementation of
|
|
292
292
|
|
|
293
|
-
`
|
|
293
|
+
`IEntityStorageMigrationConnector.removeBatch`
|
|
294
294
|
|
|
295
295
|
***
|
|
296
296
|
|
|
@@ -316,7 +316,7 @@ True if the teardown process was successful.
|
|
|
316
316
|
|
|
317
317
|
#### Implementation of
|
|
318
318
|
|
|
319
|
-
`
|
|
319
|
+
`IEntityStorageMigrationConnector.teardown`
|
|
320
320
|
|
|
321
321
|
***
|
|
322
322
|
|
|
@@ -367,16 +367,24 @@ and a cursor which can be used to request more entities.
|
|
|
367
367
|
|
|
368
368
|
#### Implementation of
|
|
369
369
|
|
|
370
|
-
`
|
|
370
|
+
`IEntityStorageMigrationConnector.query`
|
|
371
371
|
|
|
372
372
|
***
|
|
373
373
|
|
|
374
374
|
### count() {#count}
|
|
375
375
|
|
|
376
|
-
> **count**(): `Promise`\<`number`\>
|
|
376
|
+
> **count**(`conditions?`): `Promise`\<`number`\>
|
|
377
377
|
|
|
378
378
|
Count all the entities which match the conditions.
|
|
379
379
|
|
|
380
|
+
#### Parameters
|
|
381
|
+
|
|
382
|
+
##### conditions?
|
|
383
|
+
|
|
384
|
+
`EntityCondition`\<`T`\>
|
|
385
|
+
|
|
386
|
+
The optional conditions to match for the entities.
|
|
387
|
+
|
|
380
388
|
#### Returns
|
|
381
389
|
|
|
382
390
|
`Promise`\<`number`\>
|
|
@@ -385,4 +393,140 @@ The total count of entities in the storage.
|
|
|
385
393
|
|
|
386
394
|
#### Implementation of
|
|
387
395
|
|
|
388
|
-
`
|
|
396
|
+
`IEntityStorageMigrationConnector.count`
|
|
397
|
+
|
|
398
|
+
***
|
|
399
|
+
|
|
400
|
+
### getPartitionContextIds() {#getpartitioncontextids}
|
|
401
|
+
|
|
402
|
+
> **getPartitionContextIds**(): `Promise`\<`IContextIds`[]\>
|
|
403
|
+
|
|
404
|
+
Get a unique list of all the context ids from the storage.
|
|
405
|
+
|
|
406
|
+
#### Returns
|
|
407
|
+
|
|
408
|
+
`Promise`\<`IContextIds`[]\>
|
|
409
|
+
|
|
410
|
+
The list of unique context ids.
|
|
411
|
+
|
|
412
|
+
#### Implementation of
|
|
413
|
+
|
|
414
|
+
`IEntityStorageMigrationConnector.getPartitionContextIds`
|
|
415
|
+
|
|
416
|
+
***
|
|
417
|
+
|
|
418
|
+
### createTargetConnector() {#createtargetconnector}
|
|
419
|
+
|
|
420
|
+
> **createTargetConnector**\<`U`\>(`newEntitySchema`): `Promise`\<`IEntityStorageConnector`\<`U`\>\>
|
|
421
|
+
|
|
422
|
+
Create the target connector for performing the migration using a temporary container.
|
|
423
|
+
|
|
424
|
+
#### Type Parameters
|
|
425
|
+
|
|
426
|
+
##### U
|
|
427
|
+
|
|
428
|
+
`U`
|
|
429
|
+
|
|
430
|
+
#### Parameters
|
|
431
|
+
|
|
432
|
+
##### newEntitySchema
|
|
433
|
+
|
|
434
|
+
`string`
|
|
435
|
+
|
|
436
|
+
The name of the new entity schema to create the connector for.
|
|
437
|
+
|
|
438
|
+
#### Returns
|
|
439
|
+
|
|
440
|
+
`Promise`\<`IEntityStorageConnector`\<`U`\>\>
|
|
441
|
+
|
|
442
|
+
Connector for performing the migration.
|
|
443
|
+
|
|
444
|
+
#### Implementation of
|
|
445
|
+
|
|
446
|
+
`IEntityStorageMigrationConnector.createTargetConnector`
|
|
447
|
+
|
|
448
|
+
***
|
|
449
|
+
|
|
450
|
+
### finalizeMigration() {#finalizemigration}
|
|
451
|
+
|
|
452
|
+
> **finalizeMigration**\<`U`\>(`targetConnector`, `options?`, `loggingComponentType?`): `Promise`\<`CosmosDbEntityStorageConnector`\<`U`\>\>
|
|
453
|
+
|
|
454
|
+
Finalize the migration by tearing down the old container and replacing it with the target container.
|
|
455
|
+
|
|
456
|
+
#### Type Parameters
|
|
457
|
+
|
|
458
|
+
##### U
|
|
459
|
+
|
|
460
|
+
`U`
|
|
461
|
+
|
|
462
|
+
#### Parameters
|
|
463
|
+
|
|
464
|
+
##### targetConnector
|
|
465
|
+
|
|
466
|
+
`CosmosDbEntityStorageConnector`\<`U`\>
|
|
467
|
+
|
|
468
|
+
The target connector to finalize the migration with.
|
|
469
|
+
|
|
470
|
+
##### options?
|
|
471
|
+
|
|
472
|
+
`IMigrationOptions`\<`T`, `U`\>
|
|
473
|
+
|
|
474
|
+
The options to control how the migration is finalized.
|
|
475
|
+
|
|
476
|
+
##### loggingComponentType?
|
|
477
|
+
|
|
478
|
+
`string`
|
|
479
|
+
|
|
480
|
+
The optional component type to use for logging.
|
|
481
|
+
|
|
482
|
+
#### Returns
|
|
483
|
+
|
|
484
|
+
`Promise`\<`CosmosDbEntityStorageConnector`\<`U`\>\>
|
|
485
|
+
|
|
486
|
+
The final connector pointing at the original container id.
|
|
487
|
+
|
|
488
|
+
#### Implementation of
|
|
489
|
+
|
|
490
|
+
`IEntityStorageMigrationConnector.finalizeMigration`
|
|
491
|
+
|
|
492
|
+
***
|
|
493
|
+
|
|
494
|
+
### cleanupMigration() {#cleanupmigration}
|
|
495
|
+
|
|
496
|
+
> **cleanupMigration**\<`U`\>(`targetConnector`, `options?`, `loggingComponentType?`): `Promise`\<`void`\>
|
|
497
|
+
|
|
498
|
+
Cleanup the migration if a migration fails or needs to be aborted.
|
|
499
|
+
|
|
500
|
+
#### Type Parameters
|
|
501
|
+
|
|
502
|
+
##### U
|
|
503
|
+
|
|
504
|
+
`U`
|
|
505
|
+
|
|
506
|
+
#### Parameters
|
|
507
|
+
|
|
508
|
+
##### targetConnector
|
|
509
|
+
|
|
510
|
+
`IEntityStorageConnector`\<`U`\> \| `undefined`
|
|
511
|
+
|
|
512
|
+
The target connector to cleanup.
|
|
513
|
+
|
|
514
|
+
##### options?
|
|
515
|
+
|
|
516
|
+
`IMigrationOptions`\<`T`, `U`\>
|
|
517
|
+
|
|
518
|
+
The options to control how the migration is cleaned up.
|
|
519
|
+
|
|
520
|
+
##### loggingComponentType?
|
|
521
|
+
|
|
522
|
+
`string`
|
|
523
|
+
|
|
524
|
+
The optional component type to use for logging.
|
|
525
|
+
|
|
526
|
+
#### Returns
|
|
527
|
+
|
|
528
|
+
`Promise`\<`void`\>
|
|
529
|
+
|
|
530
|
+
#### Implementation of
|
|
531
|
+
|
|
532
|
+
`IEntityStorageMigrationConnector.cleanupMigration`
|
package/locales/en.json
CHANGED
|
@@ -22,11 +22,13 @@
|
|
|
22
22
|
"containerCreateFailed": "The container couldn't be created \"{containerId}\"",
|
|
23
23
|
"databaseCreateFailed": "Unable to create database \"{databaseId}\"",
|
|
24
24
|
"containerDoesNotExist": "Container \"{containerId}\" does not exist",
|
|
25
|
+
"getPartitionContextIdsFailed": "Unable to get partition context ids",
|
|
25
26
|
"setBatchFailed": "Unable to set batch of entities",
|
|
26
27
|
"countFailed": "Unable to count entities",
|
|
27
28
|
"emptyFailed": "Unable to empty entity storage",
|
|
28
29
|
"removeBatchFailed": "Unable to remove batch of entities",
|
|
29
|
-
"teardownFailed": "Unable to teardown entity storage"
|
|
30
|
+
"teardownFailed": "Unable to teardown entity storage",
|
|
31
|
+
"finalizeMigrationFailedBootstrap": "Finalizing migration failed during bootstrap phase"
|
|
30
32
|
}
|
|
31
33
|
},
|
|
32
34
|
"health": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/entity-storage-connector-cosmosdb",
|
|
3
|
-
"version": "0.0.3-next.
|
|
3
|
+
"version": "0.0.3-next.14",
|
|
4
4
|
"description": "Azure Cosmos DB connector for globally distributed persistence.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"@twin.org/context": "next",
|
|
20
20
|
"@twin.org/core": "next",
|
|
21
21
|
"@twin.org/entity": "next",
|
|
22
|
-
"@twin.org/entity-storage-models": "0.0.3-next.
|
|
22
|
+
"@twin.org/entity-storage-models": "0.0.3-next.14",
|
|
23
23
|
"@twin.org/logging-models": "next",
|
|
24
24
|
"@twin.org/nameof": "next"
|
|
25
25
|
},
|