@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 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 --detach --platform=linux/amd64 --memory=3g --cpus=2.0 mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest
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, CosmosDbDiagnosticLevel, PartitionKeyKind } from "@azure/cosmos";
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
- const schemaProp = this._entitySchema.properties?.find(p => p.property === c.property);
263
- whereQuery.push(
264
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
265
- `c.${String(c.property)} = ${this.propertyToDbValue(c.value, schemaProp?.type)}`);
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
- await this._container.deleteAllItemsForPartitionKey(partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE);
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._container.deleteAllItemsForPartitionKey(partitionKey ?? CosmosDbEntityStorageConnector._PARTITION_KEY_VALUE);
446
- await this._container.delete();
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.partitionId = @partitionId ${queryClause} ${orderByClause}`;
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: feedResponse.continuationToken
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: "SELECT VALUE COUNT(1) FROM c WHERE c.partitionId = @partitionId",
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 `array_contains(c.${attributeName}, @${propName})`;
846
+ return `ARRAY_CONTAINS(c.${attributeName}, @${propName}, true)`;
661
847
  }
662
848
  else if (comparator.comparison === ComparisonOperator.Includes) {
663
- return `contains(c.${attributeName}, @${propName})`;
849
+ return `CONTAINS(c.${attributeName}, @${propName})`;
664
850
  }
665
851
  else if (comparator.comparison === ComparisonOperator.NotIncludes) {
666
- return `notContains(c.${attributeName}, @${propName})`;
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
- ObjectHelper.propertyDelete(item, "partitionId");
754
- ObjectHelper.propertyDelete(item, "_attachments");
755
- ObjectHelper.propertyDelete(item, "_etag");
756
- ObjectHelper.propertyDelete(item, "_rid");
757
- ObjectHelper.propertyDelete(item, "_self");
758
- ObjectHelper.propertyDelete(item, "_ts");
759
- return item;
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 { IEntityStorageConnector } from "@twin.org/entity-storage-models";
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 IEntityStorageConnector<T> {
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
- - `IEntityStorageConnector`\<`T`\>
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
- `IEntityStorageConnector.bootstrap`
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
- `IEntityStorageConnector.className`
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
- `IEntityStorageConnector.health`
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
- `IEntityStorageConnector.getSchema`
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
- `IEntityStorageConnector.get`
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
- `IEntityStorageConnector.set`
191
+ `IEntityStorageMigrationConnector.set`
192
192
 
193
193
  ***
194
194
 
@@ -214,7 +214,7 @@ Nothing.
214
214
 
215
215
  #### Implementation of
216
216
 
217
- `IEntityStorageConnector.setBatch`
217
+ `IEntityStorageMigrationConnector.setBatch`
218
218
 
219
219
  ***
220
220
 
@@ -232,7 +232,7 @@ Nothing.
232
232
 
233
233
  #### Implementation of
234
234
 
235
- `IEntityStorageConnector.empty`
235
+ `IEntityStorageMigrationConnector.empty`
236
236
 
237
237
  ***
238
238
 
@@ -264,7 +264,7 @@ Nothing.
264
264
 
265
265
  #### Implementation of
266
266
 
267
- `IEntityStorageConnector.remove`
267
+ `IEntityStorageMigrationConnector.remove`
268
268
 
269
269
  ***
270
270
 
@@ -290,7 +290,7 @@ Nothing.
290
290
 
291
291
  #### Implementation of
292
292
 
293
- `IEntityStorageConnector.removeBatch`
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
- `IEntityStorageConnector.teardown`
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
- `IEntityStorageConnector.query`
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
- `IEntityStorageConnector.count`
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.13",
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.13",
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
  },