@twin.org/entity-storage-connector-dynamodb 0.0.3-next.22 → 0.0.3-next.23
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.
|
@@ -4,7 +4,7 @@ import { BatchWriteItemCommand, DynamoDB, QueryCommand, ScanCommand as RawScanCo
|
|
|
4
4
|
import { BatchWriteCommand, DeleteCommand, DynamoDBDocumentClient, GetCommand, PutCommand, ScanCommand } from "@aws-sdk/lib-dynamodb";
|
|
5
5
|
import { unmarshall } from "@aws-sdk/util-dynamodb";
|
|
6
6
|
import { ContextIdHelper, ContextIdStore } from "@twin.org/context";
|
|
7
|
-
import { BaseError, Coerce, ComponentFactory, Converter, GeneralError, Guards, HealthStatus, Is, ObjectHelper } from "@twin.org/core";
|
|
7
|
+
import { BaseError, Coerce, ComponentFactory, Converter, GeneralError, Guards, HealthStatus, Is, ObjectHelper, Validation } from "@twin.org/core";
|
|
8
8
|
import { ComparisonOperator, EntitySchemaFactory, EntitySchemaHelper, LogicalOperator, SortDirection } from "@twin.org/entity";
|
|
9
9
|
import { EntityStorageHelper } from "@twin.org/entity-storage-models";
|
|
10
10
|
/**
|
|
@@ -585,6 +585,13 @@ export class DynamoDbEntityStorageConnector {
|
|
|
585
585
|
async query(conditions, sortProperties, properties, cursor, limit) {
|
|
586
586
|
const contextIds = await ContextIdStore.getContextIds();
|
|
587
587
|
const partitionKey = ContextIdHelper.combinedContextKey(contextIds, this._partitionContextIds);
|
|
588
|
+
if (!Is.empty(limit)) {
|
|
589
|
+
const validationFailures = [];
|
|
590
|
+
Validation.integer("limit", limit, validationFailures, undefined, { minValue: 1 });
|
|
591
|
+
Validation.asValidationError(DynamoDbEntityStorageConnector.CLASS_NAME, "query", validationFailures);
|
|
592
|
+
}
|
|
593
|
+
EntityStorageHelper.validateSortProperties(this._entitySchema, sortProperties);
|
|
594
|
+
EntityStorageHelper.validateProperties(this._entitySchema, properties);
|
|
588
595
|
return this.internalQuery(conditions, sortProperties, properties, cursor, limit, undefined, partitionKey);
|
|
589
596
|
}
|
|
590
597
|
/**
|
|
@@ -1055,6 +1062,12 @@ export class DynamoDbEntityStorageConnector {
|
|
|
1055
1062
|
else if (type === "boolean") {
|
|
1056
1063
|
return { BOOL: Coerce.boolean(value) ?? false };
|
|
1057
1064
|
}
|
|
1065
|
+
if (Is.boolean(value)) {
|
|
1066
|
+
return { BOOL: value };
|
|
1067
|
+
}
|
|
1068
|
+
else if (Is.number(value)) {
|
|
1069
|
+
return { N: value.toString() };
|
|
1070
|
+
}
|
|
1058
1071
|
return { S: Coerce.string(value) ?? "" };
|
|
1059
1072
|
}
|
|
1060
1073
|
/**
|
|
@@ -1146,6 +1159,8 @@ export class DynamoDbEntityStorageConnector {
|
|
|
1146
1159
|
let indexName = Is.stringValue(secondaryIndex)
|
|
1147
1160
|
? `${secondaryIndex}Index`
|
|
1148
1161
|
: undefined;
|
|
1162
|
+
// The attribute whose value must appear in ExclusiveStartKey when querying a GSI
|
|
1163
|
+
let gsiAttribute = secondaryIndex;
|
|
1149
1164
|
// If we have a sortable property defined in the descriptor then we must use
|
|
1150
1165
|
// the secondary index for the query
|
|
1151
1166
|
let scanAscending = true;
|
|
@@ -1155,17 +1170,14 @@ export class DynamoDbEntityStorageConnector {
|
|
|
1155
1170
|
}
|
|
1156
1171
|
for (const sortProperty of sortProperties) {
|
|
1157
1172
|
const propertySchema = this._entitySchema.properties?.find(e => e.property === sortProperty.property);
|
|
1158
|
-
if (
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1173
|
+
if (propertySchema?.isPrimary) {
|
|
1174
|
+
indexName = undefined;
|
|
1175
|
+
gsiAttribute = undefined;
|
|
1176
|
+
}
|
|
1177
|
+
else {
|
|
1178
|
+
indexName = `${sortProperty.property}Index`;
|
|
1179
|
+
gsiAttribute = sortProperty.property;
|
|
1165
1180
|
}
|
|
1166
|
-
indexName = propertySchema.isPrimary
|
|
1167
|
-
? undefined
|
|
1168
|
-
: `${sortProperty.property}Index`;
|
|
1169
1181
|
scanAscending = sortProperty.sortDirection === SortDirection.Ascending;
|
|
1170
1182
|
}
|
|
1171
1183
|
}
|
|
@@ -1191,13 +1203,14 @@ export class DynamoDbEntityStorageConnector {
|
|
|
1191
1203
|
let scanStartKey = Is.empty(cursor)
|
|
1192
1204
|
? undefined
|
|
1193
1205
|
: ObjectHelper.fromBytes(Converter.base64ToBytes(cursor));
|
|
1206
|
+
const scanProjection = this.buildProjectionExpression(properties, attributeNames);
|
|
1194
1207
|
do {
|
|
1195
1208
|
const scanResult = await dbConnection.send(new RawScanCommand({
|
|
1196
1209
|
TableName: this._config.tableName,
|
|
1197
1210
|
FilterExpression: scanFilter,
|
|
1198
1211
|
ExpressionAttributeNames: attributeNames,
|
|
1199
1212
|
ExpressionAttributeValues: attributeValues,
|
|
1200
|
-
ProjectionExpression:
|
|
1213
|
+
ProjectionExpression: scanProjection,
|
|
1201
1214
|
ExclusiveStartKey: scanStartKey
|
|
1202
1215
|
}));
|
|
1203
1216
|
matchingItems.push(...(scanResult.Items ?? []));
|
|
@@ -1226,6 +1239,7 @@ export class DynamoDbEntityStorageConnector {
|
|
|
1226
1239
|
if (expressions.keyCondition.length > 0) {
|
|
1227
1240
|
keyExpression += ` AND ${expressions.keyCondition}`;
|
|
1228
1241
|
}
|
|
1242
|
+
const queryProjection = this.buildProjectionExpression(properties, attributeNames);
|
|
1229
1243
|
const query = new QueryCommand({
|
|
1230
1244
|
TableName: this._config.tableName,
|
|
1231
1245
|
IndexName: indexName,
|
|
@@ -1235,7 +1249,7 @@ export class DynamoDbEntityStorageConnector {
|
|
|
1235
1249
|
: undefined,
|
|
1236
1250
|
ExpressionAttributeNames: attributeNames,
|
|
1237
1251
|
ExpressionAttributeValues: attributeValues,
|
|
1238
|
-
ProjectionExpression:
|
|
1252
|
+
ProjectionExpression: queryProjection,
|
|
1239
1253
|
Limit: returnSize + 1,
|
|
1240
1254
|
ScanIndexForward: scanAscending,
|
|
1241
1255
|
ExclusiveStartKey: Is.empty(cursor)
|
|
@@ -1254,8 +1268,8 @@ export class DynamoDbEntityStorageConnector {
|
|
|
1254
1268
|
[DynamoDbEntityStorageConnector._PARTITION_KEY]: lastRawItem[DynamoDbEntityStorageConnector._PARTITION_KEY],
|
|
1255
1269
|
[this._primaryKey.property]: lastRawItem[this._primaryKey.property]
|
|
1256
1270
|
};
|
|
1257
|
-
if (Is.stringValue(
|
|
1258
|
-
syntheticKey[
|
|
1271
|
+
if (Is.stringValue(gsiAttribute)) {
|
|
1272
|
+
syntheticKey[gsiAttribute] = lastRawItem[gsiAttribute];
|
|
1259
1273
|
}
|
|
1260
1274
|
resultCursor = Converter.bytesToBase64(ObjectHelper.toBytes(syntheticKey));
|
|
1261
1275
|
}
|
|
@@ -1308,5 +1322,26 @@ export class DynamoDbEntityStorageConnector {
|
|
|
1308
1322
|
}
|
|
1309
1323
|
return { conditionExpression, attributeNames, attributeValues };
|
|
1310
1324
|
}
|
|
1325
|
+
/**
|
|
1326
|
+
* Build a ProjectionExpression string and register a safe alias in attributeNames for every
|
|
1327
|
+
* projected property, preventing ValidationException when a property name is a DynamoDB
|
|
1328
|
+
* reserved word (e.g. "role", "name", "status").
|
|
1329
|
+
* @param properties The properties to project, or undefined to return all attributes.
|
|
1330
|
+
* @param attributeNames The expression attribute names map to mutate with the aliases.
|
|
1331
|
+
* @returns The ProjectionExpression string, or undefined when no projection is needed.
|
|
1332
|
+
* @internal
|
|
1333
|
+
*/
|
|
1334
|
+
buildProjectionExpression(properties, attributeNames) {
|
|
1335
|
+
if (!Is.arrayValue(properties)) {
|
|
1336
|
+
return undefined;
|
|
1337
|
+
}
|
|
1338
|
+
return properties
|
|
1339
|
+
.map(p => {
|
|
1340
|
+
const alias = `#p_${p}`;
|
|
1341
|
+
attributeNames[alias] = p;
|
|
1342
|
+
return alias;
|
|
1343
|
+
})
|
|
1344
|
+
.join(", ");
|
|
1345
|
+
}
|
|
1311
1346
|
}
|
|
1312
1347
|
//# sourceMappingURL=dynamoDbEntityStorageConnector.js.map
|
|
@@ -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\tObjectHelper\n} from \"@twin.org/core\";\nimport {\n\tComparisonOperator,\n\ttype EntityCondition,\n\tEntitySchemaFactory,\n\tEntitySchemaHelper,\n\ttype EntitySchemaPropertyType,\n\ttype IComparator,\n\ttype IEntitySchema,\n\ttype IEntitySchemaProperty,\n\tLogicalOperator,\n\tSortDirection\n} from \"@twin.org/entity\";\nimport {\n\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}\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\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<T, U>,\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<T, U>,\n\t\tloggingComponentType?: string\n\t): Promise<void> {\n\t\t// If something failed the only thing to cleanup is the migration table\n\t\tawait targetConnector?.teardown?.(loggingComponentType);\n\t}\n\n\t/**\n\t * Copy all entities from sourceConnector to destConnector, paging through each partition.\n\t * @param sourceConnector The connector to read entities from.\n\t * @param destConnector The connector to write entities to.\n\t * @param partitions The partition list returned by getPartitionContextIds.\n\t * @param batchSize The number of entities to read per page.\n\t * @internal\n\t */\n\tprivate async bulkCopy<U>(\n\t\tsourceConnector: 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\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\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\ttry {\n\t\t\tconst returnSize = limit ?? DynamoDbEntityStorageConnector._DEFAULT_LIMIT;\n\n\t\t\tlet indexName: string | undefined = Is.stringValue(secondaryIndex)\n\t\t\t\t? `${secondaryIndex}Index`\n\t\t\t\t: undefined;\n\n\t\t\t// If we have a sortable property defined in the descriptor then we must use\n\t\t\t// the secondary index for the query\n\t\t\tlet scanAscending = true;\n\t\t\tif (Is.arrayValue(sortProperties)) {\n\t\t\t\tif (sortProperties.length > 1) {\n\t\t\t\t\tthrow new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, \"sortSingle\");\n\t\t\t\t}\n\n\t\t\t\tfor (const sortProperty of sortProperties) {\n\t\t\t\t\tconst propertySchema = this._entitySchema.properties?.find(\n\t\t\t\t\t\te => e.property === sortProperty.property\n\t\t\t\t\t);\n\t\t\t\t\tif (\n\t\t\t\t\t\tIs.undefined(propertySchema) ||\n\t\t\t\t\t\t(!propertySchema.isPrimary &&\n\t\t\t\t\t\t\t!propertySchema.isSecondary &&\n\t\t\t\t\t\t\tIs.empty(propertySchema.sortDirection))\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, \"sortNotIndexed\", {\n\t\t\t\t\t\t\tproperty: sortProperty.property\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\tindexName = propertySchema.isPrimary\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: `${sortProperty.property as string}Index`;\n\t\t\t\t\tscanAscending = sortProperty.sortDirection === SortDirection.Ascending;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst attributeNames: { [id: string]: string } = { \"#partitionId\": \"partitionId\" };\n\t\t\tconst attributeValues: { [id: string]: AttributeValue } = {\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\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\tsecondaryIndex\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\t// OR conditions on primary key attributes can't use KeyConditionExpression or\n\t\t\t// FilterExpression in a QueryCommand — fall back to a full table ScanCommand.\n\t\t\tif (expressions.requiresScan) {\n\t\t\t\tlet scanFilter = \"#partitionId = :partitionId\";\n\t\t\t\tif (Is.stringValue(expressions.filterCondition)) {\n\t\t\t\t\tscanFilter += ` AND ${expressions.filterCondition.trim()}`;\n\t\t\t\t}\n\n\t\t\t\tconst dbConnection = this.createConnection();\n\t\t\t\tconst matchingItems: { [id: string]: AttributeValue }[] = [];\n\t\t\t\tlet scanStartKey: { [id: string]: AttributeValue } | undefined = Is.empty(cursor)\n\t\t\t\t\t? undefined\n\t\t\t\t\t: ObjectHelper.fromBytes(Converter.base64ToBytes(cursor));\n\n\t\t\t\tdo {\n\t\t\t\t\tconst scanResult = await dbConnection.send(\n\t\t\t\t\t\tnew RawScanCommand({\n\t\t\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\t\t\tFilterExpression: scanFilter,\n\t\t\t\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\t\t\t\tProjectionExpression: properties?.map(p => p as string).join(\", \"),\n\t\t\t\t\t\t\tExclusiveStartKey: scanStartKey\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\tmatchingItems.push(...(scanResult.Items ?? []));\n\t\t\t\t\tscanStartKey = scanResult.LastEvaluatedKey;\n\t\t\t\t} while (!Is.empty(scanStartKey));\n\n\t\t\t\tconst hasMore = matchingItems.length > returnSize;\n\t\t\t\tconst returnedRawItems = hasMore ? matchingItems.slice(0, returnSize) : matchingItems;\n\n\t\t\t\tlet resultCursor: string | undefined;\n\t\t\t\tif (hasMore) {\n\t\t\t\t\tconst lastRawItem = returnedRawItems[returnedRawItems.length - 1];\n\t\t\t\t\tconst syntheticKey: { [id: string]: AttributeValue } = {\n\t\t\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\t\tlastRawItem[DynamoDbEntityStorageConnector._PARTITION_KEY],\n\t\t\t\t\t\t[this._primaryKey.property as string]: lastRawItem[this._primaryKey.property as string]\n\t\t\t\t\t};\n\t\t\t\t\tresultCursor = Converter.bytesToBase64(ObjectHelper.toBytes(syntheticKey));\n\t\t\t\t}\n\n\t\t\t\tconst scanEntities: T[] = returnedRawItems.map(item => {\n\t\t\t\t\tconst unmarshalled = unmarshall(item);\n\t\t\t\t\treturn EntityStorageHelper.unPrepareEntity(unmarshalled as T, [\n\t\t\t\t\t\tDynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t]);\n\t\t\t\t});\n\n\t\t\t\treturn { entities: scanEntities, cursor: resultCursor };\n\t\t\t}\n\n\t\t\tlet keyExpression = \"#partitionId = :partitionId\";\n\t\t\tif (expressions.keyCondition.length > 0) {\n\t\t\t\tkeyExpression += ` AND ${expressions.keyCondition}`;\n\t\t\t}\n\n\t\t\tconst query = new 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\tFilterExpression: Is.stringValue(expressions.filterCondition)\n\t\t\t\t\t? expressions.filterCondition\n\t\t\t\t\t: undefined,\n\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\tProjectionExpression: properties?.map(p => p as string).join(\", \"),\n\t\t\t\tLimit: returnSize + 1,\n\t\t\t\tScanIndexForward: scanAscending,\n\t\t\t\tExclusiveStartKey: Is.empty(cursor)\n\t\t\t\t\t? undefined\n\t\t\t\t\t: ObjectHelper.fromBytes(Converter.base64ToBytes(cursor))\n\t\t\t});\n\n\t\t\tconst connection = this.createDocClient();\n\n\t\t\tconst results = await connection.send(query);\n\n\t\t\tconst rawItems = results.Items ?? [];\n\t\t\tconst hasMore = rawItems.length > returnSize;\n\t\t\tconst returnedRawItems = hasMore ? rawItems.slice(0, returnSize) : rawItems;\n\n\t\t\tlet resultCursor: string | undefined;\n\t\t\tif (hasMore) {\n\t\t\t\tconst lastRawItem = returnedRawItems[returnedRawItems.length - 1] as {\n\t\t\t\t\t[id: string]: AttributeValue;\n\t\t\t\t};\n\t\t\t\tconst syntheticKey: { [id: string]: AttributeValue } = {\n\t\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\tlastRawItem[DynamoDbEntityStorageConnector._PARTITION_KEY],\n\t\t\t\t\t[this._primaryKey.property as string]: lastRawItem[this._primaryKey.property as string]\n\t\t\t\t};\n\t\t\t\tif (Is.stringValue(secondaryIndex)) {\n\t\t\t\t\tsyntheticKey[secondaryIndex] = lastRawItem[secondaryIndex];\n\t\t\t\t}\n\t\t\t\tresultCursor = Converter.bytesToBase64(ObjectHelper.toBytes(syntheticKey));\n\t\t\t}\n\n\t\t\tconst entities: T[] = returnedRawItems.map(item => {\n\t\t\t\tconst unmarshalled = unmarshall(item);\n\t\t\t\treturn EntityStorageHelper.unPrepareEntity(unmarshalled as T, [\n\t\t\t\t\tDynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t\t]);\n\t\t\t});\n\n\t\t\treturn { entities, cursor: resultCursor };\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 * 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"]}
|
|
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}\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<T, U>,\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<T, U>,\n\t\tloggingComponentType?: string\n\t): Promise<void> {\n\t\t// If something failed the only thing to cleanup is the migration table\n\t\tawait targetConnector?.teardown?.(loggingComponentType);\n\t}\n\n\t/**\n\t * Copy all entities from sourceConnector to destConnector, paging through each partition.\n\t * @param sourceConnector The connector to read entities from.\n\t * @param destConnector The connector to write entities to.\n\t * @param partitions The partition list returned by getPartitionContextIds.\n\t * @param batchSize The number of entities to read per page.\n\t * @internal\n\t */\n\tprivate async bulkCopy<U>(\n\t\tsourceConnector: 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\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\ttry {\n\t\t\tconst returnSize = limit ?? DynamoDbEntityStorageConnector._DEFAULT_LIMIT;\n\n\t\t\tlet indexName: string | undefined = Is.stringValue(secondaryIndex)\n\t\t\t\t? `${secondaryIndex}Index`\n\t\t\t\t: undefined;\n\t\t\t// The attribute whose value must appear in ExclusiveStartKey when querying a GSI\n\t\t\tlet gsiAttribute: string | undefined = secondaryIndex;\n\n\t\t\t// If we have a sortable property defined in the descriptor then we must use\n\t\t\t// the secondary index for the query\n\t\t\tlet scanAscending = true;\n\t\t\tif (Is.arrayValue(sortProperties)) {\n\t\t\t\tif (sortProperties.length > 1) {\n\t\t\t\t\tthrow new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, \"sortSingle\");\n\t\t\t\t}\n\n\t\t\t\tfor (const sortProperty of sortProperties) {\n\t\t\t\t\tconst propertySchema = this._entitySchema.properties?.find(\n\t\t\t\t\t\te => e.property === sortProperty.property\n\t\t\t\t\t);\n\t\t\t\t\tif (propertySchema?.isPrimary) {\n\t\t\t\t\t\tindexName = undefined;\n\t\t\t\t\t\tgsiAttribute = undefined;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tindexName = `${sortProperty.property as string}Index`;\n\t\t\t\t\t\tgsiAttribute = sortProperty.property as string;\n\t\t\t\t\t}\n\t\t\t\t\tscanAscending = sortProperty.sortDirection === SortDirection.Ascending;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst attributeNames: { [id: string]: string } = { \"#partitionId\": \"partitionId\" };\n\t\t\tconst attributeValues: { [id: string]: AttributeValue } = {\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\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\tsecondaryIndex\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\t// OR conditions on primary key attributes can't use KeyConditionExpression or\n\t\t\t// FilterExpression in a QueryCommand — fall back to a full table ScanCommand.\n\t\t\tif (expressions.requiresScan) {\n\t\t\t\tlet scanFilter = \"#partitionId = :partitionId\";\n\t\t\t\tif (Is.stringValue(expressions.filterCondition)) {\n\t\t\t\t\tscanFilter += ` AND ${expressions.filterCondition.trim()}`;\n\t\t\t\t}\n\n\t\t\t\tconst dbConnection = this.createConnection();\n\t\t\t\tconst matchingItems: { [id: string]: AttributeValue }[] = [];\n\t\t\t\tlet scanStartKey: { [id: string]: AttributeValue } | undefined = Is.empty(cursor)\n\t\t\t\t\t? undefined\n\t\t\t\t\t: ObjectHelper.fromBytes(Converter.base64ToBytes(cursor));\n\t\t\t\tconst scanProjection = this.buildProjectionExpression(properties, attributeNames);\n\n\t\t\t\tdo {\n\t\t\t\t\tconst scanResult = await dbConnection.send(\n\t\t\t\t\t\tnew RawScanCommand({\n\t\t\t\t\t\t\tTableName: this._config.tableName,\n\t\t\t\t\t\t\tFilterExpression: scanFilter,\n\t\t\t\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\t\t\t\tProjectionExpression: scanProjection,\n\t\t\t\t\t\t\tExclusiveStartKey: scanStartKey\n\t\t\t\t\t\t})\n\t\t\t\t\t);\n\t\t\t\t\tmatchingItems.push(...(scanResult.Items ?? []));\n\t\t\t\t\tscanStartKey = scanResult.LastEvaluatedKey;\n\t\t\t\t} while (!Is.empty(scanStartKey));\n\n\t\t\t\tconst hasMore = matchingItems.length > returnSize;\n\t\t\t\tconst returnedRawItems = hasMore ? matchingItems.slice(0, returnSize) : matchingItems;\n\n\t\t\t\tlet resultCursor: string | undefined;\n\t\t\t\tif (hasMore) {\n\t\t\t\t\tconst lastRawItem = returnedRawItems[returnedRawItems.length - 1];\n\t\t\t\t\tconst syntheticKey: { [id: string]: AttributeValue } = {\n\t\t\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\t\tlastRawItem[DynamoDbEntityStorageConnector._PARTITION_KEY],\n\t\t\t\t\t\t[this._primaryKey.property as string]: lastRawItem[this._primaryKey.property as string]\n\t\t\t\t\t};\n\t\t\t\t\tresultCursor = Converter.bytesToBase64(ObjectHelper.toBytes(syntheticKey));\n\t\t\t\t}\n\n\t\t\t\tconst scanEntities: T[] = returnedRawItems.map(item => {\n\t\t\t\t\tconst unmarshalled = unmarshall(item);\n\t\t\t\t\treturn EntityStorageHelper.unPrepareEntity(unmarshalled as T, [\n\t\t\t\t\t\tDynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t\t\t]);\n\t\t\t\t});\n\n\t\t\t\treturn { entities: scanEntities, cursor: resultCursor };\n\t\t\t}\n\n\t\t\tlet keyExpression = \"#partitionId = :partitionId\";\n\t\t\tif (expressions.keyCondition.length > 0) {\n\t\t\t\tkeyExpression += ` AND ${expressions.keyCondition}`;\n\t\t\t}\n\n\t\t\tconst queryProjection = this.buildProjectionExpression(properties, attributeNames);\n\t\t\tconst query = new 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\tFilterExpression: Is.stringValue(expressions.filterCondition)\n\t\t\t\t\t? expressions.filterCondition\n\t\t\t\t\t: undefined,\n\t\t\t\tExpressionAttributeNames: attributeNames,\n\t\t\t\tExpressionAttributeValues: attributeValues,\n\t\t\t\tProjectionExpression: queryProjection,\n\t\t\t\tLimit: returnSize + 1,\n\t\t\t\tScanIndexForward: scanAscending,\n\t\t\t\tExclusiveStartKey: Is.empty(cursor)\n\t\t\t\t\t? undefined\n\t\t\t\t\t: ObjectHelper.fromBytes(Converter.base64ToBytes(cursor))\n\t\t\t});\n\n\t\t\tconst connection = this.createDocClient();\n\n\t\t\tconst results = await connection.send(query);\n\n\t\t\tconst rawItems = results.Items ?? [];\n\t\t\tconst hasMore = rawItems.length > returnSize;\n\t\t\tconst returnedRawItems = hasMore ? rawItems.slice(0, returnSize) : rawItems;\n\n\t\t\tlet resultCursor: string | undefined;\n\t\t\tif (hasMore) {\n\t\t\t\tconst lastRawItem = returnedRawItems[returnedRawItems.length - 1] as {\n\t\t\t\t\t[id: string]: AttributeValue;\n\t\t\t\t};\n\t\t\t\tconst syntheticKey: { [id: string]: AttributeValue } = {\n\t\t\t\t\t[DynamoDbEntityStorageConnector._PARTITION_KEY]:\n\t\t\t\t\t\tlastRawItem[DynamoDbEntityStorageConnector._PARTITION_KEY],\n\t\t\t\t\t[this._primaryKey.property as string]: lastRawItem[this._primaryKey.property as string]\n\t\t\t\t};\n\t\t\t\tif (Is.stringValue(gsiAttribute)) {\n\t\t\t\t\tsyntheticKey[gsiAttribute] = lastRawItem[gsiAttribute];\n\t\t\t\t}\n\t\t\t\tresultCursor = Converter.bytesToBase64(ObjectHelper.toBytes(syntheticKey));\n\t\t\t}\n\n\t\t\tconst entities: T[] = returnedRawItems.map(item => {\n\t\t\t\tconst unmarshalled = unmarshall(item);\n\t\t\t\treturn EntityStorageHelper.unPrepareEntity(unmarshalled as T, [\n\t\t\t\t\tDynamoDbEntityStorageConnector._PARTITION_KEY\n\t\t\t\t]);\n\t\t\t});\n\n\t\t\treturn { entities, cursor: resultCursor };\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 * 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,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.3-next.23](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-dynamodb-v0.0.3-next.22...entity-storage-connector-dynamodb-v0.0.3-next.23) (2026-06-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* entity storage conditions ([#115](https://github.com/iotaledger/twin-entity-storage/issues/115)) ([7a53884](https://github.com/iotaledger/twin-entity-storage/commit/7a53884f6acb856d77733e4e0f23ec1c00b74cb4))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/entity-storage-models bumped from 0.0.3-next.22 to 0.0.3-next.23
|
|
16
|
+
* devDependencies
|
|
17
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.3-next.22 to 0.0.3-next.23
|
|
18
|
+
|
|
3
19
|
## [0.0.3-next.22](https://github.com/iotaledger/twin-entity-storage/compare/entity-storage-connector-dynamodb-v0.0.3-next.21...entity-storage-connector-dynamodb-v0.0.3-next.22) (2026-06-08)
|
|
4
20
|
|
|
5
21
|
|
package/locales/en.json
CHANGED
|
@@ -19,7 +19,6 @@
|
|
|
19
19
|
"comparisonNotSupported": "Comparison operator \"{comparison}\" is not supported",
|
|
20
20
|
"conditionalNotSupported": "Conditional operator \"{operator}\" is not supported",
|
|
21
21
|
"sortSingle": "You can only sort by a single property",
|
|
22
|
-
"sortNotIndexed": "The property \"{property}\" is not indexed and cannot be used for sorting",
|
|
23
22
|
"propertyNotFound": "The property \"{property}\" was not found on the entity schema",
|
|
24
23
|
"getPartitionContextIdsFailed": "Unable to get partition context ids",
|
|
25
24
|
"setBatchFailed": "Unable to set batch of entities",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/entity-storage-connector-dynamodb",
|
|
3
|
-
"version": "0.0.3-next.
|
|
3
|
+
"version": "0.0.3-next.23",
|
|
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.0.3-next.
|
|
23
|
+
"@twin.org/entity-storage-models": "0.0.3-next.23",
|
|
24
24
|
"@twin.org/logging-models": "next",
|
|
25
25
|
"@twin.org/nameof": "next"
|
|
26
26
|
},
|