@twin.org/entity-storage-connector-dynamodb 0.0.1-next.8 → 0.0.1

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.
@@ -1,8 +1,8 @@
1
- import { waitUntilTableExists, QueryCommand, DynamoDB } from '@aws-sdk/client-dynamodb';
1
+ import { waitUntilTableExists, DynamoDB, QueryCommand } from '@aws-sdk/client-dynamodb';
2
2
  import { GetCommand, PutCommand, DeleteCommand, DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
3
3
  import { unmarshall } from '@aws-sdk/util-dynamodb';
4
- import { Guards, Is, BaseError, GeneralError, ObjectHelper, Converter, Coerce } from '@twin.org/core';
5
- import { EntitySchemaFactory, EntitySchemaHelper, ComparisonOperator, LogicalOperator } from '@twin.org/entity';
4
+ import { Guards, Is, BaseError, GeneralError, Coerce, ObjectHelper, Converter } from '@twin.org/core';
5
+ import { EntitySchemaFactory, EntitySchemaHelper, ComparisonOperator, LogicalOperator, SortDirection } from '@twin.org/entity';
6
6
  import { LoggingConnectorFactory } from '@twin.org/logging-models';
7
7
 
8
8
  // Copyright 2024 IOTA Stiftung.
@@ -48,9 +48,6 @@ class DynamoDbEntityStorageConnector {
48
48
  /**
49
49
  * Create a new instance of DynamoDbEntityStorageConnector.
50
50
  * @param options The options for the connector.
51
- * @param options.entitySchema The schema for the entity.
52
- * @param options.loggingConnectorType The type of logging connector to use, defaults to no logging.
53
- * @param options.config The configuration for the connector.
54
51
  */
55
52
  constructor(options) {
56
53
  Guards.object(this.CLASS_NAME, "options", options);
@@ -223,13 +220,14 @@ class DynamoDbEntityStorageConnector {
223
220
  * Get an entity.
224
221
  * @param id The id of the entity to get, or the index value if secondaryIndex is set.
225
222
  * @param secondaryIndex Get the item using a secondary index.
223
+ * @param conditions The optional conditions to match for the entities.
226
224
  * @returns The object if it can be found or undefined.
227
225
  */
228
- async get(id, secondaryIndex) {
226
+ async get(id, secondaryIndex, conditions) {
229
227
  Guards.stringValue(this.CLASS_NAME, "id", id);
230
228
  try {
231
229
  const docClient = this.createDocClient();
232
- if (Is.undefined(secondaryIndex)) {
230
+ if (Is.empty(secondaryIndex) && Is.empty(conditions)) {
233
231
  const getCommand = new GetCommand({
234
232
  TableName: this._config.tableName,
235
233
  Key: {
@@ -241,27 +239,27 @@ class DynamoDbEntityStorageConnector {
241
239
  delete response.Item?.[DynamoDbEntityStorageConnector._PARTITION_ID_NAME];
242
240
  return response.Item;
243
241
  }
244
- const secIndex = secondaryIndex.toString();
245
- const globalSecondaryIndex = `${secIndex}Index`;
246
- const queryCommand = new QueryCommand({
247
- TableName: this._config.tableName,
248
- IndexName: globalSecondaryIndex,
249
- KeyConditionExpression: `#${secIndex} = :id AND #${DynamoDbEntityStorageConnector._PARTITION_ID_NAME} = :${DynamoDbEntityStorageConnector._PARTITION_ID_NAME}`,
250
- ExpressionAttributeNames: {
251
- [`#${secIndex}`]: secIndex,
252
- [`#${DynamoDbEntityStorageConnector._PARTITION_ID_NAME}`]: DynamoDbEntityStorageConnector._PARTITION_ID_NAME
253
- },
254
- ExpressionAttributeValues: {
255
- [`:${DynamoDbEntityStorageConnector._PARTITION_ID_NAME}`]: {
256
- S: DynamoDbEntityStorageConnector._PARTITION_ID_VALUE
257
- },
258
- ":id": { S: id }
242
+ const finalConditions = {
243
+ conditions: []
244
+ };
245
+ if (Is.stringValue(secondaryIndex)) {
246
+ finalConditions.conditions.push({
247
+ property: secondaryIndex,
248
+ comparison: ComparisonOperator.Equals,
249
+ value: id
250
+ });
251
+ }
252
+ if (Is.arrayValue(conditions)) {
253
+ for (const c of conditions) {
254
+ finalConditions.conditions.push({
255
+ property: c.property,
256
+ comparison: ComparisonOperator.Equals,
257
+ value: c.value
258
+ });
259
259
  }
260
- });
261
- const response = await docClient.send(queryCommand);
262
- if (response.Items?.length === 1) {
263
- return unmarshall(response.Items[0]);
264
260
  }
261
+ const queryResult = await this.internalQuery(finalConditions, undefined, undefined, undefined, 1, secondaryIndex);
262
+ return queryResult.entities[0];
265
263
  }
266
264
  catch (err) {
267
265
  if (BaseError.isErrorCode(err, "ResourceNotFoundException")) {
@@ -273,28 +271,40 @@ class DynamoDbEntityStorageConnector {
273
271
  id
274
272
  }, err);
275
273
  }
276
- return undefined;
277
274
  }
278
275
  /**
279
276
  * Set an entity.
280
277
  * @param entity The entity to set.
278
+ * @param conditions The optional conditions to match for the entities.
281
279
  * @returns The id of the entity.
282
280
  */
283
- async set(entity) {
281
+ async set(entity, conditions) {
284
282
  Guards.object(this.CLASS_NAME, "entity", entity);
283
+ EntitySchemaHelper.validateEntity(entity, this.getSchema());
285
284
  const id = entity[this._primaryKey.property];
286
285
  try {
287
286
  const docClient = this.createDocClient();
287
+ const { conditionExpression, attributeNames, attributeValues } = this.buildConditionExpression(conditions);
288
288
  const putCommand = new PutCommand({
289
289
  TableName: this._config.tableName,
290
290
  Item: {
291
291
  [DynamoDbEntityStorageConnector._PARTITION_ID_NAME]: DynamoDbEntityStorageConnector._PARTITION_ID_VALUE,
292
292
  ...entity
293
- }
293
+ },
294
+ // Only set the condition expression if we have conditions to match
295
+ // and the primary key exists, otherwise we are creating a new object
296
+ ConditionExpression: Is.stringValue(conditionExpression)
297
+ ? `(attribute_exists(${this._primaryKey.property}) AND ${conditionExpression}) OR attribute_not_exists(${this._primaryKey.property})`
298
+ : undefined,
299
+ ExpressionAttributeNames: attributeNames,
300
+ ExpressionAttributeValues: attributeValues
294
301
  });
295
302
  await docClient.send(putCommand);
296
303
  }
297
304
  catch (err) {
305
+ if (BaseError.isErrorName(err, "ConditionalCheckFailedException")) {
306
+ return;
307
+ }
298
308
  if (BaseError.isErrorCode(err, "ResourceNotFoundException")) {
299
309
  throw new GeneralError(this.CLASS_NAME, "tableDoesNotExist", {
300
310
  tableName: this._config.tableName
@@ -308,22 +318,30 @@ class DynamoDbEntityStorageConnector {
308
318
  /**
309
319
  * Remove the entity.
310
320
  * @param id The id of the entity to remove.
321
+ * @param conditions The optional conditions to match for the entities.
311
322
  * @returns Nothing.
312
323
  */
313
- async remove(id) {
324
+ async remove(id, conditions) {
314
325
  Guards.stringValue(this.CLASS_NAME, "id", id);
315
326
  try {
316
327
  const docClient = this.createDocClient();
328
+ const { conditionExpression, attributeNames, attributeValues } = this.buildConditionExpression(conditions);
317
329
  const deleteCommand = new DeleteCommand({
318
330
  TableName: this._config.tableName,
319
331
  Key: {
320
332
  [DynamoDbEntityStorageConnector._PARTITION_ID_NAME]: DynamoDbEntityStorageConnector._PARTITION_ID_VALUE,
321
333
  [this._primaryKey.property]: id
322
- }
334
+ },
335
+ ConditionExpression: conditionExpression,
336
+ ExpressionAttributeNames: attributeNames,
337
+ ExpressionAttributeValues: attributeValues
323
338
  });
324
339
  await docClient.send(deleteCommand);
325
340
  }
326
341
  catch (err) {
342
+ if (BaseError.isErrorName(err, "ConditionalCheckFailedException")) {
343
+ return;
344
+ }
327
345
  if (BaseError.isErrorCode(err, "ResourceNotFoundException")) {
328
346
  throw new GeneralError(this.CLASS_NAME, "tableDoesNotExist", {
329
347
  table: this._config.tableName
@@ -345,77 +363,7 @@ class DynamoDbEntityStorageConnector {
345
363
  * and a cursor which can be used to request more entities.
346
364
  */
347
365
  async query(conditions, sortProperties, properties, cursor, pageSize) {
348
- try {
349
- const returnSize = pageSize ?? DynamoDbEntityStorageConnector._PAGE_SIZE;
350
- let indexName;
351
- // If we have a sortable property defined in the descriptor then we must use
352
- // the secondary index for the query
353
- if (Is.arrayValue(sortProperties)) {
354
- if (sortProperties.length > 1) {
355
- throw new GeneralError(this.CLASS_NAME, "sortSingle");
356
- }
357
- for (const sortProperty of sortProperties) {
358
- const propertySchema = this._entitySchema.properties?.find(e => e.property === sortProperty.property);
359
- if (Is.undefined(propertySchema) ||
360
- (!propertySchema.isPrimary &&
361
- !propertySchema.isSecondary &&
362
- Is.empty(propertySchema.sortDirection))) {
363
- throw new GeneralError(this.CLASS_NAME, "sortNotIndexed", {
364
- property: sortProperty.property
365
- });
366
- }
367
- indexName = propertySchema.isPrimary
368
- ? undefined
369
- : `${sortProperty.property}Index`;
370
- }
371
- }
372
- const attributeNames = { "#partitionId": "partitionId" };
373
- const attributeValues = {
374
- [`:${DynamoDbEntityStorageConnector._PARTITION_ID_NAME}`]: {
375
- S: DynamoDbEntityStorageConnector._PARTITION_ID_VALUE
376
- }
377
- };
378
- const expressions = this.buildQueryParameters("", conditions, attributeNames, attributeValues);
379
- let keyExpression = "#partitionId = :partitionId";
380
- if (expressions.keyCondition.length > 0) {
381
- keyExpression += ` AND ${expressions.keyCondition}`;
382
- }
383
- const query = new QueryCommand({
384
- TableName: this._config.tableName,
385
- IndexName: indexName,
386
- KeyConditionExpression: keyExpression,
387
- FilterExpression: Is.stringValue(expressions.filterCondition)
388
- ? expressions.filterCondition
389
- : undefined,
390
- ExpressionAttributeNames: attributeNames,
391
- ExpressionAttributeValues: attributeValues,
392
- ProjectionExpression: properties?.map(p => p).join(", "),
393
- Limit: returnSize,
394
- ExclusiveStartKey: Is.empty(cursor)
395
- ? undefined
396
- : ObjectHelper.fromBytes(Converter.base64ToBytes(cursor))
397
- });
398
- const connection = this.createDocClient();
399
- const results = await connection.send(query);
400
- let entities = [];
401
- if (Is.arrayValue(results.Items)) {
402
- entities = results.Items.map(item => unmarshall(item));
403
- }
404
- return {
405
- entities,
406
- cursor: Is.empty(results.LastEvaluatedKey)
407
- ? undefined
408
- : Converter.bytesToBase64(ObjectHelper.toBytes(results.LastEvaluatedKey))
409
- };
410
- }
411
- catch (err) {
412
- if (BaseError.isErrorCode(err, "ResourceNotFoundException")) {
413
- throw new GeneralError(this.CLASS_NAME, "tableDoesNotExist", {
414
- table: this._config.tableName
415
- }, err);
416
- }
417
- throw new GeneralError(this.CLASS_NAME, "queryFailed", undefined, err);
418
- }
366
+ return this.internalQuery(conditions, sortProperties, properties, cursor, pageSize);
419
367
  }
420
368
  /**
421
369
  * Delete the table.
@@ -437,7 +385,7 @@ class DynamoDbEntityStorageConnector {
437
385
  * @returns The condition clause.
438
386
  * @internal
439
387
  */
440
- buildQueryParameters(objectPath, condition, attributeNames, attributeValues) {
388
+ buildQueryParameters(objectPath, condition, attributeNames, attributeValues, secondaryIndex) {
441
389
  // If no conditions are defined then return empty string
442
390
  if (Is.undefined(condition)) {
443
391
  return {
@@ -453,7 +401,7 @@ class DynamoDbEntityStorageConnector {
453
401
  };
454
402
  }
455
403
  // It's a group of comparisons, so check the individual items and combine with the logical operator
456
- const joinConditions = condition.conditions.map(c => this.buildQueryParameters(objectPath, c, attributeNames, attributeValues));
404
+ const joinConditions = condition.conditions.map(c => this.buildQueryParameters(objectPath, c, attributeNames, attributeValues, secondaryIndex));
457
405
  const logicalOperator = this.mapConditionalOperator(condition.logicalOperator);
458
406
  const keyCondition = joinConditions
459
407
  .filter(j => j.keyCondition.length > 0)
@@ -471,9 +419,10 @@ class DynamoDbEntityStorageConnector {
471
419
  const schemaProp = this._entitySchema.properties?.find(p => p.property === condition.property);
472
420
  // It's a single value so just create the property comparison for the condition
473
421
  const comparison = this.mapComparisonOperator(objectPath, condition, schemaProp?.type, attributeNames, attributeValues);
422
+ const isKey = schemaProp?.isPrimary || (schemaProp?.isSecondary && schemaProp?.property === secondaryIndex);
474
423
  return {
475
- keyCondition: schemaProp?.isPrimary ? comparison : "",
476
- filterCondition: schemaProp?.isPrimary ? "" : comparison
424
+ keyCondition: isKey ? comparison : "",
425
+ filterCondition: !isKey ? comparison : ""
477
426
  };
478
427
  }
479
428
  /**
@@ -494,6 +443,14 @@ class DynamoDbEntityStorageConnector {
494
443
  }
495
444
  prop += comparator.property;
496
445
  let attributeName = this.populateAttributeNames(prop, attributeNames);
446
+ if (Is.empty(comparator.value)) {
447
+ if (comparator.comparison === ComparisonOperator.Equals) {
448
+ return `attribute_not_exists(${attributeName})`;
449
+ }
450
+ else if (comparator.comparison === ComparisonOperator.NotEquals) {
451
+ return `attribute_exists(${attributeName})`;
452
+ }
453
+ }
497
454
  let propName = `:${attributeName.replace(/\./g, "").replace(/#/g, "")}`;
498
455
  if (Is.array(comparator.value)) {
499
456
  const dbValues = comparator.value.map(v => this.propertyToDbValue(v, type));
@@ -617,7 +574,7 @@ class DynamoDbEntityStorageConnector {
617
574
  }
618
575
  /**
619
576
  * Create a new DB connection.
620
- * @returns The dynamo db connection.
577
+ * @returns The Dynamo DB connection.
621
578
  * @internal
622
579
  */
623
580
  createConnection() {
@@ -625,7 +582,7 @@ class DynamoDbEntityStorageConnector {
625
582
  }
626
583
  /**
627
584
  * Create a new DB connection configuration.
628
- * @returns The dynamo db connection configuration.
585
+ * @returns The Dynamo DB connection configuration.
629
586
  * @internal
630
587
  */
631
588
  createConnectionConfig() {
@@ -654,6 +611,132 @@ class DynamoDbEntityStorageConnector {
654
611
  return false;
655
612
  }
656
613
  }
614
+ /**
615
+ * Find all the entities which match the conditions.
616
+ * @param conditions The conditions to match for the entities.
617
+ * @param sortProperties The optional sort order.
618
+ * @param properties The optional properties to return, defaults to all.
619
+ * @param cursor The cursor to request the next page of entities.
620
+ * @param pageSize The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
621
+ * @param secondaryIndex The secondary index to use for the query.
622
+ * @returns All the entities for the storage matching the conditions,
623
+ * and a cursor which can be used to request more entities.
624
+ * @internal
625
+ */
626
+ async internalQuery(conditions, sortProperties, properties, cursor, pageSize, secondaryIndex) {
627
+ try {
628
+ const returnSize = pageSize ?? DynamoDbEntityStorageConnector._PAGE_SIZE;
629
+ let indexName = Is.stringValue(secondaryIndex)
630
+ ? `${secondaryIndex}Index`
631
+ : undefined;
632
+ // If we have a sortable property defined in the descriptor then we must use
633
+ // the secondary index for the query
634
+ let scanAscending = true;
635
+ if (Is.arrayValue(sortProperties)) {
636
+ if (sortProperties.length > 1) {
637
+ throw new GeneralError(this.CLASS_NAME, "sortSingle");
638
+ }
639
+ for (const sortProperty of sortProperties) {
640
+ const propertySchema = this._entitySchema.properties?.find(e => e.property === sortProperty.property);
641
+ if (Is.undefined(propertySchema) ||
642
+ (!propertySchema.isPrimary &&
643
+ !propertySchema.isSecondary &&
644
+ Is.empty(propertySchema.sortDirection))) {
645
+ throw new GeneralError(this.CLASS_NAME, "sortNotIndexed", {
646
+ property: sortProperty.property
647
+ });
648
+ }
649
+ indexName = propertySchema.isPrimary
650
+ ? undefined
651
+ : `${sortProperty.property}Index`;
652
+ scanAscending = sortProperty.sortDirection === SortDirection.Ascending;
653
+ }
654
+ }
655
+ const attributeNames = { "#partitionId": "partitionId" };
656
+ const attributeValues = {
657
+ [`:${DynamoDbEntityStorageConnector._PARTITION_ID_NAME}`]: {
658
+ S: DynamoDbEntityStorageConnector._PARTITION_ID_VALUE
659
+ }
660
+ };
661
+ const expressions = this.buildQueryParameters("", conditions, attributeNames, attributeValues, secondaryIndex);
662
+ let keyExpression = "#partitionId = :partitionId";
663
+ if (expressions.keyCondition.length > 0) {
664
+ keyExpression += ` AND ${expressions.keyCondition}`;
665
+ }
666
+ const query = new QueryCommand({
667
+ TableName: this._config.tableName,
668
+ IndexName: indexName,
669
+ KeyConditionExpression: keyExpression,
670
+ FilterExpression: Is.stringValue(expressions.filterCondition)
671
+ ? expressions.filterCondition
672
+ : undefined,
673
+ ExpressionAttributeNames: attributeNames,
674
+ ExpressionAttributeValues: attributeValues,
675
+ ProjectionExpression: properties?.map(p => p).join(", "),
676
+ Limit: returnSize,
677
+ ScanIndexForward: scanAscending,
678
+ ExclusiveStartKey: Is.empty(cursor)
679
+ ? undefined
680
+ : ObjectHelper.fromBytes(Converter.base64ToBytes(cursor))
681
+ });
682
+ const connection = this.createDocClient();
683
+ const results = await connection.send(query);
684
+ let entities = [];
685
+ if (Is.arrayValue(results.Items)) {
686
+ entities = results.Items.map(item => {
687
+ const unmarshalled = unmarshall(item);
688
+ delete unmarshalled[DynamoDbEntityStorageConnector._PARTITION_ID_NAME];
689
+ return unmarshalled;
690
+ });
691
+ }
692
+ return {
693
+ entities,
694
+ cursor: Is.empty(results.LastEvaluatedKey)
695
+ ? undefined
696
+ : Converter.bytesToBase64(ObjectHelper.toBytes(results.LastEvaluatedKey))
697
+ };
698
+ }
699
+ catch (err) {
700
+ if (BaseError.isErrorCode(err, "ResourceNotFoundException")) {
701
+ throw new GeneralError(this.CLASS_NAME, "tableDoesNotExist", {
702
+ table: this._config.tableName
703
+ }, err);
704
+ }
705
+ throw new GeneralError(this.CLASS_NAME, "queryFailed", undefined, err);
706
+ }
707
+ }
708
+ /**
709
+ * Build the condition expression for the query.
710
+ * @param conditions The conditions to build the expression from.
711
+ * @returns The condition expression.
712
+ * @throws GeneralError if the property is not found in the schema.
713
+ * @internal
714
+ */
715
+ buildConditionExpression(conditions) {
716
+ let conditionExpression;
717
+ let attributeNames;
718
+ let attributeValues;
719
+ if (Is.arrayValue(conditions)) {
720
+ const expressions = [];
721
+ for (const c of conditions) {
722
+ const schemaProp = this._entitySchema.properties?.find(p => p.property === c.property);
723
+ if (Is.undefined(schemaProp)) {
724
+ throw new GeneralError(this.CLASS_NAME, "propertyNotFound", {
725
+ property: c.property
726
+ });
727
+ }
728
+ const attributeName = `#${c.property}`;
729
+ const attributeValueName = `:${c.property}`;
730
+ attributeNames ??= {};
731
+ attributeValues ??= {};
732
+ attributeNames[attributeName] = c.property;
733
+ attributeValues[attributeValueName] = c.value;
734
+ expressions.push(`${attributeName} = ${attributeValueName}`);
735
+ }
736
+ conditionExpression = expressions.join(" AND ");
737
+ }
738
+ return { conditionExpression, attributeNames, attributeValues };
739
+ }
657
740
  }
658
741
 
659
742
  export { DynamoDbEntityStorageConnector };
@@ -1,6 +1,6 @@
1
- import { type EntityCondition, type IEntitySchema, type SortDirection } from "@twin.org/entity";
1
+ import { type EntityCondition, type IEntitySchema, SortDirection } from "@twin.org/entity";
2
2
  import type { IEntityStorageConnector } from "@twin.org/entity-storage-models";
3
- import type { IDynamoDbEntityStorageConnectorConfig } from "./models/IDynamoDbEntityStorageConnectorConfig";
3
+ import type { IDynamoDbEntityStorageConnectorConstructorOptions } from "./models/IDynamoDbEntityStorageConnectorConstructorOptions";
4
4
  /**
5
5
  * Class for performing entity storage operations using Dynamo DB.
6
6
  */
@@ -12,15 +12,8 @@ export declare class DynamoDbEntityStorageConnector<T = unknown> implements IEnt
12
12
  /**
13
13
  * Create a new instance of DynamoDbEntityStorageConnector.
14
14
  * @param options The options for the connector.
15
- * @param options.entitySchema The schema for the entity.
16
- * @param options.loggingConnectorType The type of logging connector to use, defaults to no logging.
17
- * @param options.config The configuration for the connector.
18
15
  */
19
- constructor(options: {
20
- entitySchema: string;
21
- loggingConnectorType?: string;
22
- config: IDynamoDbEntityStorageConnectorConfig;
23
- });
16
+ constructor(options: IDynamoDbEntityStorageConnectorConstructorOptions);
24
17
  /**
25
18
  * Bootstrap the component by creating and initializing any resources it needs.
26
19
  * @param nodeLoggingConnectorType The node logging connector type, defaults to "node-logging".
@@ -36,21 +29,33 @@ export declare class DynamoDbEntityStorageConnector<T = unknown> implements IEnt
36
29
  * Get an entity.
37
30
  * @param id The id of the entity to get, or the index value if secondaryIndex is set.
38
31
  * @param secondaryIndex Get the item using a secondary index.
32
+ * @param conditions The optional conditions to match for the entities.
39
33
  * @returns The object if it can be found or undefined.
40
34
  */
41
- get(id: string, secondaryIndex?: keyof T): Promise<T | undefined>;
35
+ get(id: string, secondaryIndex?: keyof T, conditions?: {
36
+ property: keyof T;
37
+ value: unknown;
38
+ }[]): Promise<T | undefined>;
42
39
  /**
43
40
  * Set an entity.
44
41
  * @param entity The entity to set.
42
+ * @param conditions The optional conditions to match for the entities.
45
43
  * @returns The id of the entity.
46
44
  */
47
- set(entity: T): Promise<void>;
45
+ set(entity: T, conditions?: {
46
+ property: keyof T;
47
+ value: unknown;
48
+ }[]): Promise<void>;
48
49
  /**
49
50
  * Remove the entity.
50
51
  * @param id The id of the entity to remove.
52
+ * @param conditions The optional conditions to match for the entities.
51
53
  * @returns Nothing.
52
54
  */
53
- remove(id: string): Promise<void>;
55
+ remove(id: string, conditions?: {
56
+ property: keyof T;
57
+ value: unknown;
58
+ }[]): Promise<void>;
54
59
  /**
55
60
  * Find all the entities which match the conditions.
56
61
  * @param conditions The conditions to match for the entities.
@@ -1,2 +1,3 @@
1
1
  export * from "./dynamoDbEntityStorageConnector";
2
2
  export * from "./models/IDynamoDbEntityStorageConnectorConfig";
3
+ export * from "./models/IDynamoDbEntityStorageConnectorConstructorOptions";
@@ -0,0 +1,18 @@
1
+ import type { IDynamoDbEntityStorageConnectorConfig } from "./IDynamoDbEntityStorageConnectorConfig";
2
+ /**
3
+ * Options for the Dynamo DB Entity Storage Connector constructor.
4
+ */
5
+ export interface IDynamoDbEntityStorageConnectorConstructorOptions {
6
+ /**
7
+ * The schema for the entity
8
+ */
9
+ entitySchema: string;
10
+ /**
11
+ * The type of logging connector to use, defaults to no logging.
12
+ */
13
+ loggingConnectorType?: string;
14
+ /**
15
+ * The configuration for the connector.
16
+ */
17
+ config: IDynamoDbEntityStorageConnectorConfig;
18
+ }
package/docs/changelog.md CHANGED
@@ -1,5 +1,110 @@
1
1
  # @twin.org/entity-storage-connector-dynamodb - Changelog
2
2
 
3
- ## v0.0.1-next.8
3
+ ## 0.0.1 (2025-07-04)
4
+
5
+
6
+ ### Features
7
+
8
+ * add production release automation ([1eb4c8e](https://github.com/twinfoundation/entity-storage/commit/1eb4c8ee3eb099defdfc2d063ae44935276dcae8))
9
+ * release to production ([a309051](https://github.com/twinfoundation/entity-storage/commit/a3090519adebf7943232b4df12e4c6bd5afe7eed))
10
+ * update dependencies ([7ccc0c4](https://github.com/twinfoundation/entity-storage/commit/7ccc0c429125d073dc60b3de6cf101abc8cc6cba))
11
+ * update docs ([5203e62](https://github.com/twinfoundation/entity-storage/commit/5203e621c3ae368f6fefb29ea5146f024f4a1b0d))
12
+ * use shared store mechanism ([#34](https://github.com/twinfoundation/entity-storage/issues/34)) ([68b6b71](https://github.com/twinfoundation/entity-storage/commit/68b6b71e7a96d7d016cd57bfff36775b56bf3f93))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * query params force coercion ([dd6aa87](https://github.com/twinfoundation/entity-storage/commit/dd6aa87efdfb60bab7d6756a86888863c45c51a7))
18
+
19
+
20
+ ### Dependencies
21
+
22
+ * The following workspace dependencies were updated
23
+ * dependencies
24
+ * @twin.org/entity-storage-models bumped from ^0.0.0 to ^0.0.1
25
+ * devDependencies
26
+ * @twin.org/entity-storage-connector-memory bumped from ^0.0.0 to ^0.0.1
27
+
28
+ ## [0.0.1-next.31](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.1-next.30...entity-storage-connector-dynamodb-v0.0.1-next.31) (2025-06-20)
29
+
30
+
31
+ ### Bug Fixes
32
+
33
+ * query params force coercion ([dd6aa87](https://github.com/twinfoundation/entity-storage/commit/dd6aa87efdfb60bab7d6756a86888863c45c51a7))
34
+
35
+
36
+ ### Dependencies
37
+
38
+ * The following workspace dependencies were updated
39
+ * dependencies
40
+ * @twin.org/entity-storage-models bumped from 0.0.1-next.30 to 0.0.1-next.31
41
+ * devDependencies
42
+ * @twin.org/entity-storage-connector-memory bumped from 0.0.1-next.30 to 0.0.1-next.31
43
+
44
+ ## [0.0.1-next.30](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.1-next.29...entity-storage-connector-dynamodb-v0.0.1-next.30) (2025-06-12)
45
+
46
+
47
+ ### Features
48
+
49
+ * update dependencies ([7ccc0c4](https://github.com/twinfoundation/entity-storage/commit/7ccc0c429125d073dc60b3de6cf101abc8cc6cba))
50
+
51
+
52
+ ### Dependencies
53
+
54
+ * The following workspace dependencies were updated
55
+ * dependencies
56
+ * @twin.org/entity-storage-models bumped from 0.0.1-next.29 to 0.0.1-next.30
57
+ * devDependencies
58
+ * @twin.org/entity-storage-connector-memory bumped from 0.0.1-next.29 to 0.0.1-next.30
59
+
60
+ ## [0.0.1-next.29](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.1-next.28...entity-storage-connector-dynamodb-v0.0.1-next.29) (2025-04-17)
61
+
62
+
63
+ ### Features
64
+
65
+ * use shared store mechanism ([#34](https://github.com/twinfoundation/entity-storage/issues/34)) ([68b6b71](https://github.com/twinfoundation/entity-storage/commit/68b6b71e7a96d7d016cd57bfff36775b56bf3f93))
66
+
67
+
68
+ ### Dependencies
69
+
70
+ * The following workspace dependencies were updated
71
+ * dependencies
72
+ * @twin.org/entity-storage-models bumped from 0.0.1-next.28 to 0.0.1-next.29
73
+ * devDependencies
74
+ * @twin.org/entity-storage-connector-memory bumped from 0.0.1-next.28 to 0.0.1-next.29
75
+
76
+ ## [0.0.1-next.28](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.1-next.27...entity-storage-connector-dynamodb-v0.0.1-next.28) (2025-04-09)
77
+
78
+
79
+ ### Features
80
+
81
+ * update docs ([5203e62](https://github.com/twinfoundation/entity-storage/commit/5203e621c3ae368f6fefb29ea5146f024f4a1b0d))
82
+
83
+
84
+ ### Dependencies
85
+
86
+ * The following workspace dependencies were updated
87
+ * dependencies
88
+ * @twin.org/entity-storage-models bumped from 0.0.1-next.27 to 0.0.1-next.28
89
+ * devDependencies
90
+ * @twin.org/entity-storage-connector-memory bumped from 0.0.1-next.27 to 0.0.1-next.28
91
+
92
+ ## [0.0.1-next.27](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.1-next.26...entity-storage-connector-dynamodb-v0.0.1-next.27) (2025-03-28)
93
+
94
+
95
+ ### Miscellaneous Chores
96
+
97
+ * **entity-storage-connector-dynamodb:** Synchronize repo versions
98
+
99
+
100
+ ### Dependencies
101
+
102
+ * The following workspace dependencies were updated
103
+ * dependencies
104
+ * @twin.org/entity-storage-models bumped from 0.0.1-next.26 to 0.0.1-next.27
105
+ * devDependencies
106
+ * @twin.org/entity-storage-connector-memory bumped from 0.0.1-next.26 to 0.0.1-next.27
107
+
108
+ ## v0.0.1-next.26
4
109
 
5
110
  - Initial Release