@twin.org/entity-storage-connector-dynamodb 0.9.1-next.3 → 0.9.1-next.5

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.
@@ -865,27 +865,22 @@ export class DynamoDbEntityStorageConnector {
865
865
  if (subParts.length === 0) {
866
866
  return "";
867
867
  }
868
- if (subParts.length === 1) {
869
- return subParts[0];
870
- }
871
- return `(${subParts.join(" AND ")})`;
868
+ return subParts.length === 1 ? ` ${subParts[0]} ` : ` (${subParts.join(" AND ")}) `;
872
869
  })
873
870
  .filter(s => s.length > 0);
874
871
  const hasKeyConditions = joinConditions.some(j => j.keyCondition.length > 0);
875
872
  const filterCondition = parts.join(" OR ");
876
873
  return {
877
874
  keyCondition: "",
878
- filterCondition: Is.stringValue(filterCondition) ? ` (${filterCondition}) ` : "",
875
+ filterCondition: this.wrapConditionExpression(filterCondition, parts.length),
879
876
  requiresScan: hasKeyConditions
880
877
  };
881
878
  }
882
- const keyCondition = joinConditions
883
- .filter(j => j.keyCondition.length > 0)
884
- .map(j => j.keyCondition)
885
- .join(` ${logicalOperator} `);
886
- const filterCondition = joinConditions
887
- .filter(j => j.filterCondition.length > 0)
888
- .map(j => j.filterCondition)
879
+ const keyParts = joinConditions.filter(j => j.keyCondition.length > 0);
880
+ const filterParts = joinConditions.filter(j => j.filterCondition.length > 0);
881
+ const keyCondition = keyParts.map(j => j.keyCondition.trim()).join(` ${logicalOperator} `);
882
+ const filterCondition = filterParts
883
+ .map(j => j.filterCondition.trim())
889
884
  .join(` ${logicalOperator} `);
890
885
  // AND: if any sub-condition is a guaranteed empty result (e.g. empty IN list),
891
886
  // the whole AND group is also empty (#141). Restore the attribute maps to the
@@ -907,8 +902,8 @@ export class DynamoDbEntityStorageConnector {
907
902
  return { keyCondition: "", filterCondition: "", requiresScan: false, noResults: true };
908
903
  }
909
904
  return {
910
- keyCondition: Is.stringValue(keyCondition) ? ` (${keyCondition}) ` : "",
911
- filterCondition: Is.stringValue(filterCondition) ? ` (${filterCondition}) ` : "",
905
+ keyCondition: this.wrapConditionExpression(keyCondition, keyParts.length),
906
+ filterCondition: this.wrapConditionExpression(filterCondition, filterParts.length),
912
907
  requiresScan: joinConditions.some(j => j.requiresScan)
913
908
  };
914
909
  }
@@ -1046,6 +1041,20 @@ export class DynamoDbEntityStorageConnector {
1046
1041
  operator
1047
1042
  });
1048
1043
  }
1044
+ /**
1045
+ * Wrap a condition expression in parentheses only when multiple parts were joined.
1046
+ * A single already-parenthesised child must not be double-wrapped.
1047
+ * @param expr The joined condition expression.
1048
+ * @param partCount The number of parts that were joined to produce expr.
1049
+ * @returns The expression with surrounding spaces, wrapped only when partCount is greater than one.
1050
+ * @internal
1051
+ */
1052
+ wrapConditionExpression(expr, partCount) {
1053
+ if (!Is.stringValue(expr)) {
1054
+ return "";
1055
+ }
1056
+ return partCount > 1 ? ` (${expr}) ` : ` ${expr} `;
1057
+ }
1049
1058
  /**
1050
1059
  * Format a value to insert into DB.
1051
1060
  * @param value The value to format.
@@ -1 +1 @@
1
- {"version":3,"file":"dynamoDbEntityStorageConnector.js","sourceRoot":"","sources":["../../src/dynamoDbEntityStorageConnector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\ttype AttributeValue,\n\tBatchWriteItemCommand,\n\ttype CreateTableCommandInput,\n\tDynamoDB,\n\ttype DynamoDBClientConfig,\n\ttype GlobalSecondaryIndex,\n\tQueryCommand,\n\tScanCommand as RawScanCommand,\n\twaitUntilTableExists,\n\twaitUntilTableNotExists\n} from \"@aws-sdk/client-dynamodb\";\nimport {\n\tBatchWriteCommand,\n\tDeleteCommand,\n\tDynamoDBDocumentClient,\n\tGetCommand,\n\tPutCommand,\n\tScanCommand\n} from \"@aws-sdk/lib-dynamodb\";\nimport { type NativeAttributeValue, unmarshall } from \"@aws-sdk/util-dynamodb\";\nimport { ContextIdHelper, ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tCoerce,\n\tComponentFactory,\n\tConverter,\n\tGeneralError,\n\tGuards,\n\tHealthStatus,\n\ttype IHealth,\n\tIs,\n\ttype IValidationFailure,\n\tObjectHelper,\n\tValidation\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\tEntityStorageHelper,\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 { IDynamoDbEntityStorageConnectorConfig } from \"./models/IDynamoDbEntityStorageConnectorConfig.js\";\nimport type { IDynamoDbEntityStorageConnectorConstructorOptions } from \"./models/IDynamoDbEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations using Dynamo DB.\n */\nexport class DynamoDbEntityStorageConnector<\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<DynamoDbEntityStorageConnector>();\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: IDynamoDbEntityStorageConnectorConfig;\n\n\t/**\n\t * Create a new instance of DynamoDbEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IDynamoDbEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(DynamoDbEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<IDynamoDbEntityStorageConnectorConfig>(\n\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\n\t\toptions.config.authMode ??= \"credentials\";\n\n\t\tif (options.config.authMode === \"credentials\") {\n\t\t\tGuards.stringValue(\n\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tnameof(options.config.accessKeyId),\n\t\t\t\toptions.config.accessKeyId\n\t\t\t);\n\t\t\tGuards.stringValue(\n\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tnameof(options.config.secretAccessKey),\n\t\t\t\toptions.config.secretAccessKey\n\t\t\t);\n\t\t}\n\t\tGuards.stringValue(\n\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.region),\n\t\t\toptions.config.region\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.tableName),\n\t\t\toptions.config.tableName\n\t\t);\n\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\n\t\tthis._entitySchemaName = options.entitySchema;\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._primaryKey = EntitySchemaHelper.getPrimaryKey<T>(this._entitySchema);\n\n\t\tthis._config = options.config;\n\t\tthis._config.endpoint = Is.stringValue(this._config.endpoint)\n\t\t\t? this._config.endpoint\n\t\t\t: undefined;\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 DynamoDbEntityStorageConnector.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\tconst dbConnection = this.createConnection();\n\t\t\tawait dbConnection.describeTable({ TableName: this._config.tableName });\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tdata: { tableName: this._config.tableName }\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: DynamoDbEntityStorageConnector.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: { tableName: this._config.tableName }\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 * Bootstrap the component by creating and initializing any resources it needs.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the bootstrapping process was successful.\n\t */\n\tpublic async bootstrap(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tif (!(await this.tableExists(this._config.tableName))) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"tableCreating\",\n\t\t\t\tdata: {\n\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t}\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tconst dbConnection = this.createConnection();\n\n\t\t\t\tconst tableParams: CreateTableCommandInput = {\n\t\t\t\t\tAttributeDefinitions: [],\n\t\t\t\t\tKeySchema: [],\n\t\t\t\t\tProvisionedThroughput: {\n\t\t\t\t\t\tReadCapacityUnits: 1,\n\t\t\t\t\t\tWriteCapacityUnits: 1\n\t\t\t\t\t},\n\t\t\t\t\tTableName: this._config.tableName\n\t\t\t\t};\n\n\t\t\t\t// We always add a partition key to the table as a non optional hash key\n\t\t\t\t// is always required when querying using sort parameters\n\t\t\t\ttableParams.AttributeDefinitions?.push({\n\t\t\t\t\tAttributeName: DynamoDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\tAttributeType: \"S\"\n\t\t\t\t});\n\t\t\t\ttableParams.KeySchema?.push({\n\t\t\t\t\tAttributeName: DynamoDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\tKeyType: \"HASH\"\n\t\t\t\t});\n\n\t\t\t\tconst gsi: GlobalSecondaryIndex[] = [];\n\n\t\t\t\tif (Is.arrayValue(this._entitySchema.properties)) {\n\t\t\t\t\tfor (const prop of this._entitySchema.properties) {\n\t\t\t\t\t\tif (prop.isPrimary) {\n\t\t\t\t\t\t\ttableParams.AttributeDefinitions?.push({\n\t\t\t\t\t\t\t\tAttributeName: prop.property as string,\n\t\t\t\t\t\t\t\tAttributeType: prop.type === \"integer\" || prop.type === \"number\" ? \"N\" : \"S\"\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttableParams.KeySchema?.push({\n\t\t\t\t\t\t\t\tAttributeName: prop.property as string,\n\t\t\t\t\t\t\t\tKeyType: \"RANGE\"\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (Is.stringValue(prop.sortDirection) || prop.isSecondary) {\n\t\t\t\t\t\t\t// You can only query and sort items if you have a secondary index\n\t\t\t\t\t\t\t// defined for the property\n\t\t\t\t\t\t\ttableParams.AttributeDefinitions?.push({\n\t\t\t\t\t\t\t\tAttributeName: prop.property as string,\n\t\t\t\t\t\t\t\tAttributeType: prop.type === \"integer\" || prop.type === \"number\" ? \"N\" : \"S\"\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tgsi.push({\n\t\t\t\t\t\t\t\tIndexName: `${prop.property as string}Index`,\n\t\t\t\t\t\t\t\tKeySchema: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tAttributeName: DynamoDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\t\t\t\t\t\tKeyType: \"HASH\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tAttributeName: prop.property as string,\n\t\t\t\t\t\t\t\t\t\tKeyType: \"RANGE\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\tProjection: {\n\t\t\t\t\t\t\t\t\tProjectionType: \"ALL\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tProvisionedThroughput: {\n\t\t\t\t\t\t\t\t\tReadCapacityUnits: 1,\n\t\t\t\t\t\t\t\t\tWriteCapacityUnits: 1\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (gsi.length > 0) {\n\t\t\t\t\ttableParams.GlobalSecondaryIndexes = gsi;\n\t\t\t\t}\n\n\t\t\t\tawait dbConnection.createTable(tableParams);\n\n\t\t\t\t// Wait for table to exist\n\t\t\t\tawait waitUntilTableExists(\n\t\t\t\t\t{\n\t\t\t\t\t\tclient: dbConnection,\n\t\t\t\t\t\tmaxWaitTime: 60\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tTableName: this._config.tableName\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"tableCreated\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\tif (BaseError.isErrorCode(err, \"ResourceInUseException\")) {\n\t\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\tts: Date.now(),\n\t\t\t\t\t\tmessage: \"tableExists\",\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\tts: Date.now(),\n\t\t\t\t\t\tmessage: \"tableCreateFailed\",\n\t\t\t\t\t\terror: BaseError.fromError(err),\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} else {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"tableExists\",\n\t\t\t\tdata: {\n\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get an entity.\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(DynamoDbEntityStorageConnector.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 docClient = this.createDocClient();\n\n\t\t\tif (Is.empty(secondaryIndex) && Is.empty(conditions)) {\n\t\t\t\tconst getCommand = new GetCommand({\n\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\tKey: {\n\t\t\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\t\tpartitionKey ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\t\t\t[this._primaryKey.property]: id\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tconst response = await docClient.send(getCommand);\n\n\t\t\t\tif (response.Item) {\n\t\t\t\t\treturn EntityStorageHelper.unPrepareEntity<T>(response.Item as T, [\n\t\t\t\t\t\tDynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t]);\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\t\tconditions: []\n\t\t\t};\n\n\t\t\tif (Is.stringValue(secondaryIndex)) {\n\t\t\t\tfinalConditions.conditions.push({\n\t\t\t\t\tproperty: secondaryIndex,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: id\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tfinalConditions.conditions.push({\n\t\t\t\t\tproperty: this._primaryKey.property as string,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: id\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tfor (const c of conditions) {\n\t\t\t\t\tfinalConditions.conditions.push({\n\t\t\t\t\t\tproperty: c.property as string,\n\t\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\t\tvalue: c.value\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst queryResult = await this.internalQuery(\n\t\t\t\tfinalConditions,\n\t\t\t\tundefined,\n\t\t\t\tundefined,\n\t\t\t\tundefined,\n\t\t\t\t1,\n\t\t\t\tsecondaryIndex as string,\n\t\t\t\tpartitionKey\n\t\t\t);\n\n\t\t\treturn queryResult.entities[0] as T;\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorCode(err, \"ResourceNotFoundException\")) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"tableDoesNotExist\",\n\t\t\t\t\t{\n\t\t\t\t\t\ttableName: this._config.tableName\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\tDynamoDbEntityStorageConnector.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}\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>(DynamoDbEntityStorageConnector.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\tconst prepared = EntityStorageHelper.prepareEntity(\n\t\t\tentity,\n\t\t\tthis._entitySchema,\n\t\t\tpartitionKey\n\t\t\t\t? [{ property: DynamoDbEntityStorageConnector._PARTITION_KEY, value: partitionKey }]\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tproperty: DynamoDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\t\t\tvalue: DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t{ nullBehavior: \"omit\" }\n\t\t);\n\n\t\tconst id = (prepared as { [id: string]: unknown })[this._primaryKey.property as string];\n\n\t\ttry {\n\t\t\tconst docClient = this.createDocClient();\n\n\t\t\tconst { conditionExpression, attributeNames, attributeValues } =\n\t\t\t\tthis.buildConditionExpression(conditions);\n\n\t\t\tconst putCommand = new PutCommand({\n\t\t\t\tTableName: this._config.tableName,\n\t\t\t\tItem: prepared as { [id: string]: unknown },\n\t\t\t\t// Only set the condition expression if we have conditions to match\n\t\t\t\t// and the primary key exists, otherwise we are creating a new object\n\t\t\t\tConditionExpression: Is.stringValue(conditionExpression)\n\t\t\t\t\t? `(attribute_exists(${this._primaryKey.property as string}) AND ${conditionExpression}) OR attribute_not_exists(${this._primaryKey.property as string})`\n\t\t\t\t\t: undefined,\n\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\tExpressionAttributeValues: attributeValues\n\t\t\t});\n\n\t\t\tawait docClient.send(putCommand);\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorName(err, \"ConditionalCheckFailedException\")) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (BaseError.isErrorCode(err, \"ResourceNotFoundException\")) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"tableDoesNotExist\",\n\t\t\t\t\t{\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t},\n\t\t\t\t\terr\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthrow new GeneralError(\n\t\t\t\tDynamoDbEntityStorageConnector.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(DynamoDbEntityStorageConnector.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\tconst preparedEntities = entities.map(entity =>\n\t\t\tEntityStorageHelper.prepareEntity(\n\t\t\t\tentity,\n\t\t\t\tthis._entitySchema,\n\t\t\t\tpartitionKey\n\t\t\t\t\t? [{ property: DynamoDbEntityStorageConnector._PARTITION_KEY, value: partitionKey }]\n\t\t\t\t\t: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tproperty: DynamoDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\t\t\t\tvalue: DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t],\n\t\t\t\t{ nullBehavior: \"omit\" }\n\t\t\t)\n\t\t);\n\n\t\ttry {\n\t\t\tconst docClient = this.createDocClient();\n\t\t\tconst chunkSize = 25;\n\n\t\t\tfor (let i = 0; i < preparedEntities.length; i += chunkSize) {\n\t\t\t\tconst chunk = preparedEntities.slice(i, i + chunkSize);\n\t\t\t\tawait docClient.send(\n\t\t\t\t\tnew BatchWriteCommand({\n\t\t\t\t\t\tRequestItems: {\n\t\t\t\t\t\t\t[this._config.tableName]: chunk.map(entity => ({\n\t\t\t\t\t\t\t\tPutRequest: {\n\t\t\t\t\t\t\t\t\tItem: entity as { [id: string]: unknown }\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorCode(err, \"ResourceNotFoundException\")) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"tableDoesNotExist\",\n\t\t\t\t\t{ tableName: this._config.tableName },\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\tDynamoDbEntityStorageConnector.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 the entity storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\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 pKey = partitionKey ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE;\n\n\t\t\tconst docClient = this.createDocClient();\n\t\t\tconst chunkSize = 25;\n\n\t\t\tlet exclusiveStartKey: { [key: string]: NativeAttributeValue } | undefined;\n\n\t\t\tdo {\n\t\t\t\tconst scanResult = await docClient.send(\n\t\t\t\t\tnew ScanCommand({\n\t\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\t\tFilterExpression: \"#partitionId = :partitionId\",\n\t\t\t\t\t\tExpressionAttributeNames: {\n\t\t\t\t\t\t\t\"#partitionId\": DynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t\t},\n\t\t\t\t\t\tExpressionAttributeValues: {\n\t\t\t\t\t\t\t\":partitionId\": pKey\n\t\t\t\t\t\t},\n\t\t\t\t\t\tExclusiveStartKey: exclusiveStartKey\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\t\tconst items = scanResult.Items ?? [];\n\n\t\t\t\tfor (let i = 0; i < items.length; i += chunkSize) {\n\t\t\t\t\tconst chunk = items.slice(i, i + chunkSize);\n\t\t\t\t\tawait docClient.send(\n\t\t\t\t\t\tnew BatchWriteCommand({\n\t\t\t\t\t\t\tRequestItems: {\n\t\t\t\t\t\t\t\t[this._config.tableName]: chunk.map(\n\t\t\t\t\t\t\t\t\t(item: { [key: string]: NativeAttributeValue }) => ({\n\t\t\t\t\t\t\t\t\t\tDeleteRequest: {\n\t\t\t\t\t\t\t\t\t\t\tKey: {\n\t\t\t\t\t\t\t\t\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\t\t\t\t\t\t\t\titem[DynamoDbEntityStorageConnector._PARTITION_KEY],\n\t\t\t\t\t\t\t\t\t\t\t\t[this._primaryKey.property as string]:\n\t\t\t\t\t\t\t\t\t\t\t\t\titem[this._primaryKey.property as string]\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\texclusiveStartKey = scanResult.LastEvaluatedKey;\n\t\t\t} while (exclusiveStartKey);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tDynamoDbEntityStorageConnector.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(DynamoDbEntityStorageConnector.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 docClient = this.createDocClient();\n\n\t\t\tconst { conditionExpression, attributeNames, attributeValues } =\n\t\t\t\tthis.buildConditionExpression(conditions);\n\n\t\t\tconst deleteCommand = new DeleteCommand({\n\t\t\t\tTableName: this._config.tableName,\n\t\t\t\tKey: {\n\t\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\tpartitionKey ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\t\t[this._primaryKey.property as string]: id\n\t\t\t\t},\n\t\t\t\tConditionExpression: conditionExpression,\n\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\tExpressionAttributeValues: attributeValues\n\t\t\t});\n\n\t\t\tawait docClient.send(deleteCommand);\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorName(err, \"ConditionalCheckFailedException\")) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (BaseError.isErrorCode(err, \"ResourceNotFoundException\")) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"tableDoesNotExist\",\n\t\t\t\t\t{\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t},\n\t\t\t\t\terr\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthrow new GeneralError(\n\t\t\t\tDynamoDbEntityStorageConnector.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 their IDs in a batch.\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(DynamoDbEntityStorageConnector.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 docClient = this.createDocClient();\n\t\t\tconst chunkSize = 25;\n\t\t\tconst primaryKeyProperty = this._primaryKey.property as string;\n\n\t\t\tfor (let i = 0; i < ids.length; i += chunkSize) {\n\t\t\t\tconst chunk = ids.slice(i, i + chunkSize);\n\t\t\t\tawait docClient.send(\n\t\t\t\t\tnew BatchWriteCommand({\n\t\t\t\t\t\tRequestItems: {\n\t\t\t\t\t\t\t[this._config.tableName]: chunk.map(id => ({\n\t\t\t\t\t\t\t\tDeleteRequest: {\n\t\t\t\t\t\t\t\t\tKey: {\n\t\t\t\t\t\t\t\t\t\t[primaryKeyProperty]: id,\n\t\t\t\t\t\t\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\t\t\t\t\t\tpartitionKey ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tDynamoDbEntityStorageConnector.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 entity storage by deleting the underlying table.\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: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"tableDeleting\",\n\t\t\tdata: { tableName: this._config.tableName }\n\t\t});\n\n\t\ttry {\n\t\t\tconst dbConnection = this.createConnection();\n\n\t\t\tawait dbConnection.deleteTable({ TableName: this._config.tableName });\n\n\t\t\tawait waitUntilTableNotExists(\n\t\t\t\t{ client: dbConnection, maxWaitTime: 60 },\n\t\t\t\t{ TableName: this._config.tableName }\n\t\t\t);\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"tableDeleted\",\n\t\t\t\tdata: { tableName: this._config.tableName }\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: DynamoDbEntityStorageConnector.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?: {\n\t\t\tproperty: keyof T;\n\t\t\tsortDirection: SortDirection;\n\t\t}[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\t/**\n\t\t * The entities, which can be partial if a limited keys list was provided.\n\t\t */\n\t\tentities: Partial<T>[];\n\t\t/**\n\t\t * An optional cursor, when defined can be used to call find to get more entities.\n\t\t */\n\t\tcursor?: string;\n\t}> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tif (!Is.empty(limit)) {\n\t\t\tconst validationFailures: IValidationFailure[] = [];\n\t\t\tValidation.integer(nameof(limit), limit, validationFailures, undefined, { minValue: 1 });\n\t\t\tValidation.asValidationError(\n\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"query\",\n\t\t\t\tvalidationFailures\n\t\t\t);\n\t\t}\n\n\t\tEntityStorageHelper.validateSortProperties(this._entitySchema, sortProperties);\n\t\tEntityStorageHelper.validateProperties(this._entitySchema, properties);\n\n\t\treturn this.internalQuery(\n\t\t\tconditions,\n\t\t\tsortProperties,\n\t\t\tproperties,\n\t\t\tcursor,\n\t\t\tlimit,\n\t\t\tundefined,\n\t\t\tpartitionKey\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\t\t\"#partitionId\": DynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t};\n\t\t\tconst attributeValues: { [id: string]: AttributeValue } = {\n\t\t\t\t\":partitionId\": {\n\t\t\t\t\tS: partitionKey ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst expressions = this.buildQueryParameters(\n\t\t\t\t\"\",\n\t\t\t\tconditions,\n\t\t\t\tattributeNames,\n\t\t\t\tattributeValues\n\t\t\t);\n\n\t\t\tif (expressions.noResults) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tconst dbConnection = this.createConnection();\n\t\t\tlet total = 0;\n\t\t\tlet exclusiveStartKey: { [key: string]: AttributeValue } | undefined;\n\n\t\t\tdo {\n\t\t\t\tconst result = await dbConnection.send(\n\t\t\t\t\tnew QueryCommand({\n\t\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\t\tSelect: \"COUNT\",\n\t\t\t\t\t\tKeyConditionExpression: \"#partitionId = :partitionId\",\n\t\t\t\t\t\tFilterExpression: Is.stringValue(expressions.filterCondition)\n\t\t\t\t\t\t\t? expressions.filterCondition\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\t\t\tExclusiveStartKey: exclusiveStartKey\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\ttotal += result.Count ?? 0;\n\t\t\t\texclusiveStartKey = result.LastEvaluatedKey;\n\t\t\t} while (exclusiveStartKey);\n\n\t\t\treturn total;\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tDynamoDbEntityStorageConnector.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\tif (!Is.arrayValue(this._partitionContextIds)) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst contextIdsMap: { [id: string]: IContextIds } = {};\n\n\t\ttry {\n\t\t\tconst docClient = this.createDocClient();\n\t\t\tlet exclusiveStartKey: { [key: string]: NativeAttributeValue } | undefined;\n\n\t\t\tdo {\n\t\t\t\tconst scanResult = await docClient.send(\n\t\t\t\t\tnew ScanCommand({\n\t\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\t\tProjectionExpression: \"#partitionId\",\n\t\t\t\t\t\tExpressionAttributeNames: {\n\t\t\t\t\t\t\t\"#partitionId\": DynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t\t},\n\t\t\t\t\t\tExclusiveStartKey: exclusiveStartKey\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\t\tfor (const item of scanResult.Items ?? []) {\n\t\t\t\t\tconst partitionId = item[DynamoDbEntityStorageConnector._PARTITION_KEY] as string;\n\t\t\t\t\tif (Is.stringValue(partitionId) && !(partitionId in contextIdsMap)) {\n\t\t\t\t\t\tcontextIdsMap[partitionId] = ContextIdHelper.shortSplit(\n\t\t\t\t\t\t\tthis._partitionContextIds ?? [],\n\t\t\t\t\t\t\tpartitionId\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\texclusiveStartKey = scanResult.LastEvaluatedKey;\n\t\t\t} while (exclusiveStartKey);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tDynamoDbEntityStorageConnector.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\n\t\treturn Object.values(contextIdsMap);\n\t}\n\n\t/**\n\t * Create the target connector for performing the migration it will use a temporary storage location.\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\t// We create a new table for the migration with a unique name to avoid conflicts with the existing table\n\t\t// This table will be swapped with the existing table once the migration is finalized.\n\t\tconst migrationTableName = `${this._config.tableName}Migration${Date.now()}`;\n\t\treturn new DynamoDbEntityStorageConnector<U>({\n\t\t\tentitySchema: newEntitySchema,\n\t\t\tconfig: {\n\t\t\t\t...this._config,\n\t\t\t\ttableName: migrationTableName\n\t\t\t},\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\t}\n\n\t/**\n\t * Finalize the migration by tearing down the old connector and replacing it with the new one.\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 logging component type to use for logging during the migration finalization.\n\t * @returns A promise that resolves when the migration is finalized.\n\t */\n\tpublic async finalizeMigration<U>(\n\t\ttargetConnector: DynamoDbEntityStorageConnector<U>,\n\t\toptions?: IMigrationOptions,\n\t\tloggingComponentType?: string\n\t): Promise<DynamoDbEntityStorageConnector<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 DynamoDbEntityStorageConnector<U>({\n\t\t\tentitySchema: targetConnector._entitySchemaName,\n\t\t\tconfig: this._config,\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\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 ?? DynamoDbEntityStorageConnector._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\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\"finalizeMigrationFailedBootstrap\",\n\t\t\tundefined\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 the migration with.\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 the migration progress.\n\t * @returns A promise that resolves when the migration is cleaned up.\n\t */\n\tpublic async cleanupMigration<U>(\n\t\ttargetConnector: IEntityStorageConnector<U> | undefined,\n\t\toptions?: IMigrationOptions,\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: DynamoDbEntityStorageConnector<U>,\n\t\tdestConnector: DynamoDbEntityStorageConnector<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\tconst dbConnection = sourceConnector.createConnection();\n\t\tconst chunkSize = 25;\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) ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE;\n\n\t\t\tlet exclusiveStartKey: { [key: string]: AttributeValue } | undefined;\n\t\t\tdo {\n\t\t\t\tconst { Items: items, LastEvaluatedKey: lastKey } = await dbConnection.send(\n\t\t\t\t\tnew QueryCommand({\n\t\t\t\t\t\tTableName: sourceConnector._config.tableName,\n\t\t\t\t\t\tKeyConditionExpression: `#${DynamoDbEntityStorageConnector._PARTITION_KEY} = :${DynamoDbEntityStorageConnector._PARTITION_KEY}`,\n\t\t\t\t\t\tExpressionAttributeNames: {\n\t\t\t\t\t\t\t[`#${DynamoDbEntityStorageConnector._PARTITION_KEY}`]:\n\t\t\t\t\t\t\t\tDynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t\t},\n\t\t\t\t\t\tExpressionAttributeValues: {\n\t\t\t\t\t\t\t[`:${DynamoDbEntityStorageConnector._PARTITION_KEY}`]: { S: partitionKey }\n\t\t\t\t\t\t},\n\t\t\t\t\t\tLimit: batchSize,\n\t\t\t\t\t\tExclusiveStartKey: exclusiveStartKey\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\t\texclusiveStartKey = lastKey;\n\n\t\t\t\tif (Is.arrayValue(items)) {\n\t\t\t\t\tfor (let j = 0; j < items.length; j += chunkSize) {\n\t\t\t\t\t\tconst chunk = items.slice(j, j + chunkSize) as { [key: string]: AttributeValue }[];\n\t\t\t\t\t\tawait dbConnection.send(\n\t\t\t\t\t\t\tnew BatchWriteItemCommand({\n\t\t\t\t\t\t\t\tRequestItems: {\n\t\t\t\t\t\t\t\t\t[destConnector._config.tableName]: chunk.map(item => ({\n\t\t\t\t\t\t\t\t\t\tPutRequest: { Item: item }\n\t\t\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} while (exclusiveStartKey);\n\t\t}\n\t}\n\n\t/**\n\t * Create the parameters for a query.\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 * @param secondaryIndex The optional secondary index to use for 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]: AttributeValue },\n\t\tsecondaryIndex?: string\n\t): {\n\t\tkeyCondition: string;\n\t\tfilterCondition: string;\n\t\trequiresScan: boolean;\n\t\tnoResults?: boolean;\n\t} {\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\t\tkeyCondition: \"\",\n\t\t\t\tfilterCondition: \"\",\n\t\t\t\trequiresScan: false\n\t\t\t};\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\t\tkeyCondition: \"\",\n\t\t\t\t\tfilterCondition: \"\",\n\t\t\t\t\trequiresScan: false\n\t\t\t\t};\n\t\t\t}\n\t\t\t// Snapshot before the entire group. Used by the AND path to undo\n\t\t\t// surviving siblings' attribute registrations when the AND is dead (#141).\n\t\t\tconst preGroupNames = new Set(Object.keys(attributeNames));\n\t\t\tconst preGroupValues = new Set(Object.keys(attributeValues));\n\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: {\n\t\t\t\tkeyCondition: string;\n\t\t\t\tfilterCondition: string;\n\t\t\t\trequiresScan: boolean;\n\t\t\t\tnoResults?: boolean;\n\t\t\t}[] = condition.conditions.map(c => {\n\t\t\t\t// Snapshot before each branch. When a branch is dead (noResults),\n\t\t\t\t// undo its attribute registrations so the final expressions stay\n\t\t\t\t// consistent — DynamoDB rejects unused ExpressionAttributeNames (#141).\n\t\t\t\tconst preBranchNames = new Set(Object.keys(attributeNames));\n\t\t\t\tconst preBranchValues = new Set(Object.keys(attributeValues));\n\t\t\t\tconst result = this.buildQueryParameters(\n\t\t\t\t\tobjectPath,\n\t\t\t\t\tc,\n\t\t\t\t\tattributeNames,\n\t\t\t\t\tattributeValues,\n\t\t\t\t\tsecondaryIndex\n\t\t\t\t);\n\t\t\t\tif (result.noResults) {\n\t\t\t\t\tfor (const key of Object.keys(attributeNames)) {\n\t\t\t\t\t\tif (!preBranchNames.has(key)) {\n\t\t\t\t\t\t\tdelete attributeNames[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor (const key of Object.keys(attributeValues)) {\n\t\t\t\t\t\tif (!preBranchValues.has(key)) {\n\t\t\t\t\t\t\tdelete attributeValues[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t});\n\n\t\t\tconst logicalOperator = this.mapConditionalOperator(condition.logicalOperator);\n\n\t\t\t// DynamoDB does not support OR in KeyConditionExpression, so when the operator\n\t\t\t// is OR we must move all conditions (including key conditions) into FilterExpression.\n\t\t\tif (condition.logicalOperator === LogicalOperator.Or) {\n\t\t\t\t// OR: only empty if ALL branches are guaranteed empty (e.g. all empty IN lists).\n\t\t\t\t// If only some are empty they are naturally filtered out of `parts` below,\n\t\t\t\t// which is correct — false OR x = x (#141).\n\t\t\t\tif (joinConditions.every(j => j.noResults)) {\n\t\t\t\t\treturn { keyCondition: \"\", filterCondition: \"\", requiresScan: false, noResults: true };\n\t\t\t\t}\n\n\t\t\t\tconst parts = joinConditions\n\t\t\t\t\t.map(j => {\n\t\t\t\t\t\t// A branch marked noResults (e.g. a dead AND group containing In [])\n\t\t\t\t\t\t// must contribute nothing to the OR — false OR x = x (#141).\n\t\t\t\t\t\tif (j.noResults) {\n\t\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst subParts = [j.keyCondition.trim(), j.filterCondition.trim()].filter(\n\t\t\t\t\t\t\ts => s.length > 0\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (subParts.length === 0) {\n\t\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (subParts.length === 1) {\n\t\t\t\t\t\t\treturn subParts[0];\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn `(${subParts.join(\" AND \")})`;\n\t\t\t\t\t})\n\t\t\t\t\t.filter(s => s.length > 0);\n\t\t\t\tconst hasKeyConditions = joinConditions.some(j => j.keyCondition.length > 0);\n\t\t\t\tconst filterCondition = parts.join(\" OR \");\n\t\t\t\treturn {\n\t\t\t\t\tkeyCondition: \"\",\n\t\t\t\t\tfilterCondition: Is.stringValue(filterCondition) ? ` (${filterCondition}) ` : \"\",\n\t\t\t\t\trequiresScan: hasKeyConditions\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst keyCondition = joinConditions\n\t\t\t\t.filter(j => j.keyCondition.length > 0)\n\t\t\t\t.map(j => j.keyCondition)\n\t\t\t\t.join(` ${logicalOperator} `);\n\t\t\tconst filterCondition = joinConditions\n\t\t\t\t.filter(j => j.filterCondition.length > 0)\n\t\t\t\t.map(j => j.filterCondition)\n\t\t\t\t.join(` ${logicalOperator} `);\n\n\t\t\t// AND: if any sub-condition is a guaranteed empty result (e.g. empty IN list),\n\t\t\t// the whole AND group is also empty (#141). Restore the attribute maps to the\n\t\t\t// pre-group snapshot so surviving siblings' registrations are also undone —\n\t\t\t// per-branch cleanup above only undoes dead branches, not live ones whose AND\n\t\t\t// partner was dead.\n\t\t\tconst noResults = joinConditions.some(j => j.noResults);\n\t\t\tif (noResults) {\n\t\t\t\tfor (const key of Object.keys(attributeNames)) {\n\t\t\t\t\tif (!preGroupNames.has(key)) {\n\t\t\t\t\t\tdelete attributeNames[key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (const key of Object.keys(attributeValues)) {\n\t\t\t\t\tif (!preGroupValues.has(key)) {\n\t\t\t\t\t\tdelete attributeValues[key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { keyCondition: \"\", filterCondition: \"\", requiresScan: false, noResults: true };\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tkeyCondition: Is.stringValue(keyCondition) ? ` (${keyCondition}) ` : \"\",\n\t\t\t\tfilterCondition: Is.stringValue(filterCondition) ? ` (${filterCondition}) ` : \"\",\n\t\t\t\trequiresScan: joinConditions.some(j => j.requiresScan)\n\t\t\t};\n\t\t}\n\n\t\tconst schemaProp = this._entitySchema.properties?.find(p => p.property === condition.property);\n\n\t\t// Empty IN list: DynamoDB has no `IN ()` syntax — short-circuit to empty result (#141).\n\t\tif (\n\t\t\t\"comparison\" in condition &&\n\t\t\tcondition.comparison === ComparisonOperator.In &&\n\t\t\tIs.array(condition.value) &&\n\t\t\tcondition.value.length === 0\n\t\t) {\n\t\t\treturn { keyCondition: \"\", filterCondition: \"\", requiresScan: false, noResults: true };\n\t\t}\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\tconst isKey =\n\t\t\tschemaProp?.isPrimary ?? (schemaProp?.isSecondary && schemaProp?.property === secondaryIndex);\n\t\treturn {\n\t\t\tkeyCondition: isKey ? comparison : \"\",\n\t\t\tfilterCondition: !isKey ? comparison : \"\",\n\t\t\trequiresScan: false\n\t\t};\n\t}\n\n\t/**\n\t * Map the framework comparison operators to those in DynamoDB.\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 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 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]: AttributeValue }\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\n\t\tif (Is.empty(comparator.value)) {\n\t\t\t// With \"omit\" storage, optional null/undefined fields are absent from the item entirely.\n\t\t\t// attribute_not_exists matches absent attributes; attribute_exists matches present ones.\n\t\t\tif (comparator.comparison === ComparisonOperator.Equals) {\n\t\t\t\treturn `attribute_not_exists(${attributeName})`;\n\t\t\t} else if (comparator.comparison === ComparisonOperator.NotEquals) {\n\t\t\t\treturn `attribute_exists(${attributeName})`;\n\t\t\t}\n\t\t}\n\n\t\tconst basePropName = `:${attributeName.replace(/\\./g, \"\").replace(/#/g, \"\")}`;\n\t\tlet propName = basePropName;\n\t\tlet propSuffix = 0;\n\t\twhile (!Is.undefined(attributeValues[propName])) {\n\t\t\tpropSuffix++;\n\t\t\tpropName = `${basePropName}${propSuffix}`;\n\t\t}\n\n\t\tif (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.join(\", \")})`;\n\t\t} else {\n\t\t\tattributeValues[propName] = this.propertyToDbValue(comparator.value, type);\n\t\t}\n\n\t\tif (comparator.comparison === ComparisonOperator.Equals) {\n\t\t\treturn `${attributeName} = ${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.NotEquals) {\n\t\t\treturn `${attributeName} <> ${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.GreaterThan) {\n\t\t\treturn `${attributeName} > ${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.LessThan) {\n\t\t\treturn `${attributeName} < ${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.GreaterThanOrEqual) {\n\t\t\treturn `${attributeName} >= ${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.LessThanOrEqual) {\n\t\t\treturn `${attributeName} <= ${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.Includes) {\n\t\t\treturn `contains(${attributeName}, ${propName})`;\n\t\t} else if (comparator.comparison === ComparisonOperator.NotIncludes) {\n\t\t\treturn `NOT contains(${attributeName}, ${propName})`;\n\t\t} else if (comparator.comparison === ComparisonOperator.In) {\n\t\t\treturn `${propName} IN ${attributeName}`;\n\t\t}\n\n\t\tthrow new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, \"comparisonNotSupported\", {\n\t\t\tcomparison: comparator.comparison\n\t\t});\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 DynamoDB.\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(DynamoDbEntityStorageConnector.CLASS_NAME, \"conditionalNotSupported\", {\n\t\t\toperator\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): AttributeValue {\n\t\tif (Is.object(value)) {\n\t\t\tconst map: { [id: string]: AttributeValue } = {};\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 {\n\t\t\t\tM: map\n\t\t\t};\n\t\t}\n\n\t\tif (type === \"integer\" || type === \"number\") {\n\t\t\treturn { N: Coerce.string(value) ?? \"\" };\n\t\t} else if (type === \"boolean\") {\n\t\t\treturn { BOOL: Coerce.boolean(value) ?? false };\n\t\t}\n\n\t\tif (Is.boolean(value)) {\n\t\t\treturn { BOOL: value };\n\t\t} else if (Is.number(value)) {\n\t\t\treturn { N: value.toString() };\n\t\t}\n\n\t\treturn { S: Coerce.string(value) ?? \"\" };\n\t}\n\n\t/**\n\t * Create a doc client connection.\n\t * @returns The dynamo db document client.\n\t * @internal\n\t */\n\tprivate createDocClient(): DynamoDBDocumentClient {\n\t\treturn DynamoDBDocumentClient.from(\n\t\t\tnew DynamoDB({\n\t\t\t\tapiVersion: \"2012-10-08\",\n\t\t\t\t...this.createConnectionConfig()\n\t\t\t}),\n\t\t\t{\n\t\t\t\tmarshallOptions: {\n\t\t\t\t\tremoveUndefinedValues: true\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Create a new DB connection.\n\t * @returns The Dynamo DB connection.\n\t * @internal\n\t */\n\tprivate createConnection(): DynamoDB {\n\t\treturn new DynamoDB(this.createConnectionConfig());\n\t}\n\n\t/**\n\t * Create a new DB connection configuration.\n\t * @returns The Dynamo DB connection configuration.\n\t * @internal\n\t */\n\tprivate createConnectionConfig(): DynamoDBClientConfig {\n\t\tconst requestHandler = Is.number(this._config.connectionTimeoutMs)\n\t\t\t? { requestTimeout: this._config.connectionTimeoutMs }\n\t\t\t: undefined;\n\n\t\tif (\n\t\t\tIs.stringValue(this._config.secretAccessKey) &&\n\t\t\tIs.stringValue(this._config.accessKeyId) &&\n\t\t\tthis._config.authMode === \"credentials\"\n\t\t) {\n\t\t\treturn {\n\t\t\t\tcredentials: {\n\t\t\t\t\taccessKeyId: this._config.accessKeyId,\n\t\t\t\t\tsecretAccessKey: this._config.secretAccessKey\n\t\t\t\t},\n\t\t\t\tendpoint: this._config.endpoint,\n\t\t\t\tregion: this._config.region,\n\t\t\t\trequestHandler,\n\t\t\t\tmaxAttempts: this._config.maxAttempts\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tendpoint: this._config.endpoint,\n\t\t\tregion: this._config.region,\n\t\t\trequestHandler,\n\t\t\tmaxAttempts: this._config.maxAttempts\n\t\t};\n\t}\n\n\t/**\n\t * Check if the table exists.\n\t * @param tableName The table to check.\n\t * @returns True if the table exists.\n\t * @internal\n\t */\n\tprivate async tableExists(tableName: string): Promise<boolean> {\n\t\ttry {\n\t\t\tconst dbConnection = this.createConnection();\n\n\t\t\tconst result = await dbConnection.describeTable({ TableName: tableName });\n\n\t\t\t// A table in DELETING state should not be treated as existing\n\t\t\treturn result.Table?.TableStatus !== \"DELETING\";\n\t\t} catch {\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 * @param secondaryIndex The secondary index to use for the query.\n\t * @param partitionKey The partition key to use for the query.\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 * @internal\n\t */\n\tprivate async internalQuery(\n\t\tconditions?: EntityCondition<T>,\n\t\tsortProperties?: {\n\t\t\tproperty: keyof T;\n\t\t\tsortDirection: SortDirection;\n\t\t}[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number,\n\t\tsecondaryIndex?: string,\n\t\tpartitionKey?: string\n\t): Promise<{\n\t\tentities: Partial<T>[];\n\t\tcursor?: string;\n\t}> {\n\t\ttry {\n\t\t\tconst returnSize = limit ?? DynamoDbEntityStorageConnector._DEFAULT_LIMIT;\n\t\t\tconst indexConfig = this.resolveQueryIndexConfig(sortProperties, secondaryIndex);\n\t\t\tconst { attributeNames, attributeValues } = this.buildQueryAttributeMaps(partitionKey);\n\t\t\tconst safeCursor = this.sanitizeCursorForPartition(cursor, attributeValues);\n\n\t\t\tconst expressions = this.buildQueryParameters(\n\t\t\t\t\"\",\n\t\t\t\tconditions,\n\t\t\t\tattributeNames,\n\t\t\t\tattributeValues,\n\t\t\t\tindexConfig.gsiAttribute\n\t\t\t);\n\n\t\t\tif (expressions.noResults) {\n\t\t\t\treturn { entities: [], cursor: undefined };\n\t\t\t}\n\n\t\t\tif (expressions.requiresScan) {\n\t\t\t\tconst scanResult = await this.executeScanFallback(\n\t\t\t\t\texpressions.filterCondition,\n\t\t\t\t\tproperties,\n\t\t\t\t\tattributeNames,\n\t\t\t\t\tattributeValues,\n\t\t\t\t\tsafeCursor,\n\t\t\t\t\treturnSize\n\t\t\t\t);\n\n\t\t\t\treturn {\n\t\t\t\t\tentities: this.mapRawItemsToEntities(scanResult.rawItems),\n\t\t\t\t\tcursor: scanResult.cursor\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst keyExpression = this.buildKeyExpression(expressions.keyCondition);\n\t\t\tconst queryProjection = this.buildProjectionExpression(properties, attributeNames);\n\n\t\t\tconst queryResult = Is.stringValue(expressions.filterCondition)\n\t\t\t\t? await this.executeFilteredQuery(\n\t\t\t\t\t\tkeyExpression,\n\t\t\t\t\t\texpressions.filterCondition,\n\t\t\t\t\t\tattributeNames,\n\t\t\t\t\t\tattributeValues,\n\t\t\t\t\t\tqueryProjection,\n\t\t\t\t\t\tindexConfig.indexName,\n\t\t\t\t\t\tindexConfig.scanAscending,\n\t\t\t\t\t\tsafeCursor,\n\t\t\t\t\t\treturnSize\n\t\t\t\t\t)\n\t\t\t\t: await this.executeUnfilteredQuery(\n\t\t\t\t\t\tkeyExpression,\n\t\t\t\t\t\tattributeNames,\n\t\t\t\t\t\tattributeValues,\n\t\t\t\t\t\tqueryProjection,\n\t\t\t\t\t\tindexConfig.indexName,\n\t\t\t\t\t\tindexConfig.scanAscending,\n\t\t\t\t\t\tsafeCursor,\n\t\t\t\t\t\treturnSize\n\t\t\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tentities: this.mapRawItemsToEntities(queryResult.rawItems),\n\t\t\t\tcursor: queryResult.cursor\n\t\t\t};\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorCode(err, \"ResourceNotFoundException\")) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"tableDoesNotExist\",\n\t\t\t\t\t{\n\t\t\t\t\t\ttableName: this._config.tableName\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\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"queryFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Resolve index configuration from sort options and optional explicit secondary index.\n\t * @param sortProperties The optional sort order.\n\t * @param secondaryIndex The optional explicit secondary index.\n\t * @returns The resolved index name, GSI attribute and sort direction.\n\t * @throws GeneralError if more than one sort property is specified.\n\t * @internal\n\t */\n\tprivate resolveQueryIndexConfig(\n\t\tsortProperties?: {\n\t\t\tproperty: keyof T;\n\t\t\tsortDirection: SortDirection;\n\t\t}[],\n\t\tsecondaryIndex?: string\n\t): {\n\t\tindexName?: string;\n\t\tgsiAttribute?: string;\n\t\tscanAscending: boolean;\n\t} {\n\t\tlet indexName: string | undefined = Is.stringValue(secondaryIndex)\n\t\t\t? `${secondaryIndex}Index`\n\t\t\t: undefined;\n\t\tlet gsiAttribute: string | undefined = secondaryIndex;\n\t\tlet scanAscending = true;\n\n\t\tif (Is.arrayValue(sortProperties)) {\n\t\t\tif (sortProperties.length > 1) {\n\t\t\t\tthrow new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, \"sortSingle\");\n\t\t\t}\n\n\t\t\tfor (const sortProperty of sortProperties) {\n\t\t\t\tconst propertySchema = this._entitySchema.properties?.find(\n\t\t\t\t\te => e.property === sortProperty.property\n\t\t\t\t);\n\t\t\t\tif (propertySchema?.isPrimary) {\n\t\t\t\t\tindexName = undefined;\n\t\t\t\t\tgsiAttribute = undefined;\n\t\t\t\t} else {\n\t\t\t\t\tindexName = `${sortProperty.property as string}Index`;\n\t\t\t\t\tgsiAttribute = sortProperty.property as string;\n\t\t\t\t}\n\t\t\t\tscanAscending = sortProperty.sortDirection === SortDirection.Ascending;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tindexName,\n\t\t\tgsiAttribute,\n\t\t\tscanAscending\n\t\t};\n\t}\n\n\t/**\n\t * Build the base attribute maps used for query/scan operations.\n\t * @param partitionKey The optional partition key.\n\t * @returns The query attribute maps.\n\t * @internal\n\t */\n\tprivate buildQueryAttributeMaps(partitionKey?: string): {\n\t\tattributeNames: { [id: string]: string };\n\t\tattributeValues: { [id: string]: AttributeValue };\n\t} {\n\t\treturn {\n\t\t\tattributeNames: { \"#partitionId\": \"partitionId\" },\n\t\t\tattributeValues: {\n\t\t\t\t[`:${DynamoDbEntityStorageConnector._PARTITION_KEY}`]: {\n\t\t\t\t\tS: partitionKey ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Build the key condition expression with the mandatory partition predicate.\n\t * @param keyCondition The optional extra key condition segment.\n\t * @returns The full key condition expression.\n\t * @internal\n\t */\n\tprivate buildKeyExpression(keyCondition: string): string {\n\t\tlet keyExpression = \"#partitionId = :partitionId\";\n\t\tif (keyCondition.length > 0) {\n\t\t\tkeyExpression += ` AND ${keyCondition}`;\n\t\t}\n\t\treturn keyExpression;\n\t}\n\n\t/**\n\t * Decode a paginated cursor into a DynamoDB ExclusiveStartKey.\n\t * @param cursor The encoded cursor.\n\t * @returns The decoded exclusive start key.\n\t * @internal\n\t */\n\tprivate decodeCursor(cursor?: string): { [id: string]: AttributeValue } | undefined {\n\t\treturn Is.empty(cursor) ? undefined : ObjectHelper.fromBytes(Converter.base64ToBytes(cursor));\n\t}\n\n\t/**\n\t * Encode a DynamoDB key to a cursor string.\n\t * @param key The key to encode.\n\t * @returns The encoded cursor.\n\t * @internal\n\t */\n\tprivate encodeCursor(key?: { [id: string]: AttributeValue }): string | undefined {\n\t\treturn Is.empty(key) ? undefined : Converter.bytesToBase64(ObjectHelper.toBytes(key));\n\t}\n\n\t/**\n\t * Return undefined if the cursor belongs to a different partition, preventing cross-partition leakage.\n\t * @param cursor The encoded cursor.\n\t * @param attributeValues The current query attribute values containing the expected partition key.\n\t * @returns The cursor if it matches the current partition, otherwise undefined.\n\t * @internal\n\t */\n\tprivate sanitizeCursorForPartition(\n\t\tcursor: string | undefined,\n\t\tattributeValues: { [id: string]: AttributeValue }\n\t): string | undefined {\n\t\tif (Is.empty(cursor)) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst decoded = this.decodeCursor(cursor);\n\t\tif (Is.empty(decoded)) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst expectedPartition =\n\t\t\tattributeValues[`:${DynamoDbEntityStorageConnector._PARTITION_KEY}`]?.S;\n\t\tconst cursorPartition = decoded[DynamoDbEntityStorageConnector._PARTITION_KEY]?.S;\n\t\treturn cursorPartition === expectedPartition ? cursor : undefined;\n\t}\n\n\t/**\n\t * Execute a scan fallback path for unsupported key-condition shapes.\n\t * @param filterCondition The optional filter expression part.\n\t * @param properties The projection properties.\n\t * @param attributeNames The expression attribute names.\n\t * @param attributeValues The expression attribute values.\n\t * @param cursor The optional cursor.\n\t * @param returnSize The requested page size.\n\t * @returns Raw items and an optional cursor.\n\t * @internal\n\t */\n\tprivate async executeScanFallback(\n\t\tfilterCondition: string,\n\t\tproperties: (keyof T)[] | undefined,\n\t\tattributeNames: { [id: string]: string },\n\t\tattributeValues: { [id: string]: AttributeValue },\n\t\tcursor: string | undefined,\n\t\treturnSize: number\n\t): Promise<{\n\t\trawItems: { [id: string]: AttributeValue }[];\n\t\tcursor?: string;\n\t}> {\n\t\tlet scanFilter = \"#partitionId = :partitionId\";\n\t\tif (Is.stringValue(filterCondition)) {\n\t\t\tscanFilter += ` AND ${filterCondition.trim()}`;\n\t\t}\n\n\t\tconst dbConnection = this.createConnection();\n\t\tconst matchingItems: { [id: string]: AttributeValue }[] = [];\n\t\tlet scanStartKey = this.decodeCursor(cursor);\n\t\tlet lastEvaluatedKey: { [id: string]: AttributeValue } | undefined;\n\n\t\t// Scan in batches with a heuristic limit to avoid scanning excessive unmatched rows.\n\t\t// Use at least 2x returnSize per batch to balance accuracy and efficiency.\n\t\tconst batchScanLimit = Math.max(returnSize * 2, 100);\n\n\t\tdo {\n\t\t\tconst scanResult = await dbConnection.send(\n\t\t\t\tnew RawScanCommand({\n\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\tFilterExpression: scanFilter,\n\t\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\t\tExclusiveStartKey: scanStartKey,\n\t\t\t\t\tLimit: batchScanLimit\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tmatchingItems.push(...(scanResult.Items ?? []));\n\t\t\tlastEvaluatedKey = scanResult.LastEvaluatedKey;\n\t\t\tscanStartKey = lastEvaluatedKey;\n\n\t\t\t// Early exit: stop scanning once we have enough filtered results to fill the page.\n\t\t\tif (matchingItems.length >= returnSize) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} while (!Is.empty(lastEvaluatedKey));\n\n\t\tconst hasMore = matchingItems.length > returnSize;\n\t\tconst returnedRawItems = hasMore ? matchingItems.slice(0, returnSize) : matchingItems;\n\n\t\tlet resultCursor: string | undefined;\n\t\tif (hasMore) {\n\t\t\tconst lastRawItem = returnedRawItems[returnedRawItems.length - 1];\n\t\t\tconst syntheticKey: { [id: string]: AttributeValue } = {\n\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\tlastRawItem[DynamoDbEntityStorageConnector._PARTITION_KEY],\n\t\t\t\t[this._primaryKey.property as string]: lastRawItem[this._primaryKey.property as string]\n\t\t\t};\n\t\t\tresultCursor = this.encodeCursor(syntheticKey);\n\t\t}\n\n\t\tconst projectedRawItems = Is.arrayValue(properties)\n\t\t\t? returnedRawItems.map(item => {\n\t\t\t\t\tconst projected: { [id: string]: AttributeValue } = {};\n\t\t\t\t\tfor (const prop of properties) {\n\t\t\t\t\t\tconst key = prop as string;\n\t\t\t\t\t\tif (!Is.undefined(item[key])) {\n\t\t\t\t\t\t\tprojected[key] = item[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!Is.undefined(item[DynamoDbEntityStorageConnector._PARTITION_KEY])) {\n\t\t\t\t\t\tprojected[DynamoDbEntityStorageConnector._PARTITION_KEY] =\n\t\t\t\t\t\t\titem[DynamoDbEntityStorageConnector._PARTITION_KEY];\n\t\t\t\t\t}\n\t\t\t\t\treturn projected;\n\t\t\t\t})\n\t\t\t: returnedRawItems;\n\n\t\treturn {\n\t\t\trawItems: projectedRawItems,\n\t\t\tcursor: resultCursor\n\t\t};\n\t}\n\n\t/**\n\t * Execute a query path without filter expression.\n\t * @param keyExpression The key condition expression.\n\t * @param attributeNames The expression attribute names.\n\t * @param attributeValues The expression attribute values.\n\t * @param projectionExpression The projection expression.\n\t * @param indexName The optional index name.\n\t * @param scanAscending The scan direction.\n\t * @param cursor The optional cursor.\n\t * @param returnSize The requested page size.\n\t * @returns Raw items and an optional cursor.\n\t * @internal\n\t */\n\tprivate async executeUnfilteredQuery(\n\t\tkeyExpression: string,\n\t\tattributeNames: { [id: string]: string },\n\t\tattributeValues: { [id: string]: AttributeValue },\n\t\tprojectionExpression: string | undefined,\n\t\tindexName: string | undefined,\n\t\tscanAscending: boolean,\n\t\tcursor: string | undefined,\n\t\treturnSize: number\n\t): Promise<{\n\t\trawItems: { [id: string]: AttributeValue }[];\n\t\tcursor?: string;\n\t}> {\n\t\tconst connection = this.createDocClient();\n\t\tconst results = await connection.send(\n\t\t\tnew QueryCommand({\n\t\t\t\tTableName: this._config.tableName,\n\t\t\t\tIndexName: indexName,\n\t\t\t\tKeyConditionExpression: keyExpression,\n\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\tProjectionExpression: projectionExpression,\n\t\t\t\tLimit: returnSize,\n\t\t\t\tScanIndexForward: scanAscending,\n\t\t\t\tExclusiveStartKey: this.decodeCursor(cursor)\n\t\t\t})\n\t\t);\n\n\t\tconst rawItems = (results.Items ?? []) as { [id: string]: AttributeValue }[];\n\t\tlet hasMore = false;\n\n\t\tif (rawItems.length === returnSize && !Is.empty(results.LastEvaluatedKey)) {\n\t\t\tconst probe = await connection.send(\n\t\t\t\tnew QueryCommand({\n\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\tIndexName: indexName,\n\t\t\t\t\tKeyConditionExpression: keyExpression,\n\t\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\t\tProjectionExpression: projectionExpression,\n\t\t\t\t\tLimit: 1,\n\t\t\t\t\tScanIndexForward: scanAscending,\n\t\t\t\t\tExclusiveStartKey: results.LastEvaluatedKey\n\t\t\t\t})\n\t\t\t);\n\t\t\thasMore = (probe.Items?.length ?? 0) > 0;\n\t\t}\n\n\t\treturn {\n\t\t\trawItems,\n\t\t\tcursor: hasMore ? this.encodeCursor(results.LastEvaluatedKey) : undefined\n\t\t};\n\t}\n\n\t/**\n\t * Execute a query path with filter expression, continuing until page is full or exhausted.\n\t * @param keyExpression The key condition expression.\n\t * @param filterExpression The filter expression.\n\t * @param attributeNames The expression attribute names.\n\t * @param attributeValues The expression attribute values.\n\t * @param projectionExpression The projection expression.\n\t * @param indexName The optional index name.\n\t * @param scanAscending The scan direction.\n\t * @param cursor The optional cursor.\n\t * @param returnSize The requested page size.\n\t * @returns Raw items and an optional cursor.\n\t * @internal\n\t */\n\tprivate async executeFilteredQuery(\n\t\tkeyExpression: string,\n\t\tfilterExpression: string,\n\t\tattributeNames: { [id: string]: string },\n\t\tattributeValues: { [id: string]: AttributeValue },\n\t\tprojectionExpression: string | undefined,\n\t\tindexName: string | undefined,\n\t\tscanAscending: boolean,\n\t\tcursor: string | undefined,\n\t\treturnSize: number\n\t): Promise<{\n\t\trawItems: { [id: string]: AttributeValue }[];\n\t\tcursor?: string;\n\t}> {\n\t\tconst connection = this.createDocClient();\n\t\tconst returnedRawItems: { [id: string]: AttributeValue }[] = [];\n\t\tlet lastEvaluatedKey: { [id: string]: AttributeValue } | undefined = this.decodeCursor(cursor);\n\n\t\tdo {\n\t\t\tconst results = await connection.send(\n\t\t\t\tnew QueryCommand({\n\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\tIndexName: indexName,\n\t\t\t\t\tKeyConditionExpression: keyExpression,\n\t\t\t\t\tFilterExpression: filterExpression,\n\t\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\t\tProjectionExpression: projectionExpression,\n\t\t\t\t\tLimit: returnSize - returnedRawItems.length,\n\t\t\t\t\tScanIndexForward: scanAscending,\n\t\t\t\t\tExclusiveStartKey: lastEvaluatedKey\n\t\t\t\t})\n\t\t\t);\n\n\t\t\treturnedRawItems.push(...((results.Items ?? []) as { [id: string]: AttributeValue }[]));\n\t\t\tlastEvaluatedKey = results.LastEvaluatedKey;\n\t\t} while (returnedRawItems.length < returnSize && !Is.empty(lastEvaluatedKey));\n\n\t\treturn {\n\t\t\trawItems: returnedRawItems,\n\t\t\tcursor: this.encodeCursor(lastEvaluatedKey)\n\t\t};\n\t}\n\n\t/**\n\t * Convert raw DynamoDB items into connector entities.\n\t * @param rawItems Raw DynamoDB items.\n\t * @returns The mapped entities.\n\t * @internal\n\t */\n\tprivate mapRawItemsToEntities(rawItems: { [id: string]: AttributeValue }[]): T[] {\n\t\treturn rawItems.map(item => {\n\t\t\tconst unmarshalled = unmarshall(item);\n\t\t\treturn EntityStorageHelper.unPrepareEntity(unmarshalled as T, [\n\t\t\t\tDynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t]);\n\t\t});\n\t}\n\n\t/**\n\t * Build the condition expression for the query.\n\t * @param conditions The conditions to build the expression from.\n\t * @returns The condition expression.\n\t * @throws GeneralError if the property is not found in the schema.\n\t * @internal\n\t */\n\tprivate buildConditionExpression(conditions?: { property: keyof T; value: unknown }[]): {\n\t\tconditionExpression: string | undefined;\n\t\tattributeNames: { [id: string]: string } | undefined;\n\t\tattributeValues: { [key: string]: NativeAttributeValue } | undefined;\n\t} {\n\t\tlet conditionExpression: string | undefined;\n\t\tlet attributeNames: { [id: string]: string } | undefined;\n\t\tlet attributeValues: { [key: string]: NativeAttributeValue } | undefined;\n\n\t\tif (Is.arrayValue(conditions)) {\n\t\t\tconst expressions: string[] = [];\n\n\t\t\tfor (const c of conditions) {\n\t\t\t\tconst schemaProp = this._entitySchema.properties?.find(p => p.property === c.property);\n\n\t\t\t\tif (Is.undefined(schemaProp)) {\n\t\t\t\t\tthrow new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, \"propertyNotFound\", {\n\t\t\t\t\t\tproperty: c.property\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst attributeName = `#${c.property as string}`;\n\t\t\t\tconst attributeValueName = `:${c.property as string}`;\n\t\t\t\tattributeNames ??= {};\n\t\t\t\tattributeValues ??= {};\n\t\t\t\tattributeNames[attributeName] = c.property as string;\n\t\t\t\tattributeValues[attributeValueName] = c.value;\n\t\t\t\texpressions.push(`${attributeName} = ${attributeValueName}`);\n\t\t\t}\n\n\t\t\tconditionExpression = expressions.join(\" AND \");\n\t\t}\n\t\treturn { conditionExpression, attributeNames, attributeValues };\n\t}\n\n\t/**\n\t * Build a ProjectionExpression string and register a safe alias in attributeNames for every\n\t * projected property, preventing ValidationException when a property name is a DynamoDB\n\t * reserved word (e.g. \"role\", \"name\", \"status\").\n\t * @param properties The properties to project, or undefined to return all attributes.\n\t * @param attributeNames The expression attribute names map to mutate with the aliases.\n\t * @returns The ProjectionExpression string, or undefined when no projection is needed.\n\t * @internal\n\t */\n\tprivate buildProjectionExpression(\n\t\tproperties: (keyof T)[] | undefined,\n\t\tattributeNames: { [id: string]: string }\n\t): string | undefined {\n\t\tif (!Is.arrayValue(properties)) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn properties\n\t\t\t.map(p => {\n\t\t\t\tconst alias = `#p_${p as string}`;\n\t\t\t\tattributeNames[alias] = p as string;\n\t\t\t\treturn alias;\n\t\t\t})\n\t\t\t.join(\", \");\n\t}\n}\n"]}
1
+ {"version":3,"file":"dynamoDbEntityStorageConnector.js","sourceRoot":"","sources":["../../src/dynamoDbEntityStorageConnector.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAEN,qBAAqB,EAErB,QAAQ,EAGR,YAAY,EACZ,WAAW,IAAI,cAAc,EAC7B,oBAAoB,EACpB,uBAAuB,EACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,iBAAiB,EACjB,aAAa,EACb,sBAAsB,EACtB,UAAU,EACV,UAAU,EACV,WAAW,EACX,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAA6B,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,cAAc,EAAoB,MAAM,mBAAmB,CAAC;AACtF,OAAO,EACN,SAAS,EACT,MAAM,EACN,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,MAAM,EACN,YAAY,EAEZ,EAAE,EAEF,YAAY,EACZ,UAAU,EACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,kBAAkB,EAElB,mBAAmB,EACnB,kBAAkB,EAKlB,eAAe,EACf,aAAa,EACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,mBAAmB,EAInB,MAAM,iCAAiC,CAAC;AAMzC;;GAEG;AACH,MAAM,OAAO,8BAA8B;IAG1C;;OAEG;IACI,MAAM,CAAU,UAAU,oCAAoD;IAErF;;;OAGG;IACK,MAAM,CAAU,cAAc,GAAW,EAAE,CAAC;IAEpD;;;OAGG;IACK,MAAM,CAAU,cAAc,GAAW,aAAa,CAAC;IAE/D;;;OAGG;IACK,MAAM,CAAU,oBAAoB,GAAW,MAAM,CAAC;IAE9D;;;OAGG;IACc,iBAAiB,CAAS;IAE3C;;;OAGG;IACc,aAAa,CAAmB;IAEjD;;;OAGG;IACc,oBAAoB,CAAY;IAEjD;;;OAGG;IACc,WAAW,CAA2B;IAEvD;;;OAGG;IACc,OAAO,CAAwC;IAEhE;;;OAGG;IACH,YAAY,OAA0D;QACrE,MAAM,CAAC,MAAM,CAAC,8BAA8B,CAAC,UAAU,aAAmB,OAAO,CAAC,CAAC;QACnF,MAAM,CAAC,WAAW,CACjB,8BAA8B,CAAC,UAAU,0BAEzC,OAAO,CAAC,YAAY,CACpB,CAAC;QACF,MAAM,CAAC,MAAM,CACZ,8BAA8B,CAAC,UAAU,oBAEzC,OAAO,CAAC,MAAM,CACd,CAAC;QAEF,OAAO,CAAC,MAAM,CAAC,QAAQ,KAAK,aAAa,CAAC;QAE1C,IAAI,OAAO,CAAC,MAAM,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;YAC/C,MAAM,CAAC,WAAW,CACjB,8BAA8B,CAAC,UAAU,gCAEzC,OAAO,CAAC,MAAM,CAAC,WAAW,CAC1B,CAAC;YACF,MAAM,CAAC,WAAW,CACjB,8BAA8B,CAAC,UAAU,oCAEzC,OAAO,CAAC,MAAM,CAAC,eAAe,CAC9B,CAAC;QACH,CAAC;QACD,MAAM,CAAC,WAAW,CACjB,8BAA8B,CAAC,UAAU,2BAEzC,OAAO,CAAC,MAAM,CAAC,MAAM,CACrB,CAAC;QACF,MAAM,CAAC,WAAW,CACjB,8BAA8B,CAAC,UAAU,8BAEzC,OAAO,CAAC,MAAM,CAAC,SAAS,CACxB,CAAC;QAEF,IAAI,CAAC,oBAAoB,GAAG,OAAO,CAAC,mBAAmB,CAAC;QAExD,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC;QAC9C,IAAI,CAAC,aAAa,GAAG,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACnE,IAAI,CAAC,WAAW,GAAG,kBAAkB,CAAC,aAAa,CAAI,IAAI,CAAC,aAAa,CAAC,CAAC;QAE3E,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;QAC9B,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC5D,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ;YACvB,CAAC,CAAC,SAAS,CAAC;IACd,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,8BAA8B,CAAC,UAAU,CAAC;IAClD,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,MAAM;QAClB,IAAI,CAAC;YACJ,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC7C,MAAM,YAAY,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;YACxE,OAAO;gBACN;oBACC,MAAM,EAAE,8BAA8B,CAAC,UAAU;oBACjD,MAAM,EAAE,YAAY,CAAC,EAAE;oBACvB,WAAW,EAAE,mBAAmB;oBAChC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;iBAC3C;aACD,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACR,OAAO;gBACN;oBACC,MAAM,EAAE,8BAA8B,CAAC,UAAU;oBACjD,MAAM,EAAE,YAAY,CAAC,KAAK;oBAC1B,WAAW,EAAE,mBAAmB;oBAChC,OAAO,EAAE,kBAAkB;oBAC3B,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;iBAC3C;aACD,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;OAGG;IACI,SAAS;QACf,OAAO,IAAI,CAAC,aAA8B,CAAC;IAC5C,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,SAAS,CAAC,wBAAiC;QACvD,MAAM,WAAW,GAAG,gBAAgB,CAAC,WAAW,CAAoB,wBAAwB,CAAC,CAAC;QAE9F,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;YACvD,MAAM,WAAW,EAAE,GAAG,CAAC;gBACtB,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,8BAA8B,CAAC,UAAU;gBACjD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,OAAO,EAAE,eAAe;gBACxB,IAAI,EAAE;oBACL,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;iBACjC;aACD,CAAC,CAAC;YAEH,IAAI,CAAC;gBACJ,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAE7C,MAAM,WAAW,GAA4B;oBAC5C,oBAAoB,EAAE,EAAE;oBACxB,SAAS,EAAE,EAAE;oBACb,qBAAqB,EAAE;wBACtB,iBAAiB,EAAE,CAAC;wBACpB,kBAAkB,EAAE,CAAC;qBACrB;oBACD,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;iBACjC,CAAC;gBAEF,wEAAwE;gBACxE,yDAAyD;gBACzD,WAAW,CAAC,oBAAoB,EAAE,IAAI,CAAC;oBACtC,aAAa,EAAE,8BAA8B,CAAC,cAAc;oBAC5D,aAAa,EAAE,GAAG;iBAClB,CAAC,CAAC;gBACH,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC;oBAC3B,aAAa,EAAE,8BAA8B,CAAC,cAAc;oBAC5D,OAAO,EAAE,MAAM;iBACf,CAAC,CAAC;gBAEH,MAAM,GAAG,GAA2B,EAAE,CAAC;gBAEvC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,CAAC;oBAClD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;wBAClD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;4BACpB,WAAW,CAAC,oBAAoB,EAAE,IAAI,CAAC;gCACtC,aAAa,EAAE,IAAI,CAAC,QAAkB;gCACtC,aAAa,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;6BAC5E,CAAC,CAAC;4BACH,WAAW,CAAC,SAAS,EAAE,IAAI,CAAC;gCAC3B,aAAa,EAAE,IAAI,CAAC,QAAkB;gCACtC,OAAO,EAAE,OAAO;6BAChB,CAAC,CAAC;wBACJ,CAAC;6BAAM,IAAI,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;4BACnE,kEAAkE;4BAClE,2BAA2B;4BAC3B,WAAW,CAAC,oBAAoB,EAAE,IAAI,CAAC;gCACtC,aAAa,EAAE,IAAI,CAAC,QAAkB;gCACtC,aAAa,EAAE,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG;6BAC5E,CAAC,CAAC;4BAEH,GAAG,CAAC,IAAI,CAAC;gCACR,SAAS,EAAE,GAAG,IAAI,CAAC,QAAkB,OAAO;gCAC5C,SAAS,EAAE;oCACV;wCACC,aAAa,EAAE,8BAA8B,CAAC,cAAc;wCAC5D,OAAO,EAAE,MAAM;qCACf;oCACD;wCACC,aAAa,EAAE,IAAI,CAAC,QAAkB;wCACtC,OAAO,EAAE,OAAO;qCAChB;iCACD;gCACD,UAAU,EAAE;oCACX,cAAc,EAAE,KAAK;iCACrB;gCACD,qBAAqB,EAAE;oCACtB,iBAAiB,EAAE,CAAC;oCACpB,kBAAkB,EAAE,CAAC;iCACrB;6BACD,CAAC,CAAC;wBACJ,CAAC;oBACF,CAAC;gBACF,CAAC;gBAED,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACpB,WAAW,CAAC,sBAAsB,GAAG,GAAG,CAAC;gBAC1C,CAAC;gBAED,MAAM,YAAY,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;gBAE5C,0BAA0B;gBAC1B,MAAM,oBAAoB,CACzB;oBACC,MAAM,EAAE,YAAY;oBACpB,WAAW,EAAE,EAAE;iBACf,EACD;oBACC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;iBACjC,CACD,CAAC;gBAEF,MAAM,WAAW,EAAE,GAAG,CAAC;oBACtB,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,8BAA8B,CAAC,UAAU;oBACjD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;oBACd,OAAO,EAAE,cAAc;oBACvB,IAAI,EAAE;wBACL,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;qBACjC;iBACD,CAAC,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACd,IAAI,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,wBAAwB,CAAC,EAAE,CAAC;oBAC1D,MAAM,WAAW,EAAE,GAAG,CAAC;wBACtB,KAAK,EAAE,MAAM;wBACb,MAAM,EAAE,8BAA8B,CAAC,UAAU;wBACjD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;wBACd,OAAO,EAAE,aAAa;wBACtB,IAAI,EAAE;4BACL,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;yBACjC;qBACD,CAAC,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACP,MAAM,WAAW,EAAE,GAAG,CAAC;wBACtB,KAAK,EAAE,OAAO;wBACd,MAAM,EAAE,8BAA8B,CAAC,UAAU;wBACjD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;wBACd,OAAO,EAAE,mBAAmB;wBAC5B,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC;wBAC/B,IAAI,EAAE;4BACL,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;yBACjC;qBACD,CAAC,CAAC;gBACJ,CAAC;gBACD,OAAO,KAAK,CAAC;YACd,CAAC;QACF,CAAC;aAAM,CAAC;YACP,MAAM,WAAW,EAAE,GAAG,CAAC;gBACtB,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,8BAA8B,CAAC,UAAU;gBACjD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,OAAO,EAAE,aAAa;gBACtB,IAAI,EAAE;oBACL,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;iBACjC;aACD,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,GAAG,CACf,EAAU,EACV,cAAwB,EACxB,UAAoD;QAEpD,MAAM,CAAC,WAAW,CAAC,8BAA8B,CAAC,UAAU,QAAc,EAAE,CAAC,CAAC;QAE9E,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,IAAI,CAAC;YACJ,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YAEzC,IAAI,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;gBACtD,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC;oBACjC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;oBACjC,GAAG,EAAE;wBACJ,CAAC,8BAA8B,CAAC,cAAc,CAAC,EAC9C,YAAY,IAAI,8BAA8B,CAAC,oBAAoB;wBACpE,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,EAAE;qBAC/B;iBACD,CAAC,CAAC;gBAEH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;gBAElD,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;oBACnB,OAAO,mBAAmB,CAAC,eAAe,CAAI,QAAQ,CAAC,IAAS,EAAE;wBACjE,8BAA8B,CAAC,cAAc;qBAC7C,CAAC,CAAC;gBACJ,CAAC;gBACD,OAAO,SAAS,CAAC;YAClB,CAAC;YAED,MAAM,eAAe,GAAuB;gBAC3C,UAAU,EAAE,EAAE;aACd,CAAC;YAEF,IAAI,EAAE,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC;gBACpC,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC;oBAC/B,QAAQ,EAAE,cAAc;oBACxB,UAAU,EAAE,kBAAkB,CAAC,MAAM;oBACrC,KAAK,EAAE,EAAE;iBACT,CAAC,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACP,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC;oBAC/B,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,QAAkB;oBAC7C,UAAU,EAAE,kBAAkB,CAAC,MAAM;oBACrC,KAAK,EAAE,EAAE;iBACT,CAAC,CAAC;YACJ,CAAC;YACD,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC/B,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;oBAC5B,eAAe,CAAC,UAAU,CAAC,IAAI,CAAC;wBAC/B,QAAQ,EAAE,CAAC,CAAC,QAAkB;wBAC9B,UAAU,EAAE,kBAAkB,CAAC,MAAM;wBACrC,KAAK,EAAE,CAAC,CAAC,KAAK;qBACd,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;YAED,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,aAAa,CAC3C,eAAe,EACf,SAAS,EACT,SAAS,EACT,SAAS,EACT,CAAC,EACD,cAAwB,EACxB,YAAY,CACZ,CAAC;YAEF,OAAO,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAM,CAAC;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,2BAA2B,CAAC,EAAE,CAAC;gBAC7D,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,mBAAmB,EACnB;oBACC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;iBACjC,EACD,GAAG,CACH,CAAC;YACH,CAAC;YACD,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,WAAW,EACX;gBACC,EAAE;aACF,EACD,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,GAAG,CAAC,MAAS,EAAE,UAAoD;QAC/E,MAAM,CAAC,MAAM,CAAI,8BAA8B,CAAC,UAAU,YAAkB,MAAM,CAAC,CAAC;QAEpF,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,MAAM,QAAQ,GAAG,mBAAmB,CAAC,aAAa,CACjD,MAAM,EACN,IAAI,CAAC,aAAa,EAClB,YAAY;YACX,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,8BAA8B,CAAC,cAAc,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;YACpF,CAAC,CAAC;gBACA;oBACC,QAAQ,EAAE,8BAA8B,CAAC,cAAc;oBACvD,KAAK,EAAE,8BAA8B,CAAC,oBAAoB;iBAC1D;aACD,EACH,EAAE,YAAY,EAAE,MAAM,EAAE,CACxB,CAAC;QAEF,MAAM,EAAE,GAAI,QAAsC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAkB,CAAC,CAAC;QAExF,IAAI,CAAC;YACJ,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YAEzC,MAAM,EAAE,mBAAmB,EAAE,cAAc,EAAE,eAAe,EAAE,GAC7D,IAAI,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC;YAE3C,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC;gBACjC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;gBACjC,IAAI,EAAE,QAAqC;gBAC3C,mEAAmE;gBACnE,qEAAqE;gBACrE,mBAAmB,EAAE,EAAE,CAAC,WAAW,CAAC,mBAAmB,CAAC;oBACvD,CAAC,CAAC,qBAAqB,IAAI,CAAC,WAAW,CAAC,QAAkB,SAAS,mBAAmB,6BAA6B,IAAI,CAAC,WAAW,CAAC,QAAkB,GAAG;oBACzJ,CAAC,CAAC,SAAS;gBACZ,wBAAwB,EAAE,cAAc;gBACxC,yBAAyB,EAAE,eAAe;aAC1C,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,iCAAiC,CAAC,EAAE,CAAC;gBACnE,OAAO;YACR,CAAC;YAED,IAAI,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,2BAA2B,CAAC,EAAE,CAAC;gBAC7D,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,mBAAmB,EACnB;oBACC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;iBACjC,EACD,GAAG,CACH,CAAC;YACH,CAAC;YAED,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,WAAW,EACX;gBACC,EAAE;aACF,EACD,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,QAAQ,CAAC,QAAa;QAClC,MAAM,CAAC,UAAU,CAAC,8BAA8B,CAAC,UAAU,cAAoB,QAAQ,CAAC,CAAC;QAEzF,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,MAAM,gBAAgB,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAC9C,mBAAmB,CAAC,aAAa,CAChC,MAAM,EACN,IAAI,CAAC,aAAa,EAClB,YAAY;YACX,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,8BAA8B,CAAC,cAAc,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;YACpF,CAAC,CAAC;gBACA;oBACC,QAAQ,EAAE,8BAA8B,CAAC,cAAc;oBACvD,KAAK,EAAE,8BAA8B,CAAC,oBAAoB;iBAC1D;aACD,EACH,EAAE,YAAY,EAAE,MAAM,EAAE,CACxB,CACD,CAAC;QAEF,IAAI,CAAC;YACJ,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,EAAE,CAAC;YAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC7D,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC;gBACvD,MAAM,SAAS,CAAC,IAAI,CACnB,IAAI,iBAAiB,CAAC;oBACrB,YAAY,EAAE;wBACb,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;4BAC9C,UAAU,EAAE;gCACX,IAAI,EAAE,MAAmC;6BACzC;yBACD,CAAC,CAAC;qBACH;iBACD,CAAC,CACF,CAAC;YACH,CAAC;QACF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,2BAA2B,CAAC,EAAE,CAAC;gBAC7D,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,mBAAmB,EACnB,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EACrC,GAAG,CACH,CAAC;YACH,CAAC;YACD,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,gBAAgB,EAChB,SAAS,EACT,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,KAAK;QACjB,IAAI,CAAC;YACJ,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;YACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CACtD,UAAU,EACV,IAAI,CAAC,oBAAoB,CACzB,CAAC;YAEF,MAAM,IAAI,GAAG,YAAY,IAAI,8BAA8B,CAAC,oBAAoB,CAAC;YAEjF,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,EAAE,CAAC;YAErB,IAAI,iBAAsE,CAAC;YAE3E,GAAG,CAAC;gBACH,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,IAAI,CACtC,IAAI,WAAW,CAAC;oBACf,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;oBACjC,gBAAgB,EAAE,6BAA6B;oBAC/C,wBAAwB,EAAE;wBACzB,cAAc,EAAE,8BAA8B,CAAC,cAAc;qBAC7D;oBACD,yBAAyB,EAAE;wBAC1B,cAAc,EAAE,IAAI;qBACpB;oBACD,iBAAiB,EAAE,iBAAiB;iBACpC,CAAC,CACF,CAAC;gBAEF,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE,CAAC;gBAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC;oBAClD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC;oBAC5C,MAAM,SAAS,CAAC,IAAI,CACnB,IAAI,iBAAiB,CAAC;wBACrB,YAAY,EAAE;4BACb,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAClC,CAAC,IAA6C,EAAE,EAAE,CAAC,CAAC;gCACnD,aAAa,EAAE;oCACd,GAAG,EAAE;wCACJ,CAAC,8BAA8B,CAAC,cAAc,CAAC,EAC9C,IAAI,CAAC,8BAA8B,CAAC,cAAc,CAAC;wCACpD,CAAC,IAAI,CAAC,WAAW,CAAC,QAAkB,CAAC,EACpC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,QAAkB,CAAC;qCAC1C;iCACD;6BACD,CAAC,CACF;yBACD;qBACD,CAAC,CACF,CAAC;gBACH,CAAC;gBAED,iBAAiB,GAAG,UAAU,CAAC,gBAAgB,CAAC;YACjD,CAAC,QAAQ,iBAAiB,EAAE;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,aAAa,EACb,SAAS,EACT,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACI,KAAK,CAAC,MAAM,CAClB,EAAU,EACV,UAAoD;QAEpD,MAAM,CAAC,WAAW,CAAC,8BAA8B,CAAC,UAAU,QAAc,EAAE,CAAC,CAAC;QAE9E,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,IAAI,CAAC;YACJ,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YAEzC,MAAM,EAAE,mBAAmB,EAAE,cAAc,EAAE,eAAe,EAAE,GAC7D,IAAI,CAAC,wBAAwB,CAAC,UAAU,CAAC,CAAC;YAE3C,MAAM,aAAa,GAAG,IAAI,aAAa,CAAC;gBACvC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;gBACjC,GAAG,EAAE;oBACJ,CAAC,8BAA8B,CAAC,cAAc,CAAC,EAC9C,YAAY,IAAI,8BAA8B,CAAC,oBAAoB;oBACpE,CAAC,IAAI,CAAC,WAAW,CAAC,QAAkB,CAAC,EAAE,EAAE;iBACzC;gBACD,mBAAmB,EAAE,mBAAmB;gBACxC,wBAAwB,EAAE,cAAc;gBACxC,yBAAyB,EAAE,eAAe;aAC1C,CAAC,CAAC;YAEH,MAAM,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,iCAAiC,CAAC,EAAE,CAAC;gBACnE,OAAO;YACR,CAAC;YACD,IAAI,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,2BAA2B,CAAC,EAAE,CAAC;gBAC7D,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,mBAAmB,EACnB;oBACC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;iBACjC,EACD,GAAG,CACH,CAAC;YACH,CAAC;YAED,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,cAAc,EACd;gBACC,EAAE;aACF,EACD,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,WAAW,CAAC,GAAa;QACrC,MAAM,CAAC,UAAU,CAAC,8BAA8B,CAAC,UAAU,SAAe,GAAG,CAAC,CAAC;QAE/E,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,IAAI,CAAC;YACJ,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YACzC,MAAM,SAAS,GAAG,EAAE,CAAC;YACrB,MAAM,kBAAkB,GAAG,IAAI,CAAC,WAAW,CAAC,QAAkB,CAAC;YAE/D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC;gBAChD,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC;gBAC1C,MAAM,SAAS,CAAC,IAAI,CACnB,IAAI,iBAAiB,CAAC;oBACrB,YAAY,EAAE;wBACb,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;4BAC1C,aAAa,EAAE;gCACd,GAAG,EAAE;oCACJ,CAAC,kBAAkB,CAAC,EAAE,EAAE;oCACxB,CAAC,8BAA8B,CAAC,cAAc,CAAC,EAC9C,YAAY,IAAI,8BAA8B,CAAC,oBAAoB;iCACpE;6BACD;yBACD,CAAC,CAAC;qBACH;iBACD,CAAC,CACF,CAAC;YACH,CAAC;QACF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,mBAAmB,EACnB,SAAS,EACT,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,QAAQ,CAAC,wBAAiC;QACtD,MAAM,WAAW,GAAG,gBAAgB,CAAC,WAAW,CAAoB,wBAAwB,CAAC,CAAC;QAE9F,MAAM,WAAW,EAAE,GAAG,CAAC;YACtB,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,8BAA8B,CAAC,UAAU;YACjD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;YACd,OAAO,EAAE,eAAe;YACxB,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;SAC3C,CAAC,CAAC;QAEH,IAAI,CAAC;YACJ,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAE7C,MAAM,YAAY,CAAC,WAAW,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;YAEtE,MAAM,uBAAuB,CAC5B,EAAE,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,EAAE,EAAE,EACzC,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CACrC,CAAC;YAEF,MAAM,WAAW,EAAE,GAAG,CAAC;gBACtB,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,8BAA8B,CAAC,UAAU;gBACjD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,OAAO,EAAE,cAAc;gBACvB,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;aAC3C,CAAC,CAAC;YAEH,OAAO,IAAI,CAAC;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,WAAW,EAAE,GAAG,CAAC;gBACtB,KAAK,EAAE,OAAO;gBACd,MAAM,EAAE,8BAA8B,CAAC,UAAU;gBACjD,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;gBACd,OAAO,EAAE,gBAAgB;gBACzB,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC;aAC/B,CAAC,CAAC;YACH,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAED;;;;;;;;;OASG;IACI,KAAK,CAAC,KAAK,CACjB,UAA+B,EAC/B,cAGG,EACH,UAAwB,EACxB,MAAe,EACf,KAAc;QAWd,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;QACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CAAC,UAAU,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAE/F,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,kBAAkB,GAAyB,EAAE,CAAC;YACpD,UAAU,CAAC,OAAO,UAAgB,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;YACzF,UAAU,CAAC,iBAAiB,CAC3B,8BAA8B,CAAC,UAAU,EACzC,OAAO,EACP,kBAAkB,CAClB,CAAC;QACH,CAAC;QAED,mBAAmB,CAAC,sBAAsB,CAAC,IAAI,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;QAC/E,mBAAmB,CAAC,kBAAkB,CAAC,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;QAEvE,OAAO,IAAI,CAAC,aAAa,CACxB,UAAU,EACV,cAAc,EACd,UAAU,EACV,MAAM,EACN,KAAK,EACL,SAAS,EACT,YAAY,CACZ,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,KAAK,CAAC,UAA+B;QACjD,IAAI,CAAC;YACJ,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,aAAa,EAAE,CAAC;YACxD,MAAM,YAAY,GAAG,eAAe,CAAC,kBAAkB,CACtD,UAAU,EACV,IAAI,CAAC,oBAAoB,CACzB,CAAC;YAEF,MAAM,cAAc,GAA6B;gBAChD,cAAc,EAAE,8BAA8B,CAAC,cAAc;aAC7D,CAAC;YACF,MAAM,eAAe,GAAqC;gBACzD,cAAc,EAAE;oBACf,CAAC,EAAE,YAAY,IAAI,8BAA8B,CAAC,oBAAoB;iBACtE;aACD,CAAC;YAEF,MAAM,WAAW,GAAG,IAAI,CAAC,oBAAoB,CAC5C,EAAE,EACF,UAAU,EACV,cAAc,EACd,eAAe,CACf,CAAC;YAEF,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;gBAC3B,OAAO,CAAC,CAAC;YACV,CAAC;YAED,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC7C,IAAI,KAAK,GAAG,CAAC,CAAC;YACd,IAAI,iBAAgE,CAAC;YAErE,GAAG,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,CACrC,IAAI,YAAY,CAAC;oBAChB,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;oBACjC,MAAM,EAAE,OAAO;oBACf,sBAAsB,EAAE,6BAA6B;oBACrD,gBAAgB,EAAE,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,eAAe,CAAC;wBAC5D,CAAC,CAAC,WAAW,CAAC,eAAe;wBAC7B,CAAC,CAAC,SAAS;oBACZ,wBAAwB,EAAE,cAAc;oBACxC,yBAAyB,EAAE,eAAe;oBAC1C,iBAAiB,EAAE,iBAAiB;iBACpC,CAAC,CACF,CAAC;gBACF,KAAK,IAAI,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;gBAC3B,iBAAiB,GAAG,MAAM,CAAC,gBAAgB,CAAC;YAC7C,CAAC,QAAQ,iBAAiB,EAAE;YAE5B,OAAO,KAAK,CAAC;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,aAAa,EACb,SAAS,EACT,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,sBAAsB;QAClC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE,CAAC;YAC/C,OAAO,EAAE,CAAC;QACX,CAAC;QAED,MAAM,aAAa,GAAkC,EAAE,CAAC;QAExD,IAAI,CAAC;YACJ,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YACzC,IAAI,iBAAsE,CAAC;YAE3E,GAAG,CAAC;gBACH,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,IAAI,CACtC,IAAI,WAAW,CAAC;oBACf,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;oBACjC,oBAAoB,EAAE,cAAc;oBACpC,wBAAwB,EAAE;wBACzB,cAAc,EAAE,8BAA8B,CAAC,cAAc;qBAC7D;oBACD,iBAAiB,EAAE,iBAAiB;iBACpC,CAAC,CACF,CAAC;gBAEF,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;oBAC3C,MAAM,WAAW,GAAG,IAAI,CAAC,8BAA8B,CAAC,cAAc,CAAW,CAAC;oBAClF,IAAI,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,WAAW,IAAI,aAAa,CAAC,EAAE,CAAC;wBACpE,aAAa,CAAC,WAAW,CAAC,GAAG,eAAe,CAAC,UAAU,CACtD,IAAI,CAAC,oBAAoB,IAAI,EAAE,EAC/B,WAAW,CACX,CAAC;oBACH,CAAC;gBACF,CAAC;gBAED,iBAAiB,GAAG,UAAU,CAAC,gBAAgB,CAAC;YACjD,CAAC,QAAQ,iBAAiB,EAAE;QAC7B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,8BAA8B,EAC9B,SAAS,EACT,GAAG,CACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACI,KAAK,CAAC,qBAAqB,CACjC,eAAuB;QAEvB,wGAAwG;QACxG,sFAAsF;QACtF,MAAM,kBAAkB,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,YAAY,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QAC7E,OAAO,IAAI,8BAA8B,CAAI;YAC5C,YAAY,EAAE,eAAe;YAC7B,MAAM,EAAE;gBACP,GAAG,IAAI,CAAC,OAAO;gBACf,SAAS,EAAE,kBAAkB;aAC7B;YACD,mBAAmB,EAAE,IAAI,CAAC,oBAAoB;SAC9C,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,iBAAiB,CAC7B,eAAkD,EAClD,OAA2B,EAC3B,oBAA6B;QAE7B,0HAA0H;QAE1H,2FAA2F;QAC3F,MAAM,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;QAE1C,8EAA8E;QAC9E,qFAAqF;QACrF,MAAM,cAAc,GAAG,IAAI,8BAA8B,CAAI;YAC5D,YAAY,EAAE,eAAe,CAAC,iBAAiB;YAC/C,MAAM,EAAE,IAAI,CAAC,OAAO;YACpB,mBAAmB,EAAE,IAAI,CAAC,oBAAoB;SAC9C,CAAC,CAAC;QAEH,IAAI,MAAM,cAAc,CAAC,SAAS,CAAC,oBAAoB,CAAC,EAAE,CAAC;YAC1D,+FAA+F;YAC/F,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,sBAAsB,EAAE,CAAC;YAClE,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,8BAA8B,CAAC,cAAc,CAAC;YACtF,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;YAE5E,MAAM,eAAe,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;YAErD,OAAO,cAAc,CAAC;QACvB,CAAC;QAED,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,kCAAkC,EAClC,SAAS,CACT,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACI,KAAK,CAAC,gBAAgB,CAC5B,eAAuD,EACvD,OAA2B,EAC3B,oBAA6B;QAE7B,uEAAuE;QACvE,MAAM,eAAe,EAAE,QAAQ,EAAE,CAAC,oBAAoB,CAAC,CAAC;IACzD,CAAC;IAED;;;;;;;OAOG;IACK,KAAK,CAAC,QAAQ,CACrB,eAAkD,EAClD,aAAgD,EAChD,UAAyB,EACzB,SAAiB;QAEjB,IAAI,aAA4B,CAAC;QACjC,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,aAAa,GAAG,UAAU,CAAC;QAC5B,CAAC;aAAM,IAAI,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,oBAAoB,CAAC,EAAE,CAAC;YAChE,aAAa,GAAG,EAAE,CAAC;QACpB,CAAC;aAAM,CAAC;YACP,aAAa,GAAG,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;QAED,MAAM,YAAY,GAAG,eAAe,CAAC,gBAAgB,EAAE,CAAC;QACxD,MAAM,SAAS,GAAG,EAAE,CAAC;QAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,MAAM,YAAY,GACjB,eAAe,CAAC,kBAAkB,CACjC,aAAa,CAAC,CAAC,CAAC,EAChB,eAAe,CAAC,oBAAoB,CACpC,IAAI,8BAA8B,CAAC,oBAAoB,CAAC;YAE1D,IAAI,iBAAgE,CAAC;YACrE,GAAG,CAAC;gBACH,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,GAAG,MAAM,YAAY,CAAC,IAAI,CAC1E,IAAI,YAAY,CAAC;oBAChB,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,SAAS;oBAC5C,sBAAsB,EAAE,IAAI,8BAA8B,CAAC,cAAc,OAAO,8BAA8B,CAAC,cAAc,EAAE;oBAC/H,wBAAwB,EAAE;wBACzB,CAAC,IAAI,8BAA8B,CAAC,cAAc,EAAE,CAAC,EACpD,8BAA8B,CAAC,cAAc;qBAC9C;oBACD,yBAAyB,EAAE;wBAC1B,CAAC,IAAI,8BAA8B,CAAC,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,YAAY,EAAE;qBAC1E;oBACD,KAAK,EAAE,SAAS;oBAChB,iBAAiB,EAAE,iBAAiB;iBACpC,CAAC,CACF,CAAC;gBAEF,iBAAiB,GAAG,OAAO,CAAC;gBAE5B,IAAI,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;oBAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC;wBAClD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAwC,CAAC;wBACnF,MAAM,YAAY,CAAC,IAAI,CACtB,IAAI,qBAAqB,CAAC;4BACzB,YAAY,EAAE;gCACb,CAAC,aAAa,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;oCACrD,UAAU,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;iCAC1B,CAAC,CAAC;6BACH;yBACD,CAAC,CACF,CAAC;oBACH,CAAC;gBACF,CAAC;YACF,CAAC,QAAQ,iBAAiB,EAAE;QAC7B,CAAC;IACF,CAAC;IAED;;;;;;;;;OASG;IACK,oBAAoB,CAC3B,UAAkB,EAClB,SAAyC,EACzC,cAAwC,EACxC,eAAiD,EACjD,cAAuB;QAOvB,wDAAwD;QACxD,IAAI,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;YAC7B,OAAO;gBACN,YAAY,EAAE,EAAE;gBAChB,eAAe,EAAE,EAAE;gBACnB,YAAY,EAAE,KAAK;aACnB,CAAC;QACH,CAAC;QAED,IAAI,YAAY,IAAI,SAAS,EAAE,CAAC;YAC/B,IAAI,SAAS,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACvC,OAAO;oBACN,YAAY,EAAE,EAAE;oBAChB,eAAe,EAAE,EAAE;oBACnB,YAAY,EAAE,KAAK;iBACnB,CAAC;YACH,CAAC;YACD,iEAAiE;YACjE,2EAA2E;YAC3E,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;YAC3D,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;YAE7D,mGAAmG;YACnG,MAAM,cAAc,GAKd,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;gBAClC,kEAAkE;gBAClE,iEAAiE;gBACjE,wEAAwE;gBACxE,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;gBAC5D,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;gBAC9D,MAAM,MAAM,GAAG,IAAI,CAAC,oBAAoB,CACvC,UAAU,EACV,CAAC,EACD,cAAc,EACd,eAAe,EACf,cAAc,CACd,CAAC;gBACF,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;oBACtB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;wBAC/C,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;4BAC9B,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC;wBAC5B,CAAC;oBACF,CAAC;oBACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;wBAChD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;4BAC/B,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;wBAC7B,CAAC;oBACF,CAAC;gBACF,CAAC;gBACD,OAAO,MAAM,CAAC;YACf,CAAC,CAAC,CAAC;YAEH,MAAM,eAAe,GAAG,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;YAE/E,+EAA+E;YAC/E,sFAAsF;YACtF,IAAI,SAAS,CAAC,eAAe,KAAK,eAAe,CAAC,EAAE,EAAE,CAAC;gBACtD,iFAAiF;gBACjF,2EAA2E;gBAC3E,4CAA4C;gBAC5C,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC5C,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;gBACxF,CAAC;gBAED,MAAM,KAAK,GAAG,cAAc;qBAC1B,GAAG,CAAC,CAAC,CAAC,EAAE;oBACR,qEAAqE;oBACrE,6DAA6D;oBAC7D,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;wBACjB,OAAO,EAAE,CAAC;oBACX,CAAC;oBACD,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CACxE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CACjB,CAAC;oBACF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;wBAC3B,OAAO,EAAE,CAAC;oBACX,CAAC;oBACD,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;gBACrF,CAAC,CAAC;qBACD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAC5B,MAAM,gBAAgB,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBAC7E,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC3C,OAAO;oBACN,YAAY,EAAE,EAAE;oBAChB,eAAe,EAAE,IAAI,CAAC,uBAAuB,CAAC,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC;oBAC5E,YAAY,EAAE,gBAAgB;iBAC9B,CAAC;YACH,CAAC;YAED,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACvE,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC7E,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,eAAe,GAAG,CAAC,CAAC;YAC3F,MAAM,eAAe,GAAG,WAAW;iBACjC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;iBAClC,IAAI,CAAC,IAAI,eAAe,GAAG,CAAC,CAAC;YAE/B,+EAA+E;YAC/E,8EAA8E;YAC9E,4EAA4E;YAC5E,8EAA8E;YAC9E,oBAAoB;YACpB,MAAM,SAAS,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YACxD,IAAI,SAAS,EAAE,CAAC;gBACf,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;oBAC/C,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;wBAC7B,OAAO,cAAc,CAAC,GAAG,CAAC,CAAC;oBAC5B,CAAC;gBACF,CAAC;gBACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC;oBAChD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;wBAC9B,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;oBAC7B,CAAC;gBACF,CAAC;gBACD,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;YACxF,CAAC;YAED,OAAO;gBACN,YAAY,EAAE,IAAI,CAAC,uBAAuB,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC;gBACzE,eAAe,EAAE,IAAI,CAAC,uBAAuB,CAAC,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC;gBAClF,YAAY,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;aACtD,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,QAAQ,CAAC,CAAC;QAE/F,wFAAwF;QACxF,IACC,YAAY,IAAI,SAAS;YACzB,SAAS,CAAC,UAAU,KAAK,kBAAkB,CAAC,EAAE;YAC9C,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC;YACzB,SAAS,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAC3B,CAAC;YACF,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;QACxF,CAAC;QAED,+EAA+E;QAC/E,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,CAC5C,UAAU,EACV,SAAS,EACT,UAAU,EAAE,IAAI,EAChB,cAAc,EACd,eAAe,CACf,CAAC;QAEF,MAAM,KAAK,GACV,UAAU,EAAE,SAAS,IAAI,CAAC,UAAU,EAAE,WAAW,IAAI,UAAU,EAAE,QAAQ,KAAK,cAAc,CAAC,CAAC;QAC/F,OAAO;YACN,YAAY,EAAE,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;YACrC,eAAe,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;YACzC,YAAY,EAAE,KAAK;SACnB,CAAC;IACH,CAAC;IAED;;;;;;;;;;OAUG;IACK,qBAAqB,CAC5B,UAAkB,EAClB,UAAuB,EACvB,IAA0C,EAC1C,cAAwC,EACxC,eAAiD;QAEjD,IAAI,IAAI,GAAG,UAAU,CAAC;QACtB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,IAAI,IAAI,GAAG,CAAC;QACb,CAAC;QACD,IAAI,IAAI,UAAU,CAAC,QAAQ,CAAC;QAE5B,IAAI,aAAa,GAAG,IAAI,CAAC,sBAAsB,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAEtE,IAAI,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,yFAAyF;YACzF,yFAAyF;YACzF,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,MAAM,EAAE,CAAC;gBACzD,OAAO,wBAAwB,aAAa,GAAG,CAAC;YACjD,CAAC;iBAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,SAAS,EAAE,CAAC;gBACnE,OAAO,oBAAoB,aAAa,GAAG,CAAC;YAC7C,CAAC;QACF,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC;QAC9E,IAAI,QAAQ,GAAG,YAAY,CAAC;QAC5B,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;YACjD,UAAU,EAAE,CAAC;YACb,QAAQ,GAAG,GAAG,YAAY,GAAG,UAAU,EAAE,CAAC;QAC3C,CAAC;QAED,IAAI,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;YAC5E,MAAM,iBAAiB,GAAG,EAAE,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC1C,MAAM,gBAAgB,GAAG,GAAG,QAAQ,GAAG,CAAC,EAAE,CAAC;gBAC3C,eAAe,CAAC,gBAAgB,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAChD,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC1C,CAAC;YACD,QAAQ,GAAG,aAAa,CAAC;YACzB,aAAa,GAAG,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;QACrD,CAAC;aAAM,CAAC;YACP,eAAe,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC5E,CAAC;QAED,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,MAAM,EAAE,CAAC;YACzD,OAAO,GAAG,aAAa,MAAM,QAAQ,EAAE,CAAC;QACzC,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,SAAS,EAAE,CAAC;YACnE,OAAO,GAAG,aAAa,OAAO,QAAQ,EAAE,CAAC;QAC1C,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,WAAW,EAAE,CAAC;YACrE,OAAO,GAAG,aAAa,MAAM,QAAQ,EAAE,CAAC;QACzC,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,QAAQ,EAAE,CAAC;YAClE,OAAO,GAAG,aAAa,MAAM,QAAQ,EAAE,CAAC;QACzC,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,kBAAkB,EAAE,CAAC;YAC5E,OAAO,GAAG,aAAa,OAAO,QAAQ,EAAE,CAAC;QAC1C,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,eAAe,EAAE,CAAC;YACzE,OAAO,GAAG,aAAa,OAAO,QAAQ,EAAE,CAAC;QAC1C,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,QAAQ,EAAE,CAAC;YAClE,OAAO,YAAY,aAAa,KAAK,QAAQ,GAAG,CAAC;QAClD,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,WAAW,EAAE,CAAC;YACrE,OAAO,gBAAgB,aAAa,KAAK,QAAQ,GAAG,CAAC;QACtD,CAAC;aAAM,IAAI,UAAU,CAAC,UAAU,KAAK,kBAAkB,CAAC,EAAE,EAAE,CAAC;YAC5D,OAAO,GAAG,QAAQ,OAAO,aAAa,EAAE,CAAC;QAC1C,CAAC;QAED,MAAM,IAAI,YAAY,CAAC,8BAA8B,CAAC,UAAU,EAAE,wBAAwB,EAAE;YAC3F,UAAU,EAAE,UAAU,CAAC,UAAU;SACjC,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACK,sBAAsB,CAAC,IAAY,EAAE,cAAwC;QACpF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,kBAAkB,GAAa,EAAE,CAAC;QAExC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC;YAC5B,IAAI,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;gBACxC,cAAc,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC;YACjC,CAAC;YACD,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACnC,CAAC;QAED,OAAO,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAED;;;;;;OAMG;IACK,sBAAsB,CAAC,QAA0B;QACxD,IAAI,CAAC,QAAQ,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,eAAe,CAAC,GAAG,EAAE,CAAC;YAC/D,OAAO,KAAK,CAAC;QACd,CAAC;aAAM,IAAI,QAAQ,KAAK,eAAe,CAAC,EAAE,EAAE,CAAC;YAC5C,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,IAAI,YAAY,CAAC,8BAA8B,CAAC,UAAU,EAAE,yBAAyB,EAAE;YAC5F,QAAQ;SACR,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;;OAOG;IACK,uBAAuB,CAAC,IAAY,EAAE,SAAiB;QAC9D,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,OAAO,EAAE,CAAC;QACX,CAAC;QACD,OAAO,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC;IACpD,CAAC;IAED;;;;;;OAMG;IACK,iBAAiB,CAAC,KAAc,EAAE,IAA+B;QACxE,IAAI,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,GAAG,GAAqC,EAAE,CAAC;YACjD,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;gBACzB,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YAC/C,CAAC;YACD,OAAO;gBACN,CAAC,EAAE,GAAG;aACN,CAAC;QACH,CAAC;QAED,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC7C,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC1C,CAAC;aAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QACjD,CAAC;QAED,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACxB,CAAC;aAAM,IAAI,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7B,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC;QAChC,CAAC;QAED,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;IAC1C,CAAC;IAED;;;;OAIG;IACK,eAAe;QACtB,OAAO,sBAAsB,CAAC,IAAI,CACjC,IAAI,QAAQ,CAAC;YACZ,UAAU,EAAE,YAAY;YACxB,GAAG,IAAI,CAAC,sBAAsB,EAAE;SAChC,CAAC,EACF;YACC,eAAe,EAAE;gBAChB,qBAAqB,EAAE,IAAI;aAC3B;SACD,CACD,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,gBAAgB;QACvB,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC,CAAC;IACpD,CAAC;IAED;;;;OAIG;IACK,sBAAsB;QAC7B,MAAM,cAAc,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB,CAAC;YACjE,CAAC,CAAC,EAAE,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,mBAAmB,EAAE;YACtD,CAAC,CAAC,SAAS,CAAC;QAEb,IACC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC;YAC5C,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;YACxC,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,aAAa,EACtC,CAAC;YACF,OAAO;gBACN,WAAW,EAAE;oBACZ,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW;oBACrC,eAAe,EAAE,IAAI,CAAC,OAAO,CAAC,eAAe;iBAC7C;gBACD,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;gBAC/B,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;gBAC3B,cAAc;gBACd,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW;aACrC,CAAC;QACH,CAAC;QAED,OAAO;YACN,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ;YAC/B,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM;YAC3B,cAAc;YACd,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW;SACrC,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,WAAW,CAAC,SAAiB;QAC1C,IAAI,CAAC;YACJ,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAE7C,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;YAE1E,8DAA8D;YAC9D,OAAO,MAAM,CAAC,KAAK,EAAE,WAAW,KAAK,UAAU,CAAC;QACjD,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAED;;;;;;;;;;;;OAYG;IACK,KAAK,CAAC,aAAa,CAC1B,UAA+B,EAC/B,cAGG,EACH,UAAwB,EACxB,MAAe,EACf,KAAc,EACd,cAAuB,EACvB,YAAqB;QAKrB,IAAI,CAAC;YACJ,MAAM,UAAU,GAAG,KAAK,IAAI,8BAA8B,CAAC,cAAc,CAAC;YAC1E,MAAM,WAAW,GAAG,IAAI,CAAC,uBAAuB,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;YACjF,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC,uBAAuB,CAAC,YAAY,CAAC,CAAC;YACvF,MAAM,UAAU,GAAG,IAAI,CAAC,0BAA0B,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;YAE5E,MAAM,WAAW,GAAG,IAAI,CAAC,oBAAoB,CAC5C,EAAE,EACF,UAAU,EACV,cAAc,EACd,eAAe,EACf,WAAW,CAAC,YAAY,CACxB,CAAC;YAEF,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;gBAC3B,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;YAC5C,CAAC;YAED,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;gBAC9B,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAChD,WAAW,CAAC,eAAe,EAC3B,UAAU,EACV,cAAc,EACd,eAAe,EACf,UAAU,EACV,UAAU,CACV,CAAC;gBAEF,OAAO;oBACN,QAAQ,EAAE,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC,QAAQ,CAAC;oBACzD,MAAM,EAAE,UAAU,CAAC,MAAM;iBACzB,CAAC;YACH,CAAC;YAED,MAAM,aAAa,GAAG,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;YACxE,MAAM,eAAe,GAAG,IAAI,CAAC,yBAAyB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;YAEnF,MAAM,WAAW,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,eAAe,CAAC;gBAC9D,CAAC,CAAC,MAAM,IAAI,CAAC,oBAAoB,CAC/B,aAAa,EACb,WAAW,CAAC,eAAe,EAC3B,cAAc,EACd,eAAe,EACf,eAAe,EACf,WAAW,CAAC,SAAS,EACrB,WAAW,CAAC,aAAa,EACzB,UAAU,EACV,UAAU,CACV;gBACF,CAAC,CAAC,MAAM,IAAI,CAAC,sBAAsB,CACjC,aAAa,EACb,cAAc,EACd,eAAe,EACf,eAAe,EACf,WAAW,CAAC,SAAS,EACrB,WAAW,CAAC,aAAa,EACzB,UAAU,EACV,UAAU,CACV,CAAC;YAEJ,OAAO;gBACN,QAAQ,EAAE,IAAI,CAAC,qBAAqB,CAAC,WAAW,CAAC,QAAQ,CAAC;gBAC1D,MAAM,EAAE,WAAW,CAAC,MAAM;aAC1B,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,IAAI,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,2BAA2B,CAAC,EAAE,CAAC;gBAC7D,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,mBAAmB,EACnB;oBACC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;iBACjC,EACD,GAAG,CACH,CAAC;YACH,CAAC;YACD,MAAM,IAAI,YAAY,CACrB,8BAA8B,CAAC,UAAU,EACzC,aAAa,EACb,SAAS,EACT,GAAG,CACH,CAAC;QACH,CAAC;IACF,CAAC;IAED;;;;;;;OAOG;IACK,uBAAuB,CAC9B,cAGG,EACH,cAAuB;QAMvB,IAAI,SAAS,GAAuB,EAAE,CAAC,WAAW,CAAC,cAAc,CAAC;YACjE,CAAC,CAAC,GAAG,cAAc,OAAO;YAC1B,CAAC,CAAC,SAAS,CAAC;QACb,IAAI,YAAY,GAAuB,cAAc,CAAC;QACtD,IAAI,aAAa,GAAG,IAAI,CAAC;QAEzB,IAAI,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;YACnC,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,IAAI,YAAY,CAAC,8BAA8B,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;YACjF,CAAC;YAED,KAAK,MAAM,YAAY,IAAI,cAAc,EAAE,CAAC;gBAC3C,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CACzD,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,YAAY,CAAC,QAAQ,CACzC,CAAC;gBACF,IAAI,cAAc,EAAE,SAAS,EAAE,CAAC;oBAC/B,SAAS,GAAG,SAAS,CAAC;oBACtB,YAAY,GAAG,SAAS,CAAC;gBAC1B,CAAC;qBAAM,CAAC;oBACP,SAAS,GAAG,GAAG,YAAY,CAAC,QAAkB,OAAO,CAAC;oBACtD,YAAY,GAAG,YAAY,CAAC,QAAkB,CAAC;gBAChD,CAAC;gBACD,aAAa,GAAG,YAAY,CAAC,aAAa,KAAK,aAAa,CAAC,SAAS,CAAC;YACxE,CAAC;QACF,CAAC;QAED,OAAO;YACN,SAAS;YACT,YAAY;YACZ,aAAa;SACb,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,uBAAuB,CAAC,YAAqB;QAIpD,OAAO;YACN,cAAc,EAAE,EAAE,cAAc,EAAE,aAAa,EAAE;YACjD,eAAe,EAAE;gBAChB,CAAC,IAAI,8BAA8B,CAAC,cAAc,EAAE,CAAC,EAAE;oBACtD,CAAC,EAAE,YAAY,IAAI,8BAA8B,CAAC,oBAAoB;iBACtE;aACD;SACD,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,kBAAkB,CAAC,YAAoB;QAC9C,IAAI,aAAa,GAAG,6BAA6B,CAAC;QAClD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,aAAa,IAAI,QAAQ,YAAY,EAAE,CAAC;QACzC,CAAC;QACD,OAAO,aAAa,CAAC;IACtB,CAAC;IAED;;;;;OAKG;IACK,YAAY,CAAC,MAAe;QACnC,OAAO,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,SAAS,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/F,CAAC;IAED;;;;;OAKG;IACK,YAAY,CAAC,GAAsC;QAC1D,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACvF,CAAC;IAED;;;;;;OAMG;IACK,0BAA0B,CACjC,MAA0B,EAC1B,eAAiD;QAEjD,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACtB,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YACvB,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,MAAM,iBAAiB,GACtB,eAAe,CAAC,IAAI,8BAA8B,CAAC,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;QACzE,MAAM,eAAe,GAAG,OAAO,CAAC,8BAA8B,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QAClF,OAAO,eAAe,KAAK,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACnE,CAAC;IAED;;;;;;;;;;OAUG;IACK,KAAK,CAAC,mBAAmB,CAChC,eAAuB,EACvB,UAAmC,EACnC,cAAwC,EACxC,eAAiD,EACjD,MAA0B,EAC1B,UAAkB;QAKlB,IAAI,UAAU,GAAG,6BAA6B,CAAC;QAC/C,IAAI,EAAE,CAAC,WAAW,CAAC,eAAe,CAAC,EAAE,CAAC;YACrC,UAAU,IAAI,QAAQ,eAAe,CAAC,IAAI,EAAE,EAAE,CAAC;QAChD,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC7C,MAAM,aAAa,GAAuC,EAAE,CAAC;QAC7D,IAAI,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,gBAA8D,CAAC;QAEnE,qFAAqF;QACrF,2EAA2E;QAC3E,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;QAErD,GAAG,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,IAAI,CACzC,IAAI,cAAc,CAAC;gBAClB,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;gBACjC,gBAAgB,EAAE,UAAU;gBAC5B,wBAAwB,EAAE,cAAc;gBACxC,yBAAyB,EAAE,eAAe;gBAC1C,iBAAiB,EAAE,YAAY;gBAC/B,KAAK,EAAE,cAAc;aACrB,CAAC,CACF,CAAC;YAEF,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;YAChD,gBAAgB,GAAG,UAAU,CAAC,gBAAgB,CAAC;YAC/C,YAAY,GAAG,gBAAgB,CAAC;YAEhC,mFAAmF;YACnF,IAAI,aAAa,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;gBACxC,MAAM;YACP,CAAC;QACF,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE;QAEtC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,GAAG,UAAU,CAAC;QAClD,MAAM,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;QAEtF,IAAI,YAAgC,CAAC;QACrC,IAAI,OAAO,EAAE,CAAC;YACb,MAAM,WAAW,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAClE,MAAM,YAAY,GAAqC;gBACtD,CAAC,8BAA8B,CAAC,cAAc,CAAC,EAC9C,WAAW,CAAC,8BAA8B,CAAC,cAAc,CAAC;gBAC3D,CAAC,IAAI,CAAC,WAAW,CAAC,QAAkB,CAAC,EAAE,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,QAAkB,CAAC;aACvF,CAAC;YACF,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,iBAAiB,GAAG,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;YAClD,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;gBAC5B,MAAM,SAAS,GAAqC,EAAE,CAAC;gBACvD,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;oBAC/B,MAAM,GAAG,GAAG,IAAc,CAAC;oBAC3B,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;wBAC9B,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;oBAC5B,CAAC;gBACF,CAAC;gBACD,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,8BAA8B,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC;oBACxE,SAAS,CAAC,8BAA8B,CAAC,cAAc,CAAC;wBACvD,IAAI,CAAC,8BAA8B,CAAC,cAAc,CAAC,CAAC;gBACtD,CAAC;gBACD,OAAO,SAAS,CAAC;YAClB,CAAC,CAAC;YACH,CAAC,CAAC,gBAAgB,CAAC;QAEpB,OAAO;YACN,QAAQ,EAAE,iBAAiB;YAC3B,MAAM,EAAE,YAAY;SACpB,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;OAYG;IACK,KAAK,CAAC,sBAAsB,CACnC,aAAqB,EACrB,cAAwC,EACxC,eAAiD,EACjD,oBAAwC,EACxC,SAA6B,EAC7B,aAAsB,EACtB,MAA0B,EAC1B,UAAkB;QAKlB,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,IAAI,CACpC,IAAI,YAAY,CAAC;YAChB,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;YACjC,SAAS,EAAE,SAAS;YACpB,sBAAsB,EAAE,aAAa;YACrC,wBAAwB,EAAE,cAAc;YACxC,yBAAyB,EAAE,eAAe;YAC1C,oBAAoB,EAAE,oBAAoB;YAC1C,KAAK,EAAE,UAAU;YACjB,gBAAgB,EAAE,aAAa;YAC/B,iBAAiB,EAAE,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;SAC5C,CAAC,CACF,CAAC;QAEF,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAuC,CAAC;QAC7E,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,IAAI,QAAQ,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC3E,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,IAAI,CAClC,IAAI,YAAY,CAAC;gBAChB,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;gBACjC,SAAS,EAAE,SAAS;gBACpB,sBAAsB,EAAE,aAAa;gBACrC,wBAAwB,EAAE,cAAc;gBACxC,yBAAyB,EAAE,eAAe;gBAC1C,oBAAoB,EAAE,oBAAoB;gBAC1C,KAAK,EAAE,CAAC;gBACR,gBAAgB,EAAE,aAAa;gBAC/B,iBAAiB,EAAE,OAAO,CAAC,gBAAgB;aAC3C,CAAC,CACF,CAAC;YACF,OAAO,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO;YACN,QAAQ;YACR,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS;SACzE,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;OAaG;IACK,KAAK,CAAC,oBAAoB,CACjC,aAAqB,EACrB,gBAAwB,EACxB,cAAwC,EACxC,eAAiD,EACjD,oBAAwC,EACxC,SAA6B,EAC7B,aAAsB,EACtB,MAA0B,EAC1B,UAAkB;QAKlB,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAC1C,MAAM,gBAAgB,GAAuC,EAAE,CAAC;QAChE,IAAI,gBAAgB,GAAiD,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAE/F,GAAG,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,IAAI,CACpC,IAAI,YAAY,CAAC;gBAChB,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;gBACjC,SAAS,EAAE,SAAS;gBACpB,sBAAsB,EAAE,aAAa;gBACrC,gBAAgB,EAAE,gBAAgB;gBAClC,wBAAwB,EAAE,cAAc;gBACxC,yBAAyB,EAAE,eAAe;gBAC1C,oBAAoB,EAAE,oBAAoB;gBAC1C,KAAK,EAAE,UAAU,GAAG,gBAAgB,CAAC,MAAM;gBAC3C,gBAAgB,EAAE,aAAa;gBAC/B,iBAAiB,EAAE,gBAAgB;aACnC,CAAC,CACF,CAAC;YAEF,gBAAgB,CAAC,IAAI,CAAC,GAAI,CAAC,OAAO,CAAC,KAAK,IAAI,EAAE,CAAwC,CAAC,CAAC;YACxF,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC;QAC7C,CAAC,QAAQ,gBAAgB,CAAC,MAAM,GAAG,UAAU,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE;QAE9E,OAAO;YACN,QAAQ,EAAE,gBAAgB;YAC1B,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC;SAC3C,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,qBAAqB,CAAC,QAA4C;QACzE,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAC1B,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;YACtC,OAAO,mBAAmB,CAAC,eAAe,CAAC,YAAiB,EAAE;gBAC7D,8BAA8B,CAAC,cAAc;aAC7C,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACK,wBAAwB,CAAC,UAAoD;QAKpF,IAAI,mBAAuC,CAAC;QAC5C,IAAI,cAAoD,CAAC;QACzD,IAAI,eAAoE,CAAC;QAEzE,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,MAAM,WAAW,GAAa,EAAE,CAAC;YAEjC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;gBAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC;gBAEvF,IAAI,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;oBAC9B,MAAM,IAAI,YAAY,CAAC,8BAA8B,CAAC,UAAU,EAAE,kBAAkB,EAAE;wBACrF,QAAQ,EAAE,CAAC,CAAC,QAAQ;qBACpB,CAAC,CAAC;gBACJ,CAAC;gBAED,MAAM,aAAa,GAAG,IAAI,CAAC,CAAC,QAAkB,EAAE,CAAC;gBACjD,MAAM,kBAAkB,GAAG,IAAI,CAAC,CAAC,QAAkB,EAAE,CAAC;gBACtD,cAAc,KAAK,EAAE,CAAC;gBACtB,eAAe,KAAK,EAAE,CAAC;gBACvB,cAAc,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,QAAkB,CAAC;gBACrD,eAAe,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;gBAC9C,WAAW,CAAC,IAAI,CAAC,GAAG,aAAa,MAAM,kBAAkB,EAAE,CAAC,CAAC;YAC9D,CAAC;YAED,mBAAmB,GAAG,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC;IACjE,CAAC;IAED;;;;;;;;OAQG;IACK,yBAAyB,CAChC,UAAmC,EACnC,cAAwC;QAExC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAChC,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,OAAO,UAAU;aACf,GAAG,CAAC,CAAC,CAAC,EAAE;YACR,MAAM,KAAK,GAAG,MAAM,CAAW,EAAE,CAAC;YAClC,cAAc,CAAC,KAAK,CAAC,GAAG,CAAW,CAAC;YACpC,OAAO,KAAK,CAAC;QACd,CAAC,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,CAAC","sourcesContent":["// Copyright 2024 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport {\n\ttype AttributeValue,\n\tBatchWriteItemCommand,\n\ttype CreateTableCommandInput,\n\tDynamoDB,\n\ttype DynamoDBClientConfig,\n\ttype GlobalSecondaryIndex,\n\tQueryCommand,\n\tScanCommand as RawScanCommand,\n\twaitUntilTableExists,\n\twaitUntilTableNotExists\n} from \"@aws-sdk/client-dynamodb\";\nimport {\n\tBatchWriteCommand,\n\tDeleteCommand,\n\tDynamoDBDocumentClient,\n\tGetCommand,\n\tPutCommand,\n\tScanCommand\n} from \"@aws-sdk/lib-dynamodb\";\nimport { type NativeAttributeValue, unmarshall } from \"@aws-sdk/util-dynamodb\";\nimport { ContextIdHelper, ContextIdStore, type IContextIds } from \"@twin.org/context\";\nimport {\n\tBaseError,\n\tCoerce,\n\tComponentFactory,\n\tConverter,\n\tGeneralError,\n\tGuards,\n\tHealthStatus,\n\ttype IHealth,\n\tIs,\n\ttype IValidationFailure,\n\tObjectHelper,\n\tValidation\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\tEntityStorageHelper,\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 { IDynamoDbEntityStorageConnectorConfig } from \"./models/IDynamoDbEntityStorageConnectorConfig.js\";\nimport type { IDynamoDbEntityStorageConnectorConstructorOptions } from \"./models/IDynamoDbEntityStorageConnectorConstructorOptions.js\";\n\n/**\n * Class for performing entity storage operations using Dynamo DB.\n */\nexport class DynamoDbEntityStorageConnector<\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<DynamoDbEntityStorageConnector>();\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: IDynamoDbEntityStorageConnectorConfig;\n\n\t/**\n\t * Create a new instance of DynamoDbEntityStorageConnector.\n\t * @param options The options for the connector.\n\t */\n\tconstructor(options: IDynamoDbEntityStorageConnectorConstructorOptions) {\n\t\tGuards.object(DynamoDbEntityStorageConnector.CLASS_NAME, nameof(options), options);\n\t\tGuards.stringValue(\n\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.entitySchema),\n\t\t\toptions.entitySchema\n\t\t);\n\t\tGuards.object<IDynamoDbEntityStorageConnectorConfig>(\n\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config),\n\t\t\toptions.config\n\t\t);\n\n\t\toptions.config.authMode ??= \"credentials\";\n\n\t\tif (options.config.authMode === \"credentials\") {\n\t\t\tGuards.stringValue(\n\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tnameof(options.config.accessKeyId),\n\t\t\t\toptions.config.accessKeyId\n\t\t\t);\n\t\t\tGuards.stringValue(\n\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tnameof(options.config.secretAccessKey),\n\t\t\t\toptions.config.secretAccessKey\n\t\t\t);\n\t\t}\n\t\tGuards.stringValue(\n\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.region),\n\t\t\toptions.config.region\n\t\t);\n\t\tGuards.stringValue(\n\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tnameof(options.config.tableName),\n\t\t\toptions.config.tableName\n\t\t);\n\n\t\tthis._partitionContextIds = options.partitionContextIds;\n\n\t\tthis._entitySchemaName = options.entitySchema;\n\t\tthis._entitySchema = EntitySchemaFactory.get(options.entitySchema);\n\t\tthis._primaryKey = EntitySchemaHelper.getPrimaryKey<T>(this._entitySchema);\n\n\t\tthis._config = options.config;\n\t\tthis._config.endpoint = Is.stringValue(this._config.endpoint)\n\t\t\t? this._config.endpoint\n\t\t\t: undefined;\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 DynamoDbEntityStorageConnector.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\tconst dbConnection = this.createConnection();\n\t\t\tawait dbConnection.describeTable({ TableName: this._config.tableName });\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tstatus: HealthStatus.Ok,\n\t\t\t\t\tdescription: \"healthDescription\",\n\t\t\t\t\tdata: { tableName: this._config.tableName }\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: DynamoDbEntityStorageConnector.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: { tableName: this._config.tableName }\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 * Bootstrap the component by creating and initializing any resources it needs.\n\t * @param nodeLoggingComponentType The node logging component type.\n\t * @returns True if the bootstrapping process was successful.\n\t */\n\tpublic async bootstrap(nodeLoggingComponentType?: string): Promise<boolean> {\n\t\tconst nodeLogging = ComponentFactory.getIfExists<ILoggingComponent>(nodeLoggingComponentType);\n\n\t\tif (!(await this.tableExists(this._config.tableName))) {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"tableCreating\",\n\t\t\t\tdata: {\n\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t}\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tconst dbConnection = this.createConnection();\n\n\t\t\t\tconst tableParams: CreateTableCommandInput = {\n\t\t\t\t\tAttributeDefinitions: [],\n\t\t\t\t\tKeySchema: [],\n\t\t\t\t\tProvisionedThroughput: {\n\t\t\t\t\t\tReadCapacityUnits: 1,\n\t\t\t\t\t\tWriteCapacityUnits: 1\n\t\t\t\t\t},\n\t\t\t\t\tTableName: this._config.tableName\n\t\t\t\t};\n\n\t\t\t\t// We always add a partition key to the table as a non optional hash key\n\t\t\t\t// is always required when querying using sort parameters\n\t\t\t\ttableParams.AttributeDefinitions?.push({\n\t\t\t\t\tAttributeName: DynamoDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\tAttributeType: \"S\"\n\t\t\t\t});\n\t\t\t\ttableParams.KeySchema?.push({\n\t\t\t\t\tAttributeName: DynamoDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\tKeyType: \"HASH\"\n\t\t\t\t});\n\n\t\t\t\tconst gsi: GlobalSecondaryIndex[] = [];\n\n\t\t\t\tif (Is.arrayValue(this._entitySchema.properties)) {\n\t\t\t\t\tfor (const prop of this._entitySchema.properties) {\n\t\t\t\t\t\tif (prop.isPrimary) {\n\t\t\t\t\t\t\ttableParams.AttributeDefinitions?.push({\n\t\t\t\t\t\t\t\tAttributeName: prop.property as string,\n\t\t\t\t\t\t\t\tAttributeType: prop.type === \"integer\" || prop.type === \"number\" ? \"N\" : \"S\"\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttableParams.KeySchema?.push({\n\t\t\t\t\t\t\t\tAttributeName: prop.property as string,\n\t\t\t\t\t\t\t\tKeyType: \"RANGE\"\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (Is.stringValue(prop.sortDirection) || prop.isSecondary) {\n\t\t\t\t\t\t\t// You can only query and sort items if you have a secondary index\n\t\t\t\t\t\t\t// defined for the property\n\t\t\t\t\t\t\ttableParams.AttributeDefinitions?.push({\n\t\t\t\t\t\t\t\tAttributeName: prop.property as string,\n\t\t\t\t\t\t\t\tAttributeType: prop.type === \"integer\" || prop.type === \"number\" ? \"N\" : \"S\"\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tgsi.push({\n\t\t\t\t\t\t\t\tIndexName: `${prop.property as string}Index`,\n\t\t\t\t\t\t\t\tKeySchema: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tAttributeName: DynamoDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\t\t\t\t\t\tKeyType: \"HASH\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tAttributeName: prop.property as string,\n\t\t\t\t\t\t\t\t\t\tKeyType: \"RANGE\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\tProjection: {\n\t\t\t\t\t\t\t\t\tProjectionType: \"ALL\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tProvisionedThroughput: {\n\t\t\t\t\t\t\t\t\tReadCapacityUnits: 1,\n\t\t\t\t\t\t\t\t\tWriteCapacityUnits: 1\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (gsi.length > 0) {\n\t\t\t\t\ttableParams.GlobalSecondaryIndexes = gsi;\n\t\t\t\t}\n\n\t\t\t\tawait dbConnection.createTable(tableParams);\n\n\t\t\t\t// Wait for table to exist\n\t\t\t\tawait waitUntilTableExists(\n\t\t\t\t\t{\n\t\t\t\t\t\tclient: dbConnection,\n\t\t\t\t\t\tmaxWaitTime: 60\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tTableName: this._config.tableName\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\tts: Date.now(),\n\t\t\t\t\tmessage: \"tableCreated\",\n\t\t\t\t\tdata: {\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} catch (err) {\n\t\t\t\tif (BaseError.isErrorCode(err, \"ResourceInUseException\")) {\n\t\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\tts: Date.now(),\n\t\t\t\t\t\tmessage: \"tableExists\",\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tawait nodeLogging?.log({\n\t\t\t\t\t\tlevel: \"error\",\n\t\t\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\tts: Date.now(),\n\t\t\t\t\t\tmessage: \"tableCreateFailed\",\n\t\t\t\t\t\terror: BaseError.fromError(err),\n\t\t\t\t\t\tdata: {\n\t\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} else {\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"tableExists\",\n\t\t\t\tdata: {\n\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Get an entity.\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(DynamoDbEntityStorageConnector.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 docClient = this.createDocClient();\n\n\t\t\tif (Is.empty(secondaryIndex) && Is.empty(conditions)) {\n\t\t\t\tconst getCommand = new GetCommand({\n\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\tKey: {\n\t\t\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\t\tpartitionKey ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\t\t\t[this._primaryKey.property]: id\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tconst response = await docClient.send(getCommand);\n\n\t\t\t\tif (response.Item) {\n\t\t\t\t\treturn EntityStorageHelper.unPrepareEntity<T>(response.Item as T, [\n\t\t\t\t\t\tDynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t]);\n\t\t\t\t}\n\t\t\t\treturn undefined;\n\t\t\t}\n\n\t\t\tconst finalConditions: EntityCondition<T> = {\n\t\t\t\tconditions: []\n\t\t\t};\n\n\t\t\tif (Is.stringValue(secondaryIndex)) {\n\t\t\t\tfinalConditions.conditions.push({\n\t\t\t\t\tproperty: secondaryIndex,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: id\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tfinalConditions.conditions.push({\n\t\t\t\t\tproperty: this._primaryKey.property as string,\n\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\tvalue: id\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (Is.arrayValue(conditions)) {\n\t\t\t\tfor (const c of conditions) {\n\t\t\t\t\tfinalConditions.conditions.push({\n\t\t\t\t\t\tproperty: c.property as string,\n\t\t\t\t\t\tcomparison: ComparisonOperator.Equals,\n\t\t\t\t\t\tvalue: c.value\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst queryResult = await this.internalQuery(\n\t\t\t\tfinalConditions,\n\t\t\t\tundefined,\n\t\t\t\tundefined,\n\t\t\t\tundefined,\n\t\t\t\t1,\n\t\t\t\tsecondaryIndex as string,\n\t\t\t\tpartitionKey\n\t\t\t);\n\n\t\t\treturn queryResult.entities[0] as T;\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorCode(err, \"ResourceNotFoundException\")) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"tableDoesNotExist\",\n\t\t\t\t\t{\n\t\t\t\t\t\ttableName: this._config.tableName\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\tDynamoDbEntityStorageConnector.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}\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>(DynamoDbEntityStorageConnector.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\tconst prepared = EntityStorageHelper.prepareEntity(\n\t\t\tentity,\n\t\t\tthis._entitySchema,\n\t\t\tpartitionKey\n\t\t\t\t? [{ property: DynamoDbEntityStorageConnector._PARTITION_KEY, value: partitionKey }]\n\t\t\t\t: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tproperty: DynamoDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\t\t\tvalue: DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t{ nullBehavior: \"omit\" }\n\t\t);\n\n\t\tconst id = (prepared as { [id: string]: unknown })[this._primaryKey.property as string];\n\n\t\ttry {\n\t\t\tconst docClient = this.createDocClient();\n\n\t\t\tconst { conditionExpression, attributeNames, attributeValues } =\n\t\t\t\tthis.buildConditionExpression(conditions);\n\n\t\t\tconst putCommand = new PutCommand({\n\t\t\t\tTableName: this._config.tableName,\n\t\t\t\tItem: prepared as { [id: string]: unknown },\n\t\t\t\t// Only set the condition expression if we have conditions to match\n\t\t\t\t// and the primary key exists, otherwise we are creating a new object\n\t\t\t\tConditionExpression: Is.stringValue(conditionExpression)\n\t\t\t\t\t? `(attribute_exists(${this._primaryKey.property as string}) AND ${conditionExpression}) OR attribute_not_exists(${this._primaryKey.property as string})`\n\t\t\t\t\t: undefined,\n\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\tExpressionAttributeValues: attributeValues\n\t\t\t});\n\n\t\t\tawait docClient.send(putCommand);\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorName(err, \"ConditionalCheckFailedException\")) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (BaseError.isErrorCode(err, \"ResourceNotFoundException\")) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"tableDoesNotExist\",\n\t\t\t\t\t{\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t},\n\t\t\t\t\terr\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthrow new GeneralError(\n\t\t\t\tDynamoDbEntityStorageConnector.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(DynamoDbEntityStorageConnector.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\tconst preparedEntities = entities.map(entity =>\n\t\t\tEntityStorageHelper.prepareEntity(\n\t\t\t\tentity,\n\t\t\t\tthis._entitySchema,\n\t\t\t\tpartitionKey\n\t\t\t\t\t? [{ property: DynamoDbEntityStorageConnector._PARTITION_KEY, value: partitionKey }]\n\t\t\t\t\t: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tproperty: DynamoDbEntityStorageConnector._PARTITION_KEY,\n\t\t\t\t\t\t\t\tvalue: DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t],\n\t\t\t\t{ nullBehavior: \"omit\" }\n\t\t\t)\n\t\t);\n\n\t\ttry {\n\t\t\tconst docClient = this.createDocClient();\n\t\t\tconst chunkSize = 25;\n\n\t\t\tfor (let i = 0; i < preparedEntities.length; i += chunkSize) {\n\t\t\t\tconst chunk = preparedEntities.slice(i, i + chunkSize);\n\t\t\t\tawait docClient.send(\n\t\t\t\t\tnew BatchWriteCommand({\n\t\t\t\t\t\tRequestItems: {\n\t\t\t\t\t\t\t[this._config.tableName]: chunk.map(entity => ({\n\t\t\t\t\t\t\t\tPutRequest: {\n\t\t\t\t\t\t\t\t\tItem: entity as { [id: string]: unknown }\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorCode(err, \"ResourceNotFoundException\")) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"tableDoesNotExist\",\n\t\t\t\t\t{ tableName: this._config.tableName },\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\tDynamoDbEntityStorageConnector.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 the entity storage.\n\t * @returns Nothing.\n\t */\n\tpublic async empty(): Promise<void> {\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 pKey = partitionKey ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE;\n\n\t\t\tconst docClient = this.createDocClient();\n\t\t\tconst chunkSize = 25;\n\n\t\t\tlet exclusiveStartKey: { [key: string]: NativeAttributeValue } | undefined;\n\n\t\t\tdo {\n\t\t\t\tconst scanResult = await docClient.send(\n\t\t\t\t\tnew ScanCommand({\n\t\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\t\tFilterExpression: \"#partitionId = :partitionId\",\n\t\t\t\t\t\tExpressionAttributeNames: {\n\t\t\t\t\t\t\t\"#partitionId\": DynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t\t},\n\t\t\t\t\t\tExpressionAttributeValues: {\n\t\t\t\t\t\t\t\":partitionId\": pKey\n\t\t\t\t\t\t},\n\t\t\t\t\t\tExclusiveStartKey: exclusiveStartKey\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\t\tconst items = scanResult.Items ?? [];\n\n\t\t\t\tfor (let i = 0; i < items.length; i += chunkSize) {\n\t\t\t\t\tconst chunk = items.slice(i, i + chunkSize);\n\t\t\t\t\tawait docClient.send(\n\t\t\t\t\t\tnew BatchWriteCommand({\n\t\t\t\t\t\t\tRequestItems: {\n\t\t\t\t\t\t\t\t[this._config.tableName]: chunk.map(\n\t\t\t\t\t\t\t\t\t(item: { [key: string]: NativeAttributeValue }) => ({\n\t\t\t\t\t\t\t\t\t\tDeleteRequest: {\n\t\t\t\t\t\t\t\t\t\t\tKey: {\n\t\t\t\t\t\t\t\t\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\t\t\t\t\t\t\t\titem[DynamoDbEntityStorageConnector._PARTITION_KEY],\n\t\t\t\t\t\t\t\t\t\t\t\t[this._primaryKey.property as string]:\n\t\t\t\t\t\t\t\t\t\t\t\t\titem[this._primaryKey.property as string]\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\texclusiveStartKey = scanResult.LastEvaluatedKey;\n\t\t\t} while (exclusiveStartKey);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tDynamoDbEntityStorageConnector.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(DynamoDbEntityStorageConnector.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 docClient = this.createDocClient();\n\n\t\t\tconst { conditionExpression, attributeNames, attributeValues } =\n\t\t\t\tthis.buildConditionExpression(conditions);\n\n\t\t\tconst deleteCommand = new DeleteCommand({\n\t\t\t\tTableName: this._config.tableName,\n\t\t\t\tKey: {\n\t\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\tpartitionKey ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE,\n\t\t\t\t\t[this._primaryKey.property as string]: id\n\t\t\t\t},\n\t\t\t\tConditionExpression: conditionExpression,\n\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\tExpressionAttributeValues: attributeValues\n\t\t\t});\n\n\t\t\tawait docClient.send(deleteCommand);\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorName(err, \"ConditionalCheckFailedException\")) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (BaseError.isErrorCode(err, \"ResourceNotFoundException\")) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"tableDoesNotExist\",\n\t\t\t\t\t{\n\t\t\t\t\t\ttableName: this._config.tableName\n\t\t\t\t\t},\n\t\t\t\t\terr\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthrow new GeneralError(\n\t\t\t\tDynamoDbEntityStorageConnector.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 their IDs in a batch.\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(DynamoDbEntityStorageConnector.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 docClient = this.createDocClient();\n\t\t\tconst chunkSize = 25;\n\t\t\tconst primaryKeyProperty = this._primaryKey.property as string;\n\n\t\t\tfor (let i = 0; i < ids.length; i += chunkSize) {\n\t\t\t\tconst chunk = ids.slice(i, i + chunkSize);\n\t\t\t\tawait docClient.send(\n\t\t\t\t\tnew BatchWriteCommand({\n\t\t\t\t\t\tRequestItems: {\n\t\t\t\t\t\t\t[this._config.tableName]: chunk.map(id => ({\n\t\t\t\t\t\t\t\tDeleteRequest: {\n\t\t\t\t\t\t\t\t\tKey: {\n\t\t\t\t\t\t\t\t\t\t[primaryKeyProperty]: id,\n\t\t\t\t\t\t\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\t\t\t\t\t\tpartitionKey ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tDynamoDbEntityStorageConnector.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 entity storage by deleting the underlying table.\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: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\tts: Date.now(),\n\t\t\tmessage: \"tableDeleting\",\n\t\t\tdata: { tableName: this._config.tableName }\n\t\t});\n\n\t\ttry {\n\t\t\tconst dbConnection = this.createConnection();\n\n\t\t\tawait dbConnection.deleteTable({ TableName: this._config.tableName });\n\n\t\t\tawait waitUntilTableNotExists(\n\t\t\t\t{ client: dbConnection, maxWaitTime: 60 },\n\t\t\t\t{ TableName: this._config.tableName }\n\t\t\t);\n\n\t\t\tawait nodeLogging?.log({\n\t\t\t\tlevel: \"info\",\n\t\t\t\tsource: DynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\tts: Date.now(),\n\t\t\t\tmessage: \"tableDeleted\",\n\t\t\t\tdata: { tableName: this._config.tableName }\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: DynamoDbEntityStorageConnector.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?: {\n\t\t\tproperty: keyof T;\n\t\t\tsortDirection: SortDirection;\n\t\t}[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number\n\t): Promise<{\n\t\t/**\n\t\t * The entities, which can be partial if a limited keys list was provided.\n\t\t */\n\t\tentities: Partial<T>[];\n\t\t/**\n\t\t * An optional cursor, when defined can be used to call find to get more entities.\n\t\t */\n\t\tcursor?: string;\n\t}> {\n\t\tconst contextIds = await ContextIdStore.getContextIds();\n\t\tconst partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);\n\n\t\tif (!Is.empty(limit)) {\n\t\t\tconst validationFailures: IValidationFailure[] = [];\n\t\t\tValidation.integer(nameof(limit), limit, validationFailures, undefined, { minValue: 1 });\n\t\t\tValidation.asValidationError(\n\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"query\",\n\t\t\t\tvalidationFailures\n\t\t\t);\n\t\t}\n\n\t\tEntityStorageHelper.validateSortProperties(this._entitySchema, sortProperties);\n\t\tEntityStorageHelper.validateProperties(this._entitySchema, properties);\n\n\t\treturn this.internalQuery(\n\t\t\tconditions,\n\t\t\tsortProperties,\n\t\t\tproperties,\n\t\t\tcursor,\n\t\t\tlimit,\n\t\t\tundefined,\n\t\t\tpartitionKey\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\t\t\"#partitionId\": DynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t};\n\t\t\tconst attributeValues: { [id: string]: AttributeValue } = {\n\t\t\t\t\":partitionId\": {\n\t\t\t\t\tS: partitionKey ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst expressions = this.buildQueryParameters(\n\t\t\t\t\"\",\n\t\t\t\tconditions,\n\t\t\t\tattributeNames,\n\t\t\t\tattributeValues\n\t\t\t);\n\n\t\t\tif (expressions.noResults) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\tconst dbConnection = this.createConnection();\n\t\t\tlet total = 0;\n\t\t\tlet exclusiveStartKey: { [key: string]: AttributeValue } | undefined;\n\n\t\t\tdo {\n\t\t\t\tconst result = await dbConnection.send(\n\t\t\t\t\tnew QueryCommand({\n\t\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\t\tSelect: \"COUNT\",\n\t\t\t\t\t\tKeyConditionExpression: \"#partitionId = :partitionId\",\n\t\t\t\t\t\tFilterExpression: Is.stringValue(expressions.filterCondition)\n\t\t\t\t\t\t\t? expressions.filterCondition\n\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\t\t\tExclusiveStartKey: exclusiveStartKey\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\ttotal += result.Count ?? 0;\n\t\t\t\texclusiveStartKey = result.LastEvaluatedKey;\n\t\t\t} while (exclusiveStartKey);\n\n\t\t\treturn total;\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tDynamoDbEntityStorageConnector.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\tif (!Is.arrayValue(this._partitionContextIds)) {\n\t\t\treturn [];\n\t\t}\n\n\t\tconst contextIdsMap: { [id: string]: IContextIds } = {};\n\n\t\ttry {\n\t\t\tconst docClient = this.createDocClient();\n\t\t\tlet exclusiveStartKey: { [key: string]: NativeAttributeValue } | undefined;\n\n\t\t\tdo {\n\t\t\t\tconst scanResult = await docClient.send(\n\t\t\t\t\tnew ScanCommand({\n\t\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\t\tProjectionExpression: \"#partitionId\",\n\t\t\t\t\t\tExpressionAttributeNames: {\n\t\t\t\t\t\t\t\"#partitionId\": DynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t\t},\n\t\t\t\t\t\tExclusiveStartKey: exclusiveStartKey\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\t\tfor (const item of scanResult.Items ?? []) {\n\t\t\t\t\tconst partitionId = item[DynamoDbEntityStorageConnector._PARTITION_KEY] as string;\n\t\t\t\t\tif (Is.stringValue(partitionId) && !(partitionId in contextIdsMap)) {\n\t\t\t\t\t\tcontextIdsMap[partitionId] = ContextIdHelper.shortSplit(\n\t\t\t\t\t\t\tthis._partitionContextIds ?? [],\n\t\t\t\t\t\t\tpartitionId\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\texclusiveStartKey = scanResult.LastEvaluatedKey;\n\t\t\t} while (exclusiveStartKey);\n\t\t} catch (err) {\n\t\t\tthrow new GeneralError(\n\t\t\t\tDynamoDbEntityStorageConnector.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\n\t\treturn Object.values(contextIdsMap);\n\t}\n\n\t/**\n\t * Create the target connector for performing the migration it will use a temporary storage location.\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\t// We create a new table for the migration with a unique name to avoid conflicts with the existing table\n\t\t// This table will be swapped with the existing table once the migration is finalized.\n\t\tconst migrationTableName = `${this._config.tableName}Migration${Date.now()}`;\n\t\treturn new DynamoDbEntityStorageConnector<U>({\n\t\t\tentitySchema: newEntitySchema,\n\t\t\tconfig: {\n\t\t\t\t...this._config,\n\t\t\t\ttableName: migrationTableName\n\t\t\t},\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\t}\n\n\t/**\n\t * Finalize the migration by tearing down the old connector and replacing it with the new one.\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 logging component type to use for logging during the migration finalization.\n\t * @returns A promise that resolves when the migration is finalized.\n\t */\n\tpublic async finalizeMigration<U>(\n\t\ttargetConnector: DynamoDbEntityStorageConnector<U>,\n\t\toptions?: IMigrationOptions,\n\t\tloggingComponentType?: string\n\t): Promise<DynamoDbEntityStorageConnector<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 DynamoDbEntityStorageConnector<U>({\n\t\t\tentitySchema: targetConnector._entitySchemaName,\n\t\t\tconfig: this._config,\n\t\t\tpartitionContextIds: this._partitionContextIds\n\t\t});\n\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 ?? DynamoDbEntityStorageConnector._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\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\"finalizeMigrationFailedBootstrap\",\n\t\t\tundefined\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 the migration with.\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 the migration progress.\n\t * @returns A promise that resolves when the migration is cleaned up.\n\t */\n\tpublic async cleanupMigration<U>(\n\t\ttargetConnector: IEntityStorageConnector<U> | undefined,\n\t\toptions?: IMigrationOptions,\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: DynamoDbEntityStorageConnector<U>,\n\t\tdestConnector: DynamoDbEntityStorageConnector<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\tconst dbConnection = sourceConnector.createConnection();\n\t\tconst chunkSize = 25;\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) ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE;\n\n\t\t\tlet exclusiveStartKey: { [key: string]: AttributeValue } | undefined;\n\t\t\tdo {\n\t\t\t\tconst { Items: items, LastEvaluatedKey: lastKey } = await dbConnection.send(\n\t\t\t\t\tnew QueryCommand({\n\t\t\t\t\t\tTableName: sourceConnector._config.tableName,\n\t\t\t\t\t\tKeyConditionExpression: `#${DynamoDbEntityStorageConnector._PARTITION_KEY} = :${DynamoDbEntityStorageConnector._PARTITION_KEY}`,\n\t\t\t\t\t\tExpressionAttributeNames: {\n\t\t\t\t\t\t\t[`#${DynamoDbEntityStorageConnector._PARTITION_KEY}`]:\n\t\t\t\t\t\t\t\tDynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t\t},\n\t\t\t\t\t\tExpressionAttributeValues: {\n\t\t\t\t\t\t\t[`:${DynamoDbEntityStorageConnector._PARTITION_KEY}`]: { S: partitionKey }\n\t\t\t\t\t\t},\n\t\t\t\t\t\tLimit: batchSize,\n\t\t\t\t\t\tExclusiveStartKey: exclusiveStartKey\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\t\texclusiveStartKey = lastKey;\n\n\t\t\t\tif (Is.arrayValue(items)) {\n\t\t\t\t\tfor (let j = 0; j < items.length; j += chunkSize) {\n\t\t\t\t\t\tconst chunk = items.slice(j, j + chunkSize) as { [key: string]: AttributeValue }[];\n\t\t\t\t\t\tawait dbConnection.send(\n\t\t\t\t\t\t\tnew BatchWriteItemCommand({\n\t\t\t\t\t\t\t\tRequestItems: {\n\t\t\t\t\t\t\t\t\t[destConnector._config.tableName]: chunk.map(item => ({\n\t\t\t\t\t\t\t\t\t\tPutRequest: { Item: item }\n\t\t\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} while (exclusiveStartKey);\n\t\t}\n\t}\n\n\t/**\n\t * Create the parameters for a query.\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 * @param secondaryIndex The optional secondary index to use for 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]: AttributeValue },\n\t\tsecondaryIndex?: string\n\t): {\n\t\tkeyCondition: string;\n\t\tfilterCondition: string;\n\t\trequiresScan: boolean;\n\t\tnoResults?: boolean;\n\t} {\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\t\tkeyCondition: \"\",\n\t\t\t\tfilterCondition: \"\",\n\t\t\t\trequiresScan: false\n\t\t\t};\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\t\tkeyCondition: \"\",\n\t\t\t\t\tfilterCondition: \"\",\n\t\t\t\t\trequiresScan: false\n\t\t\t\t};\n\t\t\t}\n\t\t\t// Snapshot before the entire group. Used by the AND path to undo\n\t\t\t// surviving siblings' attribute registrations when the AND is dead (#141).\n\t\t\tconst preGroupNames = new Set(Object.keys(attributeNames));\n\t\t\tconst preGroupValues = new Set(Object.keys(attributeValues));\n\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: {\n\t\t\t\tkeyCondition: string;\n\t\t\t\tfilterCondition: string;\n\t\t\t\trequiresScan: boolean;\n\t\t\t\tnoResults?: boolean;\n\t\t\t}[] = condition.conditions.map(c => {\n\t\t\t\t// Snapshot before each branch. When a branch is dead (noResults),\n\t\t\t\t// undo its attribute registrations so the final expressions stay\n\t\t\t\t// consistent — DynamoDB rejects unused ExpressionAttributeNames (#141).\n\t\t\t\tconst preBranchNames = new Set(Object.keys(attributeNames));\n\t\t\t\tconst preBranchValues = new Set(Object.keys(attributeValues));\n\t\t\t\tconst result = this.buildQueryParameters(\n\t\t\t\t\tobjectPath,\n\t\t\t\t\tc,\n\t\t\t\t\tattributeNames,\n\t\t\t\t\tattributeValues,\n\t\t\t\t\tsecondaryIndex\n\t\t\t\t);\n\t\t\t\tif (result.noResults) {\n\t\t\t\t\tfor (const key of Object.keys(attributeNames)) {\n\t\t\t\t\t\tif (!preBranchNames.has(key)) {\n\t\t\t\t\t\t\tdelete attributeNames[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tfor (const key of Object.keys(attributeValues)) {\n\t\t\t\t\t\tif (!preBranchValues.has(key)) {\n\t\t\t\t\t\t\tdelete attributeValues[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t});\n\n\t\t\tconst logicalOperator = this.mapConditionalOperator(condition.logicalOperator);\n\n\t\t\t// DynamoDB does not support OR in KeyConditionExpression, so when the operator\n\t\t\t// is OR we must move all conditions (including key conditions) into FilterExpression.\n\t\t\tif (condition.logicalOperator === LogicalOperator.Or) {\n\t\t\t\t// OR: only empty if ALL branches are guaranteed empty (e.g. all empty IN lists).\n\t\t\t\t// If only some are empty they are naturally filtered out of `parts` below,\n\t\t\t\t// which is correct — false OR x = x (#141).\n\t\t\t\tif (joinConditions.every(j => j.noResults)) {\n\t\t\t\t\treturn { keyCondition: \"\", filterCondition: \"\", requiresScan: false, noResults: true };\n\t\t\t\t}\n\n\t\t\t\tconst parts = joinConditions\n\t\t\t\t\t.map(j => {\n\t\t\t\t\t\t// A branch marked noResults (e.g. a dead AND group containing In [])\n\t\t\t\t\t\t// must contribute nothing to the OR — false OR x = x (#141).\n\t\t\t\t\t\tif (j.noResults) {\n\t\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst subParts = [j.keyCondition.trim(), j.filterCondition.trim()].filter(\n\t\t\t\t\t\t\ts => s.length > 0\n\t\t\t\t\t\t);\n\t\t\t\t\t\tif (subParts.length === 0) {\n\t\t\t\t\t\t\treturn \"\";\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn subParts.length === 1 ? ` ${subParts[0]} ` : ` (${subParts.join(\" AND \")}) `;\n\t\t\t\t\t})\n\t\t\t\t\t.filter(s => s.length > 0);\n\t\t\t\tconst hasKeyConditions = joinConditions.some(j => j.keyCondition.length > 0);\n\t\t\t\tconst filterCondition = parts.join(\" OR \");\n\t\t\t\treturn {\n\t\t\t\t\tkeyCondition: \"\",\n\t\t\t\t\tfilterCondition: this.wrapConditionExpression(filterCondition, parts.length),\n\t\t\t\t\trequiresScan: hasKeyConditions\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst keyParts = joinConditions.filter(j => j.keyCondition.length > 0);\n\t\t\tconst filterParts = joinConditions.filter(j => j.filterCondition.length > 0);\n\t\t\tconst keyCondition = keyParts.map(j => j.keyCondition.trim()).join(` ${logicalOperator} `);\n\t\t\tconst filterCondition = filterParts\n\t\t\t\t.map(j => j.filterCondition.trim())\n\t\t\t\t.join(` ${logicalOperator} `);\n\n\t\t\t// AND: if any sub-condition is a guaranteed empty result (e.g. empty IN list),\n\t\t\t// the whole AND group is also empty (#141). Restore the attribute maps to the\n\t\t\t// pre-group snapshot so surviving siblings' registrations are also undone —\n\t\t\t// per-branch cleanup above only undoes dead branches, not live ones whose AND\n\t\t\t// partner was dead.\n\t\t\tconst noResults = joinConditions.some(j => j.noResults);\n\t\t\tif (noResults) {\n\t\t\t\tfor (const key of Object.keys(attributeNames)) {\n\t\t\t\t\tif (!preGroupNames.has(key)) {\n\t\t\t\t\t\tdelete attributeNames[key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (const key of Object.keys(attributeValues)) {\n\t\t\t\t\tif (!preGroupValues.has(key)) {\n\t\t\t\t\t\tdelete attributeValues[key];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn { keyCondition: \"\", filterCondition: \"\", requiresScan: false, noResults: true };\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tkeyCondition: this.wrapConditionExpression(keyCondition, keyParts.length),\n\t\t\t\tfilterCondition: this.wrapConditionExpression(filterCondition, filterParts.length),\n\t\t\t\trequiresScan: joinConditions.some(j => j.requiresScan)\n\t\t\t};\n\t\t}\n\n\t\tconst schemaProp = this._entitySchema.properties?.find(p => p.property === condition.property);\n\n\t\t// Empty IN list: DynamoDB has no `IN ()` syntax — short-circuit to empty result (#141).\n\t\tif (\n\t\t\t\"comparison\" in condition &&\n\t\t\tcondition.comparison === ComparisonOperator.In &&\n\t\t\tIs.array(condition.value) &&\n\t\t\tcondition.value.length === 0\n\t\t) {\n\t\t\treturn { keyCondition: \"\", filterCondition: \"\", requiresScan: false, noResults: true };\n\t\t}\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\tconst isKey =\n\t\t\tschemaProp?.isPrimary ?? (schemaProp?.isSecondary && schemaProp?.property === secondaryIndex);\n\t\treturn {\n\t\t\tkeyCondition: isKey ? comparison : \"\",\n\t\t\tfilterCondition: !isKey ? comparison : \"\",\n\t\t\trequiresScan: false\n\t\t};\n\t}\n\n\t/**\n\t * Map the framework comparison operators to those in DynamoDB.\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 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 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]: AttributeValue }\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\n\t\tif (Is.empty(comparator.value)) {\n\t\t\t// With \"omit\" storage, optional null/undefined fields are absent from the item entirely.\n\t\t\t// attribute_not_exists matches absent attributes; attribute_exists matches present ones.\n\t\t\tif (comparator.comparison === ComparisonOperator.Equals) {\n\t\t\t\treturn `attribute_not_exists(${attributeName})`;\n\t\t\t} else if (comparator.comparison === ComparisonOperator.NotEquals) {\n\t\t\t\treturn `attribute_exists(${attributeName})`;\n\t\t\t}\n\t\t}\n\n\t\tconst basePropName = `:${attributeName.replace(/\\./g, \"\").replace(/#/g, \"\")}`;\n\t\tlet propName = basePropName;\n\t\tlet propSuffix = 0;\n\t\twhile (!Is.undefined(attributeValues[propName])) {\n\t\t\tpropSuffix++;\n\t\t\tpropName = `${basePropName}${propSuffix}`;\n\t\t}\n\n\t\tif (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.join(\", \")})`;\n\t\t} else {\n\t\t\tattributeValues[propName] = this.propertyToDbValue(comparator.value, type);\n\t\t}\n\n\t\tif (comparator.comparison === ComparisonOperator.Equals) {\n\t\t\treturn `${attributeName} = ${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.NotEquals) {\n\t\t\treturn `${attributeName} <> ${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.GreaterThan) {\n\t\t\treturn `${attributeName} > ${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.LessThan) {\n\t\t\treturn `${attributeName} < ${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.GreaterThanOrEqual) {\n\t\t\treturn `${attributeName} >= ${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.LessThanOrEqual) {\n\t\t\treturn `${attributeName} <= ${propName}`;\n\t\t} else if (comparator.comparison === ComparisonOperator.Includes) {\n\t\t\treturn `contains(${attributeName}, ${propName})`;\n\t\t} else if (comparator.comparison === ComparisonOperator.NotIncludes) {\n\t\t\treturn `NOT contains(${attributeName}, ${propName})`;\n\t\t} else if (comparator.comparison === ComparisonOperator.In) {\n\t\t\treturn `${propName} IN ${attributeName}`;\n\t\t}\n\n\t\tthrow new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, \"comparisonNotSupported\", {\n\t\t\tcomparison: comparator.comparison\n\t\t});\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 DynamoDB.\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(DynamoDbEntityStorageConnector.CLASS_NAME, \"conditionalNotSupported\", {\n\t\t\toperator\n\t\t});\n\t}\n\n\t/**\n\t * Wrap a condition expression in parentheses only when multiple parts were joined.\n\t * A single already-parenthesised child must not be double-wrapped.\n\t * @param expr The joined condition expression.\n\t * @param partCount The number of parts that were joined to produce expr.\n\t * @returns The expression with surrounding spaces, wrapped only when partCount is greater than one.\n\t * @internal\n\t */\n\tprivate wrapConditionExpression(expr: string, partCount: number): string {\n\t\tif (!Is.stringValue(expr)) {\n\t\t\treturn \"\";\n\t\t}\n\t\treturn partCount > 1 ? ` (${expr}) ` : ` ${expr} `;\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): AttributeValue {\n\t\tif (Is.object(value)) {\n\t\t\tconst map: { [id: string]: AttributeValue } = {};\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 {\n\t\t\t\tM: map\n\t\t\t};\n\t\t}\n\n\t\tif (type === \"integer\" || type === \"number\") {\n\t\t\treturn { N: Coerce.string(value) ?? \"\" };\n\t\t} else if (type === \"boolean\") {\n\t\t\treturn { BOOL: Coerce.boolean(value) ?? false };\n\t\t}\n\n\t\tif (Is.boolean(value)) {\n\t\t\treturn { BOOL: value };\n\t\t} else if (Is.number(value)) {\n\t\t\treturn { N: value.toString() };\n\t\t}\n\n\t\treturn { S: Coerce.string(value) ?? \"\" };\n\t}\n\n\t/**\n\t * Create a doc client connection.\n\t * @returns The dynamo db document client.\n\t * @internal\n\t */\n\tprivate createDocClient(): DynamoDBDocumentClient {\n\t\treturn DynamoDBDocumentClient.from(\n\t\t\tnew DynamoDB({\n\t\t\t\tapiVersion: \"2012-10-08\",\n\t\t\t\t...this.createConnectionConfig()\n\t\t\t}),\n\t\t\t{\n\t\t\t\tmarshallOptions: {\n\t\t\t\t\tremoveUndefinedValues: true\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\t/**\n\t * Create a new DB connection.\n\t * @returns The Dynamo DB connection.\n\t * @internal\n\t */\n\tprivate createConnection(): DynamoDB {\n\t\treturn new DynamoDB(this.createConnectionConfig());\n\t}\n\n\t/**\n\t * Create a new DB connection configuration.\n\t * @returns The Dynamo DB connection configuration.\n\t * @internal\n\t */\n\tprivate createConnectionConfig(): DynamoDBClientConfig {\n\t\tconst requestHandler = Is.number(this._config.connectionTimeoutMs)\n\t\t\t? { requestTimeout: this._config.connectionTimeoutMs }\n\t\t\t: undefined;\n\n\t\tif (\n\t\t\tIs.stringValue(this._config.secretAccessKey) &&\n\t\t\tIs.stringValue(this._config.accessKeyId) &&\n\t\t\tthis._config.authMode === \"credentials\"\n\t\t) {\n\t\t\treturn {\n\t\t\t\tcredentials: {\n\t\t\t\t\taccessKeyId: this._config.accessKeyId,\n\t\t\t\t\tsecretAccessKey: this._config.secretAccessKey\n\t\t\t\t},\n\t\t\t\tendpoint: this._config.endpoint,\n\t\t\t\tregion: this._config.region,\n\t\t\t\trequestHandler,\n\t\t\t\tmaxAttempts: this._config.maxAttempts\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tendpoint: this._config.endpoint,\n\t\t\tregion: this._config.region,\n\t\t\trequestHandler,\n\t\t\tmaxAttempts: this._config.maxAttempts\n\t\t};\n\t}\n\n\t/**\n\t * Check if the table exists.\n\t * @param tableName The table to check.\n\t * @returns True if the table exists.\n\t * @internal\n\t */\n\tprivate async tableExists(tableName: string): Promise<boolean> {\n\t\ttry {\n\t\t\tconst dbConnection = this.createConnection();\n\n\t\t\tconst result = await dbConnection.describeTable({ TableName: tableName });\n\n\t\t\t// A table in DELETING state should not be treated as existing\n\t\t\treturn result.Table?.TableStatus !== \"DELETING\";\n\t\t} catch {\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 * @param secondaryIndex The secondary index to use for the query.\n\t * @param partitionKey The partition key to use for the query.\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 * @internal\n\t */\n\tprivate async internalQuery(\n\t\tconditions?: EntityCondition<T>,\n\t\tsortProperties?: {\n\t\t\tproperty: keyof T;\n\t\t\tsortDirection: SortDirection;\n\t\t}[],\n\t\tproperties?: (keyof T)[],\n\t\tcursor?: string,\n\t\tlimit?: number,\n\t\tsecondaryIndex?: string,\n\t\tpartitionKey?: string\n\t): Promise<{\n\t\tentities: Partial<T>[];\n\t\tcursor?: string;\n\t}> {\n\t\ttry {\n\t\t\tconst returnSize = limit ?? DynamoDbEntityStorageConnector._DEFAULT_LIMIT;\n\t\t\tconst indexConfig = this.resolveQueryIndexConfig(sortProperties, secondaryIndex);\n\t\t\tconst { attributeNames, attributeValues } = this.buildQueryAttributeMaps(partitionKey);\n\t\t\tconst safeCursor = this.sanitizeCursorForPartition(cursor, attributeValues);\n\n\t\t\tconst expressions = this.buildQueryParameters(\n\t\t\t\t\"\",\n\t\t\t\tconditions,\n\t\t\t\tattributeNames,\n\t\t\t\tattributeValues,\n\t\t\t\tindexConfig.gsiAttribute\n\t\t\t);\n\n\t\t\tif (expressions.noResults) {\n\t\t\t\treturn { entities: [], cursor: undefined };\n\t\t\t}\n\n\t\t\tif (expressions.requiresScan) {\n\t\t\t\tconst scanResult = await this.executeScanFallback(\n\t\t\t\t\texpressions.filterCondition,\n\t\t\t\t\tproperties,\n\t\t\t\t\tattributeNames,\n\t\t\t\t\tattributeValues,\n\t\t\t\t\tsafeCursor,\n\t\t\t\t\treturnSize\n\t\t\t\t);\n\n\t\t\t\treturn {\n\t\t\t\t\tentities: this.mapRawItemsToEntities(scanResult.rawItems),\n\t\t\t\t\tcursor: scanResult.cursor\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst keyExpression = this.buildKeyExpression(expressions.keyCondition);\n\t\t\tconst queryProjection = this.buildProjectionExpression(properties, attributeNames);\n\n\t\t\tconst queryResult = Is.stringValue(expressions.filterCondition)\n\t\t\t\t? await this.executeFilteredQuery(\n\t\t\t\t\t\tkeyExpression,\n\t\t\t\t\t\texpressions.filterCondition,\n\t\t\t\t\t\tattributeNames,\n\t\t\t\t\t\tattributeValues,\n\t\t\t\t\t\tqueryProjection,\n\t\t\t\t\t\tindexConfig.indexName,\n\t\t\t\t\t\tindexConfig.scanAscending,\n\t\t\t\t\t\tsafeCursor,\n\t\t\t\t\t\treturnSize\n\t\t\t\t\t)\n\t\t\t\t: await this.executeUnfilteredQuery(\n\t\t\t\t\t\tkeyExpression,\n\t\t\t\t\t\tattributeNames,\n\t\t\t\t\t\tattributeValues,\n\t\t\t\t\t\tqueryProjection,\n\t\t\t\t\t\tindexConfig.indexName,\n\t\t\t\t\t\tindexConfig.scanAscending,\n\t\t\t\t\t\tsafeCursor,\n\t\t\t\t\t\treturnSize\n\t\t\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tentities: this.mapRawItemsToEntities(queryResult.rawItems),\n\t\t\t\tcursor: queryResult.cursor\n\t\t\t};\n\t\t} catch (err) {\n\t\t\tif (BaseError.isErrorCode(err, \"ResourceNotFoundException\")) {\n\t\t\t\tthrow new GeneralError(\n\t\t\t\t\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\t\"tableDoesNotExist\",\n\t\t\t\t\t{\n\t\t\t\t\t\ttableName: this._config.tableName\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\tDynamoDbEntityStorageConnector.CLASS_NAME,\n\t\t\t\t\"queryFailed\",\n\t\t\t\tundefined,\n\t\t\t\terr\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Resolve index configuration from sort options and optional explicit secondary index.\n\t * @param sortProperties The optional sort order.\n\t * @param secondaryIndex The optional explicit secondary index.\n\t * @returns The resolved index name, GSI attribute and sort direction.\n\t * @throws GeneralError if more than one sort property is specified.\n\t * @internal\n\t */\n\tprivate resolveQueryIndexConfig(\n\t\tsortProperties?: {\n\t\t\tproperty: keyof T;\n\t\t\tsortDirection: SortDirection;\n\t\t}[],\n\t\tsecondaryIndex?: string\n\t): {\n\t\tindexName?: string;\n\t\tgsiAttribute?: string;\n\t\tscanAscending: boolean;\n\t} {\n\t\tlet indexName: string | undefined = Is.stringValue(secondaryIndex)\n\t\t\t? `${secondaryIndex}Index`\n\t\t\t: undefined;\n\t\tlet gsiAttribute: string | undefined = secondaryIndex;\n\t\tlet scanAscending = true;\n\n\t\tif (Is.arrayValue(sortProperties)) {\n\t\t\tif (sortProperties.length > 1) {\n\t\t\t\tthrow new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, \"sortSingle\");\n\t\t\t}\n\n\t\t\tfor (const sortProperty of sortProperties) {\n\t\t\t\tconst propertySchema = this._entitySchema.properties?.find(\n\t\t\t\t\te => e.property === sortProperty.property\n\t\t\t\t);\n\t\t\t\tif (propertySchema?.isPrimary) {\n\t\t\t\t\tindexName = undefined;\n\t\t\t\t\tgsiAttribute = undefined;\n\t\t\t\t} else {\n\t\t\t\t\tindexName = `${sortProperty.property as string}Index`;\n\t\t\t\t\tgsiAttribute = sortProperty.property as string;\n\t\t\t\t}\n\t\t\t\tscanAscending = sortProperty.sortDirection === SortDirection.Ascending;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tindexName,\n\t\t\tgsiAttribute,\n\t\t\tscanAscending\n\t\t};\n\t}\n\n\t/**\n\t * Build the base attribute maps used for query/scan operations.\n\t * @param partitionKey The optional partition key.\n\t * @returns The query attribute maps.\n\t * @internal\n\t */\n\tprivate buildQueryAttributeMaps(partitionKey?: string): {\n\t\tattributeNames: { [id: string]: string };\n\t\tattributeValues: { [id: string]: AttributeValue };\n\t} {\n\t\treturn {\n\t\t\tattributeNames: { \"#partitionId\": \"partitionId\" },\n\t\t\tattributeValues: {\n\t\t\t\t[`:${DynamoDbEntityStorageConnector._PARTITION_KEY}`]: {\n\t\t\t\t\tS: partitionKey ?? DynamoDbEntityStorageConnector._PARTITION_KEY_VALUE\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t/**\n\t * Build the key condition expression with the mandatory partition predicate.\n\t * @param keyCondition The optional extra key condition segment.\n\t * @returns The full key condition expression.\n\t * @internal\n\t */\n\tprivate buildKeyExpression(keyCondition: string): string {\n\t\tlet keyExpression = \"#partitionId = :partitionId\";\n\t\tif (keyCondition.length > 0) {\n\t\t\tkeyExpression += ` AND ${keyCondition}`;\n\t\t}\n\t\treturn keyExpression;\n\t}\n\n\t/**\n\t * Decode a paginated cursor into a DynamoDB ExclusiveStartKey.\n\t * @param cursor The encoded cursor.\n\t * @returns The decoded exclusive start key.\n\t * @internal\n\t */\n\tprivate decodeCursor(cursor?: string): { [id: string]: AttributeValue } | undefined {\n\t\treturn Is.empty(cursor) ? undefined : ObjectHelper.fromBytes(Converter.base64ToBytes(cursor));\n\t}\n\n\t/**\n\t * Encode a DynamoDB key to a cursor string.\n\t * @param key The key to encode.\n\t * @returns The encoded cursor.\n\t * @internal\n\t */\n\tprivate encodeCursor(key?: { [id: string]: AttributeValue }): string | undefined {\n\t\treturn Is.empty(key) ? undefined : Converter.bytesToBase64(ObjectHelper.toBytes(key));\n\t}\n\n\t/**\n\t * Return undefined if the cursor belongs to a different partition, preventing cross-partition leakage.\n\t * @param cursor The encoded cursor.\n\t * @param attributeValues The current query attribute values containing the expected partition key.\n\t * @returns The cursor if it matches the current partition, otherwise undefined.\n\t * @internal\n\t */\n\tprivate sanitizeCursorForPartition(\n\t\tcursor: string | undefined,\n\t\tattributeValues: { [id: string]: AttributeValue }\n\t): string | undefined {\n\t\tif (Is.empty(cursor)) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst decoded = this.decodeCursor(cursor);\n\t\tif (Is.empty(decoded)) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst expectedPartition =\n\t\t\tattributeValues[`:${DynamoDbEntityStorageConnector._PARTITION_KEY}`]?.S;\n\t\tconst cursorPartition = decoded[DynamoDbEntityStorageConnector._PARTITION_KEY]?.S;\n\t\treturn cursorPartition === expectedPartition ? cursor : undefined;\n\t}\n\n\t/**\n\t * Execute a scan fallback path for unsupported key-condition shapes.\n\t * @param filterCondition The optional filter expression part.\n\t * @param properties The projection properties.\n\t * @param attributeNames The expression attribute names.\n\t * @param attributeValues The expression attribute values.\n\t * @param cursor The optional cursor.\n\t * @param returnSize The requested page size.\n\t * @returns Raw items and an optional cursor.\n\t * @internal\n\t */\n\tprivate async executeScanFallback(\n\t\tfilterCondition: string,\n\t\tproperties: (keyof T)[] | undefined,\n\t\tattributeNames: { [id: string]: string },\n\t\tattributeValues: { [id: string]: AttributeValue },\n\t\tcursor: string | undefined,\n\t\treturnSize: number\n\t): Promise<{\n\t\trawItems: { [id: string]: AttributeValue }[];\n\t\tcursor?: string;\n\t}> {\n\t\tlet scanFilter = \"#partitionId = :partitionId\";\n\t\tif (Is.stringValue(filterCondition)) {\n\t\t\tscanFilter += ` AND ${filterCondition.trim()}`;\n\t\t}\n\n\t\tconst dbConnection = this.createConnection();\n\t\tconst matchingItems: { [id: string]: AttributeValue }[] = [];\n\t\tlet scanStartKey = this.decodeCursor(cursor);\n\t\tlet lastEvaluatedKey: { [id: string]: AttributeValue } | undefined;\n\n\t\t// Scan in batches with a heuristic limit to avoid scanning excessive unmatched rows.\n\t\t// Use at least 2x returnSize per batch to balance accuracy and efficiency.\n\t\tconst batchScanLimit = Math.max(returnSize * 2, 100);\n\n\t\tdo {\n\t\t\tconst scanResult = await dbConnection.send(\n\t\t\t\tnew RawScanCommand({\n\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\tFilterExpression: scanFilter,\n\t\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\t\tExclusiveStartKey: scanStartKey,\n\t\t\t\t\tLimit: batchScanLimit\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tmatchingItems.push(...(scanResult.Items ?? []));\n\t\t\tlastEvaluatedKey = scanResult.LastEvaluatedKey;\n\t\t\tscanStartKey = lastEvaluatedKey;\n\n\t\t\t// Early exit: stop scanning once we have enough filtered results to fill the page.\n\t\t\tif (matchingItems.length >= returnSize) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t} while (!Is.empty(lastEvaluatedKey));\n\n\t\tconst hasMore = matchingItems.length > returnSize;\n\t\tconst returnedRawItems = hasMore ? matchingItems.slice(0, returnSize) : matchingItems;\n\n\t\tlet resultCursor: string | undefined;\n\t\tif (hasMore) {\n\t\t\tconst lastRawItem = returnedRawItems[returnedRawItems.length - 1];\n\t\t\tconst syntheticKey: { [id: string]: AttributeValue } = {\n\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\tlastRawItem[DynamoDbEntityStorageConnector._PARTITION_KEY],\n\t\t\t\t[this._primaryKey.property as string]: lastRawItem[this._primaryKey.property as string]\n\t\t\t};\n\t\t\tresultCursor = this.encodeCursor(syntheticKey);\n\t\t}\n\n\t\tconst projectedRawItems = Is.arrayValue(properties)\n\t\t\t? returnedRawItems.map(item => {\n\t\t\t\t\tconst projected: { [id: string]: AttributeValue } = {};\n\t\t\t\t\tfor (const prop of properties) {\n\t\t\t\t\t\tconst key = prop as string;\n\t\t\t\t\t\tif (!Is.undefined(item[key])) {\n\t\t\t\t\t\t\tprojected[key] = item[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!Is.undefined(item[DynamoDbEntityStorageConnector._PARTITION_KEY])) {\n\t\t\t\t\t\tprojected[DynamoDbEntityStorageConnector._PARTITION_KEY] =\n\t\t\t\t\t\t\titem[DynamoDbEntityStorageConnector._PARTITION_KEY];\n\t\t\t\t\t}\n\t\t\t\t\treturn projected;\n\t\t\t\t})\n\t\t\t: returnedRawItems;\n\n\t\treturn {\n\t\t\trawItems: projectedRawItems,\n\t\t\tcursor: resultCursor\n\t\t};\n\t}\n\n\t/**\n\t * Execute a query path without filter expression.\n\t * @param keyExpression The key condition expression.\n\t * @param attributeNames The expression attribute names.\n\t * @param attributeValues The expression attribute values.\n\t * @param projectionExpression The projection expression.\n\t * @param indexName The optional index name.\n\t * @param scanAscending The scan direction.\n\t * @param cursor The optional cursor.\n\t * @param returnSize The requested page size.\n\t * @returns Raw items and an optional cursor.\n\t * @internal\n\t */\n\tprivate async executeUnfilteredQuery(\n\t\tkeyExpression: string,\n\t\tattributeNames: { [id: string]: string },\n\t\tattributeValues: { [id: string]: AttributeValue },\n\t\tprojectionExpression: string | undefined,\n\t\tindexName: string | undefined,\n\t\tscanAscending: boolean,\n\t\tcursor: string | undefined,\n\t\treturnSize: number\n\t): Promise<{\n\t\trawItems: { [id: string]: AttributeValue }[];\n\t\tcursor?: string;\n\t}> {\n\t\tconst connection = this.createDocClient();\n\t\tconst results = await connection.send(\n\t\t\tnew QueryCommand({\n\t\t\t\tTableName: this._config.tableName,\n\t\t\t\tIndexName: indexName,\n\t\t\t\tKeyConditionExpression: keyExpression,\n\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\tProjectionExpression: projectionExpression,\n\t\t\t\tLimit: returnSize,\n\t\t\t\tScanIndexForward: scanAscending,\n\t\t\t\tExclusiveStartKey: this.decodeCursor(cursor)\n\t\t\t})\n\t\t);\n\n\t\tconst rawItems = (results.Items ?? []) as { [id: string]: AttributeValue }[];\n\t\tlet hasMore = false;\n\n\t\tif (rawItems.length === returnSize && !Is.empty(results.LastEvaluatedKey)) {\n\t\t\tconst probe = await connection.send(\n\t\t\t\tnew QueryCommand({\n\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\tIndexName: indexName,\n\t\t\t\t\tKeyConditionExpression: keyExpression,\n\t\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\t\tProjectionExpression: projectionExpression,\n\t\t\t\t\tLimit: 1,\n\t\t\t\t\tScanIndexForward: scanAscending,\n\t\t\t\t\tExclusiveStartKey: results.LastEvaluatedKey\n\t\t\t\t})\n\t\t\t);\n\t\t\thasMore = (probe.Items?.length ?? 0) > 0;\n\t\t}\n\n\t\treturn {\n\t\t\trawItems,\n\t\t\tcursor: hasMore ? this.encodeCursor(results.LastEvaluatedKey) : undefined\n\t\t};\n\t}\n\n\t/**\n\t * Execute a query path with filter expression, continuing until page is full or exhausted.\n\t * @param keyExpression The key condition expression.\n\t * @param filterExpression The filter expression.\n\t * @param attributeNames The expression attribute names.\n\t * @param attributeValues The expression attribute values.\n\t * @param projectionExpression The projection expression.\n\t * @param indexName The optional index name.\n\t * @param scanAscending The scan direction.\n\t * @param cursor The optional cursor.\n\t * @param returnSize The requested page size.\n\t * @returns Raw items and an optional cursor.\n\t * @internal\n\t */\n\tprivate async executeFilteredQuery(\n\t\tkeyExpression: string,\n\t\tfilterExpression: string,\n\t\tattributeNames: { [id: string]: string },\n\t\tattributeValues: { [id: string]: AttributeValue },\n\t\tprojectionExpression: string | undefined,\n\t\tindexName: string | undefined,\n\t\tscanAscending: boolean,\n\t\tcursor: string | undefined,\n\t\treturnSize: number\n\t): Promise<{\n\t\trawItems: { [id: string]: AttributeValue }[];\n\t\tcursor?: string;\n\t}> {\n\t\tconst connection = this.createDocClient();\n\t\tconst returnedRawItems: { [id: string]: AttributeValue }[] = [];\n\t\tlet lastEvaluatedKey: { [id: string]: AttributeValue } | undefined = this.decodeCursor(cursor);\n\n\t\tdo {\n\t\t\tconst results = await connection.send(\n\t\t\t\tnew QueryCommand({\n\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\tIndexName: indexName,\n\t\t\t\t\tKeyConditionExpression: keyExpression,\n\t\t\t\t\tFilterExpression: filterExpression,\n\t\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\t\tProjectionExpression: projectionExpression,\n\t\t\t\t\tLimit: returnSize - returnedRawItems.length,\n\t\t\t\t\tScanIndexForward: scanAscending,\n\t\t\t\t\tExclusiveStartKey: lastEvaluatedKey\n\t\t\t\t})\n\t\t\t);\n\n\t\t\treturnedRawItems.push(...((results.Items ?? []) as { [id: string]: AttributeValue }[]));\n\t\t\tlastEvaluatedKey = results.LastEvaluatedKey;\n\t\t} while (returnedRawItems.length < returnSize && !Is.empty(lastEvaluatedKey));\n\n\t\treturn {\n\t\t\trawItems: returnedRawItems,\n\t\t\tcursor: this.encodeCursor(lastEvaluatedKey)\n\t\t};\n\t}\n\n\t/**\n\t * Convert raw DynamoDB items into connector entities.\n\t * @param rawItems Raw DynamoDB items.\n\t * @returns The mapped entities.\n\t * @internal\n\t */\n\tprivate mapRawItemsToEntities(rawItems: { [id: string]: AttributeValue }[]): T[] {\n\t\treturn rawItems.map(item => {\n\t\t\tconst unmarshalled = unmarshall(item);\n\t\t\treturn EntityStorageHelper.unPrepareEntity(unmarshalled as T, [\n\t\t\t\tDynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t]);\n\t\t});\n\t}\n\n\t/**\n\t * Build the condition expression for the query.\n\t * @param conditions The conditions to build the expression from.\n\t * @returns The condition expression.\n\t * @throws GeneralError if the property is not found in the schema.\n\t * @internal\n\t */\n\tprivate buildConditionExpression(conditions?: { property: keyof T; value: unknown }[]): {\n\t\tconditionExpression: string | undefined;\n\t\tattributeNames: { [id: string]: string } | undefined;\n\t\tattributeValues: { [key: string]: NativeAttributeValue } | undefined;\n\t} {\n\t\tlet conditionExpression: string | undefined;\n\t\tlet attributeNames: { [id: string]: string } | undefined;\n\t\tlet attributeValues: { [key: string]: NativeAttributeValue } | undefined;\n\n\t\tif (Is.arrayValue(conditions)) {\n\t\t\tconst expressions: string[] = [];\n\n\t\t\tfor (const c of conditions) {\n\t\t\t\tconst schemaProp = this._entitySchema.properties?.find(p => p.property === c.property);\n\n\t\t\t\tif (Is.undefined(schemaProp)) {\n\t\t\t\t\tthrow new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, \"propertyNotFound\", {\n\t\t\t\t\t\tproperty: c.property\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst attributeName = `#${c.property as string}`;\n\t\t\t\tconst attributeValueName = `:${c.property as string}`;\n\t\t\t\tattributeNames ??= {};\n\t\t\t\tattributeValues ??= {};\n\t\t\t\tattributeNames[attributeName] = c.property as string;\n\t\t\t\tattributeValues[attributeValueName] = c.value;\n\t\t\t\texpressions.push(`${attributeName} = ${attributeValueName}`);\n\t\t\t}\n\n\t\t\tconditionExpression = expressions.join(\" AND \");\n\t\t}\n\t\treturn { conditionExpression, attributeNames, attributeValues };\n\t}\n\n\t/**\n\t * Build a ProjectionExpression string and register a safe alias in attributeNames for every\n\t * projected property, preventing ValidationException when a property name is a DynamoDB\n\t * reserved word (e.g. \"role\", \"name\", \"status\").\n\t * @param properties The properties to project, or undefined to return all attributes.\n\t * @param attributeNames The expression attribute names map to mutate with the aliases.\n\t * @returns The ProjectionExpression string, or undefined when no projection is needed.\n\t * @internal\n\t */\n\tprivate buildProjectionExpression(\n\t\tproperties: (keyof T)[] | undefined,\n\t\tattributeNames: { [id: string]: string }\n\t): string | undefined {\n\t\tif (!Is.arrayValue(properties)) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn properties\n\t\t\t.map(p => {\n\t\t\t\tconst alias = `#p_${p as string}`;\n\t\t\t\tattributeNames[alias] = p as string;\n\t\t\t\treturn alias;\n\t\t\t})\n\t\t\t.join(\", \");\n\t}\n}\n"]}
package/docs/changelog.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.1-next.5](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-dynamodb-v0.9.1-next.4...entity-storage-connector-dynamodb-v0.9.1-next.5) (2026-06-30)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * handle empty conditions ([#159](https://github.com/iotaledger/twin-entity-storage/issues/159)) ([ae3319c](https://github.com/iotaledger/twin-entity-storage/commit/ae3319c3136bccc94244b2d79b3baef7a1b037d7))
9
+
10
+
11
+ ### Dependencies
12
+
13
+ * The following workspace dependencies were updated
14
+ * dependencies
15
+ * @twin.org/entity-storage-models bumped from 0.9.1-next.4 to 0.9.1-next.5
16
+ * devDependencies
17
+ * @twin.org/entity-storage-connector-memory bumped from 0.9.1-next.4 to 0.9.1-next.5
18
+
19
+ ## [0.9.1-next.4](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-dynamodb-v0.9.1-next.3...entity-storage-connector-dynamodb-v0.9.1-next.4) (2026-06-29)
20
+
21
+
22
+ ### Miscellaneous Chores
23
+
24
+ * **entity-storage-connector-dynamodb:** Synchronize repo versions
25
+
26
+
27
+ ### Dependencies
28
+
29
+ * The following workspace dependencies were updated
30
+ * dependencies
31
+ * @twin.org/entity-storage-models bumped from 0.9.1-next.3 to 0.9.1-next.4
32
+ * devDependencies
33
+ * @twin.org/entity-storage-connector-memory bumped from 0.9.1-next.3 to 0.9.1-next.4
34
+
3
35
  ## [0.9.1-next.3](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-dynamodb-v0.9.1-next.2...entity-storage-connector-dynamodb-v0.9.1-next.3) (2026-06-26)
4
36
 
5
37
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twin.org/entity-storage-connector-dynamodb",
3
- "version": "0.9.1-next.3",
3
+ "version": "0.9.1-next.5",
4
4
  "description": "Amazon DynamoDB connector for managed NoSQL persistence.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -20,7 +20,7 @@
20
20
  "@twin.org/context": "next",
21
21
  "@twin.org/core": "next",
22
22
  "@twin.org/entity": "next",
23
- "@twin.org/entity-storage-models": "0.9.1-next.3",
23
+ "@twin.org/entity-storage-models": "0.9.1-next.5",
24
24
  "@twin.org/logging-models": "next",
25
25
  "@twin.org/nameof": "next"
26
26
  },