@twin.org/entity-storage-connector-dynamodb 0.0.2-next.1 → 0.0.2-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cjs/index.cjs +74 -65
- package/dist/esm/index.mjs +75 -66
- package/dist/types/dynamoDbEntityStorageConnector.d.ts +6 -6
- package/dist/types/models/IDynamoDbEntityStorageConnectorConfig.d.ts +11 -4
- package/dist/types/models/IDynamoDbEntityStorageConnectorConstructorOptions.d.ts +2 -2
- package/docs/changelog.md +144 -0
- package/docs/reference/classes/DynamoDbEntityStorageConnector.md +7 -11
- package/docs/reference/interfaces/IDynamoDbEntityStorageConnectorConfig.md +22 -6
- package/docs/reference/interfaces/IDynamoDbEntityStorageConnectorConstructorOptions.md +3 -3
- package/locales/en.json +2 -1
- package/package.json +25 -6
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ npm install @twin.org/entity-storage-connector-dynamodb
|
|
|
13
13
|
The tests developed are functional tests and need an instance of DynamoDB up and running. To run DynamoDB locally:
|
|
14
14
|
|
|
15
15
|
```sh
|
|
16
|
-
docker run -p
|
|
16
|
+
docker run -p 8500:8000 --name twin-entity-storage-dynamodb --hostname dynamodb -d amazon/dynamodb-local
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Afterwards you can run the tests as follows:
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -5,7 +5,6 @@ var libDynamodb = require('@aws-sdk/lib-dynamodb');
|
|
|
5
5
|
var utilDynamodb = require('@aws-sdk/util-dynamodb');
|
|
6
6
|
var core = require('@twin.org/core');
|
|
7
7
|
var entity = require('@twin.org/entity');
|
|
8
|
-
var loggingModels = require('@twin.org/logging-models');
|
|
9
8
|
|
|
10
9
|
// Copyright 2024 IOTA Stiftung.
|
|
11
10
|
// SPDX-License-Identifier: Apache-2.0.
|
|
@@ -13,11 +12,15 @@ var loggingModels = require('@twin.org/logging-models');
|
|
|
13
12
|
* Class for performing entity storage operations using Dynamo DB.
|
|
14
13
|
*/
|
|
15
14
|
class DynamoDbEntityStorageConnector {
|
|
15
|
+
/**
|
|
16
|
+
* Runtime name for the class.
|
|
17
|
+
*/
|
|
18
|
+
static CLASS_NAME = "DynamoDbEntityStorageConnector";
|
|
16
19
|
/**
|
|
17
20
|
* Limit the number of entities when finding.
|
|
18
21
|
* @internal
|
|
19
22
|
*/
|
|
20
|
-
static
|
|
23
|
+
static _DEFAULT_LIMIT = 40;
|
|
21
24
|
/**
|
|
22
25
|
* Partition id field name.
|
|
23
26
|
* @internal
|
|
@@ -28,10 +31,6 @@ class DynamoDbEntityStorageConnector {
|
|
|
28
31
|
* @internal
|
|
29
32
|
*/
|
|
30
33
|
static _PARTITION_ID_VALUE = "1";
|
|
31
|
-
/**
|
|
32
|
-
* Runtime name for the class.
|
|
33
|
-
*/
|
|
34
|
-
CLASS_NAME = "DynamoDbEntityStorageConnector";
|
|
35
34
|
/**
|
|
36
35
|
* The schema for the entity.
|
|
37
36
|
* @internal
|
|
@@ -52,13 +51,16 @@ class DynamoDbEntityStorageConnector {
|
|
|
52
51
|
* @param options The options for the connector.
|
|
53
52
|
*/
|
|
54
53
|
constructor(options) {
|
|
55
|
-
core.Guards.object(
|
|
56
|
-
core.Guards.stringValue(
|
|
57
|
-
core.Guards.object(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
core.Guards.object(DynamoDbEntityStorageConnector.CLASS_NAME, "options", options);
|
|
55
|
+
core.Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "options.entitySchema", options.entitySchema);
|
|
56
|
+
core.Guards.object(DynamoDbEntityStorageConnector.CLASS_NAME, "options.config", options.config);
|
|
57
|
+
options.config.authMode ??= "credentials";
|
|
58
|
+
if (options.config.authMode === "credentials") {
|
|
59
|
+
core.Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "options.config.accessKeyId", options.config.accessKeyId);
|
|
60
|
+
core.Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "options.config.secretAccessKey", options.config.secretAccessKey);
|
|
61
|
+
}
|
|
62
|
+
core.Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "options.config.region", options.config.region);
|
|
63
|
+
core.Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "options.config.tableName", options.config.tableName);
|
|
62
64
|
this._entitySchema = entity.EntitySchemaFactory.get(options.entitySchema);
|
|
63
65
|
this._primaryKey = entity.EntitySchemaHelper.getPrimaryKey(this._entitySchema);
|
|
64
66
|
this._config = options.config;
|
|
@@ -68,15 +70,15 @@ class DynamoDbEntityStorageConnector {
|
|
|
68
70
|
}
|
|
69
71
|
/**
|
|
70
72
|
* Bootstrap the component by creating and initializing any resources it needs.
|
|
71
|
-
* @param
|
|
73
|
+
* @param nodeLoggingComponentType The node logging component type.
|
|
72
74
|
* @returns True if the bootstrapping process was successful.
|
|
73
75
|
*/
|
|
74
|
-
async bootstrap(
|
|
75
|
-
const nodeLogging =
|
|
76
|
+
async bootstrap(nodeLoggingComponentType) {
|
|
77
|
+
const nodeLogging = core.ComponentFactory.getIfExists(nodeLoggingComponentType);
|
|
76
78
|
if (!(await this.tableExists(this._config.tableName))) {
|
|
77
79
|
await nodeLogging?.log({
|
|
78
80
|
level: "info",
|
|
79
|
-
source:
|
|
81
|
+
source: DynamoDbEntityStorageConnector.CLASS_NAME,
|
|
80
82
|
ts: Date.now(),
|
|
81
83
|
message: "tableCreating",
|
|
82
84
|
data: {
|
|
@@ -160,7 +162,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
160
162
|
});
|
|
161
163
|
await nodeLogging?.log({
|
|
162
164
|
level: "info",
|
|
163
|
-
source:
|
|
165
|
+
source: DynamoDbEntityStorageConnector.CLASS_NAME,
|
|
164
166
|
ts: Date.now(),
|
|
165
167
|
message: "tableCreated",
|
|
166
168
|
data: {
|
|
@@ -172,7 +174,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
172
174
|
if (core.BaseError.isErrorCode(err, "ResourceInUseException")) {
|
|
173
175
|
await nodeLogging?.log({
|
|
174
176
|
level: "info",
|
|
175
|
-
source:
|
|
177
|
+
source: DynamoDbEntityStorageConnector.CLASS_NAME,
|
|
176
178
|
ts: Date.now(),
|
|
177
179
|
message: "tableExists",
|
|
178
180
|
data: {
|
|
@@ -181,19 +183,16 @@ class DynamoDbEntityStorageConnector {
|
|
|
181
183
|
});
|
|
182
184
|
}
|
|
183
185
|
else {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
});
|
|
196
|
-
}
|
|
186
|
+
await nodeLogging?.log({
|
|
187
|
+
level: "error",
|
|
188
|
+
source: DynamoDbEntityStorageConnector.CLASS_NAME,
|
|
189
|
+
ts: Date.now(),
|
|
190
|
+
message: "tableCreateFailed",
|
|
191
|
+
error: core.BaseError.fromError(err),
|
|
192
|
+
data: {
|
|
193
|
+
tableName: this._config.tableName
|
|
194
|
+
}
|
|
195
|
+
});
|
|
197
196
|
}
|
|
198
197
|
return false;
|
|
199
198
|
}
|
|
@@ -201,7 +200,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
201
200
|
else {
|
|
202
201
|
await nodeLogging?.log({
|
|
203
202
|
level: "info",
|
|
204
|
-
source:
|
|
203
|
+
source: DynamoDbEntityStorageConnector.CLASS_NAME,
|
|
205
204
|
ts: Date.now(),
|
|
206
205
|
message: "tableExists",
|
|
207
206
|
data: {
|
|
@@ -226,7 +225,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
226
225
|
* @returns The object if it can be found or undefined.
|
|
227
226
|
*/
|
|
228
227
|
async get(id, secondaryIndex, conditions) {
|
|
229
|
-
core.Guards.stringValue(
|
|
228
|
+
core.Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "id", id);
|
|
230
229
|
try {
|
|
231
230
|
const docClient = this.createDocClient();
|
|
232
231
|
if (core.Is.empty(secondaryIndex) && core.Is.empty(conditions)) {
|
|
@@ -265,11 +264,11 @@ class DynamoDbEntityStorageConnector {
|
|
|
265
264
|
}
|
|
266
265
|
catch (err) {
|
|
267
266
|
if (core.BaseError.isErrorCode(err, "ResourceNotFoundException")) {
|
|
268
|
-
throw new core.GeneralError(
|
|
269
|
-
|
|
267
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "tableDoesNotExist", {
|
|
268
|
+
tableName: this._config.tableName
|
|
270
269
|
}, err);
|
|
271
270
|
}
|
|
272
|
-
throw new core.GeneralError(
|
|
271
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "getFailed", {
|
|
273
272
|
id
|
|
274
273
|
}, err);
|
|
275
274
|
}
|
|
@@ -281,7 +280,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
281
280
|
* @returns The id of the entity.
|
|
282
281
|
*/
|
|
283
282
|
async set(entity$1, conditions) {
|
|
284
|
-
core.Guards.object(
|
|
283
|
+
core.Guards.object(DynamoDbEntityStorageConnector.CLASS_NAME, "entity", entity$1);
|
|
285
284
|
entity.EntitySchemaHelper.validateEntity(entity$1, this.getSchema());
|
|
286
285
|
const id = entity$1[this._primaryKey.property];
|
|
287
286
|
try {
|
|
@@ -308,11 +307,11 @@ class DynamoDbEntityStorageConnector {
|
|
|
308
307
|
return;
|
|
309
308
|
}
|
|
310
309
|
if (core.BaseError.isErrorCode(err, "ResourceNotFoundException")) {
|
|
311
|
-
throw new core.GeneralError(
|
|
310
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "tableDoesNotExist", {
|
|
312
311
|
tableName: this._config.tableName
|
|
313
312
|
}, err);
|
|
314
313
|
}
|
|
315
|
-
throw new core.GeneralError(
|
|
314
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "setFailed", {
|
|
316
315
|
id
|
|
317
316
|
}, err);
|
|
318
317
|
}
|
|
@@ -324,7 +323,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
324
323
|
* @returns Nothing.
|
|
325
324
|
*/
|
|
326
325
|
async remove(id, conditions) {
|
|
327
|
-
core.Guards.stringValue(
|
|
326
|
+
core.Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "id", id);
|
|
328
327
|
try {
|
|
329
328
|
const docClient = this.createDocClient();
|
|
330
329
|
const { conditionExpression, attributeNames, attributeValues } = this.buildConditionExpression(conditions);
|
|
@@ -345,11 +344,11 @@ class DynamoDbEntityStorageConnector {
|
|
|
345
344
|
return;
|
|
346
345
|
}
|
|
347
346
|
if (core.BaseError.isErrorCode(err, "ResourceNotFoundException")) {
|
|
348
|
-
throw new core.GeneralError(
|
|
349
|
-
|
|
347
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "tableDoesNotExist", {
|
|
348
|
+
tableName: this._config.tableName
|
|
350
349
|
}, err);
|
|
351
350
|
}
|
|
352
|
-
throw new core.GeneralError(
|
|
351
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "removeFailed", {
|
|
353
352
|
id
|
|
354
353
|
}, err);
|
|
355
354
|
}
|
|
@@ -359,13 +358,13 @@ class DynamoDbEntityStorageConnector {
|
|
|
359
358
|
* @param conditions The conditions to match for the entities.
|
|
360
359
|
* @param sortProperties The optional sort order.
|
|
361
360
|
* @param properties The optional properties to return, defaults to all.
|
|
362
|
-
* @param cursor The cursor to request the next
|
|
363
|
-
* @param
|
|
361
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
362
|
+
* @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
|
|
364
363
|
* @returns All the entities for the storage matching the conditions,
|
|
365
364
|
* and a cursor which can be used to request more entities.
|
|
366
365
|
*/
|
|
367
|
-
async query(conditions, sortProperties, properties, cursor,
|
|
368
|
-
return this.internalQuery(conditions, sortProperties, properties, cursor,
|
|
366
|
+
async query(conditions, sortProperties, properties, cursor, limit) {
|
|
367
|
+
return this.internalQuery(conditions, sortProperties, properties, cursor, limit);
|
|
369
368
|
}
|
|
370
369
|
/**
|
|
371
370
|
* Delete the table.
|
|
@@ -421,7 +420,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
421
420
|
const schemaProp = this._entitySchema.properties?.find(p => p.property === condition.property);
|
|
422
421
|
// It's a single value so just create the property comparison for the condition
|
|
423
422
|
const comparison = this.mapComparisonOperator(objectPath, condition, schemaProp?.type, attributeNames, attributeValues);
|
|
424
|
-
const isKey = schemaProp?.isPrimary
|
|
423
|
+
const isKey = schemaProp?.isPrimary ?? (schemaProp?.isSecondary && schemaProp?.property === secondaryIndex);
|
|
425
424
|
return {
|
|
426
425
|
keyCondition: isKey ? comparison : "",
|
|
427
426
|
filterCondition: !isKey ? comparison : ""
|
|
@@ -495,7 +494,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
495
494
|
else if (comparator.comparison === entity.ComparisonOperator.In) {
|
|
496
495
|
return `${propName} IN ${attributeName}`;
|
|
497
496
|
}
|
|
498
|
-
throw new core.GeneralError(
|
|
497
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "comparisonNotSupported", {
|
|
499
498
|
comparison: comparator.comparison
|
|
500
499
|
});
|
|
501
500
|
}
|
|
@@ -532,7 +531,9 @@ class DynamoDbEntityStorageConnector {
|
|
|
532
531
|
else if (operator === entity.LogicalOperator.Or) {
|
|
533
532
|
return "OR";
|
|
534
533
|
}
|
|
535
|
-
throw new core.GeneralError(
|
|
534
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "conditionalNotSupported", {
|
|
535
|
+
operator
|
|
536
|
+
});
|
|
536
537
|
}
|
|
537
538
|
/**
|
|
538
539
|
* Format a value to insert into DB.
|
|
@@ -588,11 +589,19 @@ class DynamoDbEntityStorageConnector {
|
|
|
588
589
|
* @internal
|
|
589
590
|
*/
|
|
590
591
|
createConnectionConfig() {
|
|
592
|
+
if (core.Is.stringValue(this._config.secretAccessKey) &&
|
|
593
|
+
core.Is.stringValue(this._config.accessKeyId) &&
|
|
594
|
+
this._config.authMode === "credentials") {
|
|
595
|
+
return {
|
|
596
|
+
credentials: {
|
|
597
|
+
accessKeyId: this._config.accessKeyId,
|
|
598
|
+
secretAccessKey: this._config.secretAccessKey
|
|
599
|
+
},
|
|
600
|
+
endpoint: this._config.endpoint,
|
|
601
|
+
region: this._config.region
|
|
602
|
+
};
|
|
603
|
+
}
|
|
591
604
|
return {
|
|
592
|
-
credentials: {
|
|
593
|
-
accessKeyId: this._config.accessKeyId,
|
|
594
|
-
secretAccessKey: this._config.secretAccessKey
|
|
595
|
-
},
|
|
596
605
|
endpoint: this._config.endpoint,
|
|
597
606
|
region: this._config.region
|
|
598
607
|
};
|
|
@@ -618,16 +627,16 @@ class DynamoDbEntityStorageConnector {
|
|
|
618
627
|
* @param conditions The conditions to match for the entities.
|
|
619
628
|
* @param sortProperties The optional sort order.
|
|
620
629
|
* @param properties The optional properties to return, defaults to all.
|
|
621
|
-
* @param cursor The cursor to request the next
|
|
622
|
-
* @param
|
|
630
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
631
|
+
* @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
|
|
623
632
|
* @param secondaryIndex The secondary index to use for the query.
|
|
624
633
|
* @returns All the entities for the storage matching the conditions,
|
|
625
634
|
* and a cursor which can be used to request more entities.
|
|
626
635
|
* @internal
|
|
627
636
|
*/
|
|
628
|
-
async internalQuery(conditions, sortProperties, properties, cursor,
|
|
637
|
+
async internalQuery(conditions, sortProperties, properties, cursor, limit, secondaryIndex) {
|
|
629
638
|
try {
|
|
630
|
-
const returnSize =
|
|
639
|
+
const returnSize = limit ?? DynamoDbEntityStorageConnector._DEFAULT_LIMIT;
|
|
631
640
|
let indexName = core.Is.stringValue(secondaryIndex)
|
|
632
641
|
? `${secondaryIndex}Index`
|
|
633
642
|
: undefined;
|
|
@@ -636,7 +645,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
636
645
|
let scanAscending = true;
|
|
637
646
|
if (core.Is.arrayValue(sortProperties)) {
|
|
638
647
|
if (sortProperties.length > 1) {
|
|
639
|
-
throw new core.GeneralError(
|
|
648
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "sortSingle");
|
|
640
649
|
}
|
|
641
650
|
for (const sortProperty of sortProperties) {
|
|
642
651
|
const propertySchema = this._entitySchema.properties?.find(e => e.property === sortProperty.property);
|
|
@@ -644,7 +653,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
644
653
|
(!propertySchema.isPrimary &&
|
|
645
654
|
!propertySchema.isSecondary &&
|
|
646
655
|
core.Is.empty(propertySchema.sortDirection))) {
|
|
647
|
-
throw new core.GeneralError(
|
|
656
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "sortNotIndexed", {
|
|
648
657
|
property: sortProperty.property
|
|
649
658
|
});
|
|
650
659
|
}
|
|
@@ -700,11 +709,11 @@ class DynamoDbEntityStorageConnector {
|
|
|
700
709
|
}
|
|
701
710
|
catch (err) {
|
|
702
711
|
if (core.BaseError.isErrorCode(err, "ResourceNotFoundException")) {
|
|
703
|
-
throw new core.GeneralError(
|
|
704
|
-
|
|
712
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "tableDoesNotExist", {
|
|
713
|
+
tableName: this._config.tableName
|
|
705
714
|
}, err);
|
|
706
715
|
}
|
|
707
|
-
throw new core.GeneralError(
|
|
716
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "queryFailed", undefined, err);
|
|
708
717
|
}
|
|
709
718
|
}
|
|
710
719
|
/**
|
|
@@ -723,7 +732,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
723
732
|
for (const c of conditions) {
|
|
724
733
|
const schemaProp = this._entitySchema.properties?.find(p => p.property === c.property);
|
|
725
734
|
if (core.Is.undefined(schemaProp)) {
|
|
726
|
-
throw new core.GeneralError(
|
|
735
|
+
throw new core.GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "propertyNotFound", {
|
|
727
736
|
property: c.property
|
|
728
737
|
});
|
|
729
738
|
}
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
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, Coerce, ObjectHelper, Converter } from '@twin.org/core';
|
|
4
|
+
import { Guards, Is, ComponentFactory, BaseError, GeneralError, Coerce, ObjectHelper, Converter } from '@twin.org/core';
|
|
5
5
|
import { EntitySchemaFactory, EntitySchemaHelper, ComparisonOperator, LogicalOperator, SortDirection } from '@twin.org/entity';
|
|
6
|
-
import { LoggingConnectorFactory } from '@twin.org/logging-models';
|
|
7
6
|
|
|
8
7
|
// Copyright 2024 IOTA Stiftung.
|
|
9
8
|
// SPDX-License-Identifier: Apache-2.0.
|
|
@@ -11,11 +10,15 @@ import { LoggingConnectorFactory } from '@twin.org/logging-models';
|
|
|
11
10
|
* Class for performing entity storage operations using Dynamo DB.
|
|
12
11
|
*/
|
|
13
12
|
class DynamoDbEntityStorageConnector {
|
|
13
|
+
/**
|
|
14
|
+
* Runtime name for the class.
|
|
15
|
+
*/
|
|
16
|
+
static CLASS_NAME = "DynamoDbEntityStorageConnector";
|
|
14
17
|
/**
|
|
15
18
|
* Limit the number of entities when finding.
|
|
16
19
|
* @internal
|
|
17
20
|
*/
|
|
18
|
-
static
|
|
21
|
+
static _DEFAULT_LIMIT = 40;
|
|
19
22
|
/**
|
|
20
23
|
* Partition id field name.
|
|
21
24
|
* @internal
|
|
@@ -26,10 +29,6 @@ class DynamoDbEntityStorageConnector {
|
|
|
26
29
|
* @internal
|
|
27
30
|
*/
|
|
28
31
|
static _PARTITION_ID_VALUE = "1";
|
|
29
|
-
/**
|
|
30
|
-
* Runtime name for the class.
|
|
31
|
-
*/
|
|
32
|
-
CLASS_NAME = "DynamoDbEntityStorageConnector";
|
|
33
32
|
/**
|
|
34
33
|
* The schema for the entity.
|
|
35
34
|
* @internal
|
|
@@ -50,13 +49,16 @@ class DynamoDbEntityStorageConnector {
|
|
|
50
49
|
* @param options The options for the connector.
|
|
51
50
|
*/
|
|
52
51
|
constructor(options) {
|
|
53
|
-
Guards.object(
|
|
54
|
-
Guards.stringValue(
|
|
55
|
-
Guards.object(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
52
|
+
Guards.object(DynamoDbEntityStorageConnector.CLASS_NAME, "options", options);
|
|
53
|
+
Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "options.entitySchema", options.entitySchema);
|
|
54
|
+
Guards.object(DynamoDbEntityStorageConnector.CLASS_NAME, "options.config", options.config);
|
|
55
|
+
options.config.authMode ??= "credentials";
|
|
56
|
+
if (options.config.authMode === "credentials") {
|
|
57
|
+
Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "options.config.accessKeyId", options.config.accessKeyId);
|
|
58
|
+
Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "options.config.secretAccessKey", options.config.secretAccessKey);
|
|
59
|
+
}
|
|
60
|
+
Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "options.config.region", options.config.region);
|
|
61
|
+
Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "options.config.tableName", options.config.tableName);
|
|
60
62
|
this._entitySchema = EntitySchemaFactory.get(options.entitySchema);
|
|
61
63
|
this._primaryKey = EntitySchemaHelper.getPrimaryKey(this._entitySchema);
|
|
62
64
|
this._config = options.config;
|
|
@@ -66,15 +68,15 @@ class DynamoDbEntityStorageConnector {
|
|
|
66
68
|
}
|
|
67
69
|
/**
|
|
68
70
|
* Bootstrap the component by creating and initializing any resources it needs.
|
|
69
|
-
* @param
|
|
71
|
+
* @param nodeLoggingComponentType The node logging component type.
|
|
70
72
|
* @returns True if the bootstrapping process was successful.
|
|
71
73
|
*/
|
|
72
|
-
async bootstrap(
|
|
73
|
-
const nodeLogging =
|
|
74
|
+
async bootstrap(nodeLoggingComponentType) {
|
|
75
|
+
const nodeLogging = ComponentFactory.getIfExists(nodeLoggingComponentType);
|
|
74
76
|
if (!(await this.tableExists(this._config.tableName))) {
|
|
75
77
|
await nodeLogging?.log({
|
|
76
78
|
level: "info",
|
|
77
|
-
source:
|
|
79
|
+
source: DynamoDbEntityStorageConnector.CLASS_NAME,
|
|
78
80
|
ts: Date.now(),
|
|
79
81
|
message: "tableCreating",
|
|
80
82
|
data: {
|
|
@@ -158,7 +160,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
158
160
|
});
|
|
159
161
|
await nodeLogging?.log({
|
|
160
162
|
level: "info",
|
|
161
|
-
source:
|
|
163
|
+
source: DynamoDbEntityStorageConnector.CLASS_NAME,
|
|
162
164
|
ts: Date.now(),
|
|
163
165
|
message: "tableCreated",
|
|
164
166
|
data: {
|
|
@@ -170,7 +172,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
170
172
|
if (BaseError.isErrorCode(err, "ResourceInUseException")) {
|
|
171
173
|
await nodeLogging?.log({
|
|
172
174
|
level: "info",
|
|
173
|
-
source:
|
|
175
|
+
source: DynamoDbEntityStorageConnector.CLASS_NAME,
|
|
174
176
|
ts: Date.now(),
|
|
175
177
|
message: "tableExists",
|
|
176
178
|
data: {
|
|
@@ -179,19 +181,16 @@ class DynamoDbEntityStorageConnector {
|
|
|
179
181
|
});
|
|
180
182
|
}
|
|
181
183
|
else {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
}
|
|
184
|
+
await nodeLogging?.log({
|
|
185
|
+
level: "error",
|
|
186
|
+
source: DynamoDbEntityStorageConnector.CLASS_NAME,
|
|
187
|
+
ts: Date.now(),
|
|
188
|
+
message: "tableCreateFailed",
|
|
189
|
+
error: BaseError.fromError(err),
|
|
190
|
+
data: {
|
|
191
|
+
tableName: this._config.tableName
|
|
192
|
+
}
|
|
193
|
+
});
|
|
195
194
|
}
|
|
196
195
|
return false;
|
|
197
196
|
}
|
|
@@ -199,7 +198,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
199
198
|
else {
|
|
200
199
|
await nodeLogging?.log({
|
|
201
200
|
level: "info",
|
|
202
|
-
source:
|
|
201
|
+
source: DynamoDbEntityStorageConnector.CLASS_NAME,
|
|
203
202
|
ts: Date.now(),
|
|
204
203
|
message: "tableExists",
|
|
205
204
|
data: {
|
|
@@ -224,7 +223,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
224
223
|
* @returns The object if it can be found or undefined.
|
|
225
224
|
*/
|
|
226
225
|
async get(id, secondaryIndex, conditions) {
|
|
227
|
-
Guards.stringValue(
|
|
226
|
+
Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "id", id);
|
|
228
227
|
try {
|
|
229
228
|
const docClient = this.createDocClient();
|
|
230
229
|
if (Is.empty(secondaryIndex) && Is.empty(conditions)) {
|
|
@@ -263,11 +262,11 @@ class DynamoDbEntityStorageConnector {
|
|
|
263
262
|
}
|
|
264
263
|
catch (err) {
|
|
265
264
|
if (BaseError.isErrorCode(err, "ResourceNotFoundException")) {
|
|
266
|
-
throw new GeneralError(
|
|
267
|
-
|
|
265
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "tableDoesNotExist", {
|
|
266
|
+
tableName: this._config.tableName
|
|
268
267
|
}, err);
|
|
269
268
|
}
|
|
270
|
-
throw new GeneralError(
|
|
269
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "getFailed", {
|
|
271
270
|
id
|
|
272
271
|
}, err);
|
|
273
272
|
}
|
|
@@ -279,7 +278,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
279
278
|
* @returns The id of the entity.
|
|
280
279
|
*/
|
|
281
280
|
async set(entity, conditions) {
|
|
282
|
-
Guards.object(
|
|
281
|
+
Guards.object(DynamoDbEntityStorageConnector.CLASS_NAME, "entity", entity);
|
|
283
282
|
EntitySchemaHelper.validateEntity(entity, this.getSchema());
|
|
284
283
|
const id = entity[this._primaryKey.property];
|
|
285
284
|
try {
|
|
@@ -306,11 +305,11 @@ class DynamoDbEntityStorageConnector {
|
|
|
306
305
|
return;
|
|
307
306
|
}
|
|
308
307
|
if (BaseError.isErrorCode(err, "ResourceNotFoundException")) {
|
|
309
|
-
throw new GeneralError(
|
|
308
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "tableDoesNotExist", {
|
|
310
309
|
tableName: this._config.tableName
|
|
311
310
|
}, err);
|
|
312
311
|
}
|
|
313
|
-
throw new GeneralError(
|
|
312
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "setFailed", {
|
|
314
313
|
id
|
|
315
314
|
}, err);
|
|
316
315
|
}
|
|
@@ -322,7 +321,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
322
321
|
* @returns Nothing.
|
|
323
322
|
*/
|
|
324
323
|
async remove(id, conditions) {
|
|
325
|
-
Guards.stringValue(
|
|
324
|
+
Guards.stringValue(DynamoDbEntityStorageConnector.CLASS_NAME, "id", id);
|
|
326
325
|
try {
|
|
327
326
|
const docClient = this.createDocClient();
|
|
328
327
|
const { conditionExpression, attributeNames, attributeValues } = this.buildConditionExpression(conditions);
|
|
@@ -343,11 +342,11 @@ class DynamoDbEntityStorageConnector {
|
|
|
343
342
|
return;
|
|
344
343
|
}
|
|
345
344
|
if (BaseError.isErrorCode(err, "ResourceNotFoundException")) {
|
|
346
|
-
throw new GeneralError(
|
|
347
|
-
|
|
345
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "tableDoesNotExist", {
|
|
346
|
+
tableName: this._config.tableName
|
|
348
347
|
}, err);
|
|
349
348
|
}
|
|
350
|
-
throw new GeneralError(
|
|
349
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "removeFailed", {
|
|
351
350
|
id
|
|
352
351
|
}, err);
|
|
353
352
|
}
|
|
@@ -357,13 +356,13 @@ class DynamoDbEntityStorageConnector {
|
|
|
357
356
|
* @param conditions The conditions to match for the entities.
|
|
358
357
|
* @param sortProperties The optional sort order.
|
|
359
358
|
* @param properties The optional properties to return, defaults to all.
|
|
360
|
-
* @param cursor The cursor to request the next
|
|
361
|
-
* @param
|
|
359
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
360
|
+
* @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
|
|
362
361
|
* @returns All the entities for the storage matching the conditions,
|
|
363
362
|
* and a cursor which can be used to request more entities.
|
|
364
363
|
*/
|
|
365
|
-
async query(conditions, sortProperties, properties, cursor,
|
|
366
|
-
return this.internalQuery(conditions, sortProperties, properties, cursor,
|
|
364
|
+
async query(conditions, sortProperties, properties, cursor, limit) {
|
|
365
|
+
return this.internalQuery(conditions, sortProperties, properties, cursor, limit);
|
|
367
366
|
}
|
|
368
367
|
/**
|
|
369
368
|
* Delete the table.
|
|
@@ -419,7 +418,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
419
418
|
const schemaProp = this._entitySchema.properties?.find(p => p.property === condition.property);
|
|
420
419
|
// It's a single value so just create the property comparison for the condition
|
|
421
420
|
const comparison = this.mapComparisonOperator(objectPath, condition, schemaProp?.type, attributeNames, attributeValues);
|
|
422
|
-
const isKey = schemaProp?.isPrimary
|
|
421
|
+
const isKey = schemaProp?.isPrimary ?? (schemaProp?.isSecondary && schemaProp?.property === secondaryIndex);
|
|
423
422
|
return {
|
|
424
423
|
keyCondition: isKey ? comparison : "",
|
|
425
424
|
filterCondition: !isKey ? comparison : ""
|
|
@@ -493,7 +492,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
493
492
|
else if (comparator.comparison === ComparisonOperator.In) {
|
|
494
493
|
return `${propName} IN ${attributeName}`;
|
|
495
494
|
}
|
|
496
|
-
throw new GeneralError(
|
|
495
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "comparisonNotSupported", {
|
|
497
496
|
comparison: comparator.comparison
|
|
498
497
|
});
|
|
499
498
|
}
|
|
@@ -530,7 +529,9 @@ class DynamoDbEntityStorageConnector {
|
|
|
530
529
|
else if (operator === LogicalOperator.Or) {
|
|
531
530
|
return "OR";
|
|
532
531
|
}
|
|
533
|
-
throw new GeneralError(
|
|
532
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "conditionalNotSupported", {
|
|
533
|
+
operator
|
|
534
|
+
});
|
|
534
535
|
}
|
|
535
536
|
/**
|
|
536
537
|
* Format a value to insert into DB.
|
|
@@ -586,11 +587,19 @@ class DynamoDbEntityStorageConnector {
|
|
|
586
587
|
* @internal
|
|
587
588
|
*/
|
|
588
589
|
createConnectionConfig() {
|
|
590
|
+
if (Is.stringValue(this._config.secretAccessKey) &&
|
|
591
|
+
Is.stringValue(this._config.accessKeyId) &&
|
|
592
|
+
this._config.authMode === "credentials") {
|
|
593
|
+
return {
|
|
594
|
+
credentials: {
|
|
595
|
+
accessKeyId: this._config.accessKeyId,
|
|
596
|
+
secretAccessKey: this._config.secretAccessKey
|
|
597
|
+
},
|
|
598
|
+
endpoint: this._config.endpoint,
|
|
599
|
+
region: this._config.region
|
|
600
|
+
};
|
|
601
|
+
}
|
|
589
602
|
return {
|
|
590
|
-
credentials: {
|
|
591
|
-
accessKeyId: this._config.accessKeyId,
|
|
592
|
-
secretAccessKey: this._config.secretAccessKey
|
|
593
|
-
},
|
|
594
603
|
endpoint: this._config.endpoint,
|
|
595
604
|
region: this._config.region
|
|
596
605
|
};
|
|
@@ -616,16 +625,16 @@ class DynamoDbEntityStorageConnector {
|
|
|
616
625
|
* @param conditions The conditions to match for the entities.
|
|
617
626
|
* @param sortProperties The optional sort order.
|
|
618
627
|
* @param properties The optional properties to return, defaults to all.
|
|
619
|
-
* @param cursor The cursor to request the next
|
|
620
|
-
* @param
|
|
628
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
629
|
+
* @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
|
|
621
630
|
* @param secondaryIndex The secondary index to use for the query.
|
|
622
631
|
* @returns All the entities for the storage matching the conditions,
|
|
623
632
|
* and a cursor which can be used to request more entities.
|
|
624
633
|
* @internal
|
|
625
634
|
*/
|
|
626
|
-
async internalQuery(conditions, sortProperties, properties, cursor,
|
|
635
|
+
async internalQuery(conditions, sortProperties, properties, cursor, limit, secondaryIndex) {
|
|
627
636
|
try {
|
|
628
|
-
const returnSize =
|
|
637
|
+
const returnSize = limit ?? DynamoDbEntityStorageConnector._DEFAULT_LIMIT;
|
|
629
638
|
let indexName = Is.stringValue(secondaryIndex)
|
|
630
639
|
? `${secondaryIndex}Index`
|
|
631
640
|
: undefined;
|
|
@@ -634,7 +643,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
634
643
|
let scanAscending = true;
|
|
635
644
|
if (Is.arrayValue(sortProperties)) {
|
|
636
645
|
if (sortProperties.length > 1) {
|
|
637
|
-
throw new GeneralError(
|
|
646
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "sortSingle");
|
|
638
647
|
}
|
|
639
648
|
for (const sortProperty of sortProperties) {
|
|
640
649
|
const propertySchema = this._entitySchema.properties?.find(e => e.property === sortProperty.property);
|
|
@@ -642,7 +651,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
642
651
|
(!propertySchema.isPrimary &&
|
|
643
652
|
!propertySchema.isSecondary &&
|
|
644
653
|
Is.empty(propertySchema.sortDirection))) {
|
|
645
|
-
throw new GeneralError(
|
|
654
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "sortNotIndexed", {
|
|
646
655
|
property: sortProperty.property
|
|
647
656
|
});
|
|
648
657
|
}
|
|
@@ -698,11 +707,11 @@ class DynamoDbEntityStorageConnector {
|
|
|
698
707
|
}
|
|
699
708
|
catch (err) {
|
|
700
709
|
if (BaseError.isErrorCode(err, "ResourceNotFoundException")) {
|
|
701
|
-
throw new GeneralError(
|
|
702
|
-
|
|
710
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "tableDoesNotExist", {
|
|
711
|
+
tableName: this._config.tableName
|
|
703
712
|
}, err);
|
|
704
713
|
}
|
|
705
|
-
throw new GeneralError(
|
|
714
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "queryFailed", undefined, err);
|
|
706
715
|
}
|
|
707
716
|
}
|
|
708
717
|
/**
|
|
@@ -721,7 +730,7 @@ class DynamoDbEntityStorageConnector {
|
|
|
721
730
|
for (const c of conditions) {
|
|
722
731
|
const schemaProp = this._entitySchema.properties?.find(p => p.property === c.property);
|
|
723
732
|
if (Is.undefined(schemaProp)) {
|
|
724
|
-
throw new GeneralError(
|
|
733
|
+
throw new GeneralError(DynamoDbEntityStorageConnector.CLASS_NAME, "propertyNotFound", {
|
|
725
734
|
property: c.property
|
|
726
735
|
});
|
|
727
736
|
}
|
|
@@ -8,7 +8,7 @@ export declare class DynamoDbEntityStorageConnector<T = unknown> implements IEnt
|
|
|
8
8
|
/**
|
|
9
9
|
* Runtime name for the class.
|
|
10
10
|
*/
|
|
11
|
-
readonly CLASS_NAME: string;
|
|
11
|
+
static readonly CLASS_NAME: string;
|
|
12
12
|
/**
|
|
13
13
|
* Create a new instance of DynamoDbEntityStorageConnector.
|
|
14
14
|
* @param options The options for the connector.
|
|
@@ -16,10 +16,10 @@ export declare class DynamoDbEntityStorageConnector<T = unknown> implements IEnt
|
|
|
16
16
|
constructor(options: IDynamoDbEntityStorageConnectorConstructorOptions);
|
|
17
17
|
/**
|
|
18
18
|
* Bootstrap the component by creating and initializing any resources it needs.
|
|
19
|
-
* @param
|
|
19
|
+
* @param nodeLoggingComponentType The node logging component type.
|
|
20
20
|
* @returns True if the bootstrapping process was successful.
|
|
21
21
|
*/
|
|
22
|
-
bootstrap(
|
|
22
|
+
bootstrap(nodeLoggingComponentType?: string): Promise<boolean>;
|
|
23
23
|
/**
|
|
24
24
|
* Get the schema for the entities.
|
|
25
25
|
* @returns The schema for the entities.
|
|
@@ -61,15 +61,15 @@ export declare class DynamoDbEntityStorageConnector<T = unknown> implements IEnt
|
|
|
61
61
|
* @param conditions The conditions to match for the entities.
|
|
62
62
|
* @param sortProperties The optional sort order.
|
|
63
63
|
* @param properties The optional properties to return, defaults to all.
|
|
64
|
-
* @param cursor The cursor to request the next
|
|
65
|
-
* @param
|
|
64
|
+
* @param cursor The cursor to request the next chunk of entities.
|
|
65
|
+
* @param limit The suggested number of entities to return in each chunk, in some scenarios can return a different amount.
|
|
66
66
|
* @returns All the entities for the storage matching the conditions,
|
|
67
67
|
* and a cursor which can be used to request more entities.
|
|
68
68
|
*/
|
|
69
69
|
query(conditions?: EntityCondition<T>, sortProperties?: {
|
|
70
70
|
property: keyof T;
|
|
71
71
|
sortDirection: SortDirection;
|
|
72
|
-
}[], properties?: (keyof T)[], cursor?: string,
|
|
72
|
+
}[], properties?: (keyof T)[], cursor?: string, limit?: number): Promise<{
|
|
73
73
|
/**
|
|
74
74
|
* The entities, which can be partial if a limited keys list was provided.
|
|
75
75
|
*/
|
|
@@ -7,19 +7,26 @@ export interface IDynamoDbEntityStorageConnectorConfig {
|
|
|
7
7
|
*/
|
|
8
8
|
region: string;
|
|
9
9
|
/**
|
|
10
|
-
* The
|
|
10
|
+
* The authentication mode.
|
|
11
|
+
* - "credentials": Use access key ID and secret access key.
|
|
12
|
+
* - "pod": Use IAM role attached to the pod (e.g., in EKS).
|
|
13
|
+
* @default credentials
|
|
11
14
|
*/
|
|
12
|
-
|
|
15
|
+
authMode?: "credentials" | "pod";
|
|
16
|
+
/**
|
|
17
|
+
* The AWS access key ID.
|
|
18
|
+
*/
|
|
19
|
+
accessKeyId?: string;
|
|
13
20
|
/**
|
|
14
21
|
* The AWS secret access key.
|
|
15
22
|
*/
|
|
16
|
-
secretAccessKey
|
|
23
|
+
secretAccessKey?: string;
|
|
17
24
|
/**
|
|
18
25
|
* The name of the table for the storage.
|
|
19
26
|
*/
|
|
20
27
|
tableName: string;
|
|
21
28
|
/**
|
|
22
|
-
* AWS endpoint, not usually required but could be used for local DynamoDB instance e.g. http://localhost:
|
|
29
|
+
* AWS endpoint, not usually required but could be used for local DynamoDB instance e.g. http://localhost:8500.
|
|
23
30
|
*/
|
|
24
31
|
endpoint?: string;
|
|
25
32
|
}
|
|
@@ -8,9 +8,9 @@ export interface IDynamoDbEntityStorageConnectorConstructorOptions {
|
|
|
8
8
|
*/
|
|
9
9
|
entitySchema: string;
|
|
10
10
|
/**
|
|
11
|
-
* The type of logging
|
|
11
|
+
* The type of logging component to use, defaults to no logging.
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
loggingComponentType?: string;
|
|
14
14
|
/**
|
|
15
15
|
* The configuration for the connector.
|
|
16
16
|
*/
|
package/docs/changelog.md
CHANGED
|
@@ -1,5 +1,149 @@
|
|
|
1
1
|
# @twin.org/entity-storage-connector-dynamodb - Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.2-next.10](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.2-next.9...entity-storage-connector-dynamodb-v0.0.2-next.10) (2025-10-09)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* add validate-locales ([e66ef0d](https://github.com/twinfoundation/entity-storage/commit/e66ef0de26ca2f82b3fe89bb5c7a15a0978a9644))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Dependencies
|
|
12
|
+
|
|
13
|
+
* The following workspace dependencies were updated
|
|
14
|
+
* dependencies
|
|
15
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.9 to 0.0.2-next.10
|
|
16
|
+
* devDependencies
|
|
17
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.9 to 0.0.2-next.10
|
|
18
|
+
|
|
19
|
+
## [0.0.2-next.9](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.2-next.8...entity-storage-connector-dynamodb-v0.0.2-next.9) (2025-10-02)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### Features
|
|
23
|
+
|
|
24
|
+
* add AWS pod authentication mode ([caaae36](https://github.com/twinfoundation/entity-storage/commit/caaae368ca104cd9994e1af7b6c4c20e603c2021))
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
### Dependencies
|
|
28
|
+
|
|
29
|
+
* The following workspace dependencies were updated
|
|
30
|
+
* dependencies
|
|
31
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.8 to 0.0.2-next.9
|
|
32
|
+
* devDependencies
|
|
33
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.8 to 0.0.2-next.9
|
|
34
|
+
|
|
35
|
+
## [0.0.2-next.8](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.2-next.7...entity-storage-connector-dynamodb-v0.0.2-next.8) (2025-08-29)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
### Features
|
|
39
|
+
|
|
40
|
+
* eslint migration to flat config ([f033b64](https://github.com/twinfoundation/entity-storage/commit/f033b64984c0e6a8129d929c9dd816dcc1b8dab0))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
### Dependencies
|
|
44
|
+
|
|
45
|
+
* The following workspace dependencies were updated
|
|
46
|
+
* dependencies
|
|
47
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.7 to 0.0.2-next.8
|
|
48
|
+
* devDependencies
|
|
49
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.7 to 0.0.2-next.8
|
|
50
|
+
|
|
51
|
+
## [0.0.2-next.7](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.2-next.6...entity-storage-connector-dynamodb-v0.0.2-next.7) (2025-08-20)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
### Features
|
|
55
|
+
|
|
56
|
+
* logging naming consistency ([f99d12d](https://github.com/twinfoundation/entity-storage/commit/f99d12dea04b6d4f2b5632ff5473e9ec7d5f9055))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
### Dependencies
|
|
60
|
+
|
|
61
|
+
* The following workspace dependencies were updated
|
|
62
|
+
* dependencies
|
|
63
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.6 to 0.0.2-next.7
|
|
64
|
+
* devDependencies
|
|
65
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.6 to 0.0.2-next.7
|
|
66
|
+
|
|
67
|
+
## [0.0.2-next.6](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.2-next.5...entity-storage-connector-dynamodb-v0.0.2-next.6) (2025-08-19)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
### Features
|
|
71
|
+
|
|
72
|
+
* update framework core ([b59a380](https://github.com/twinfoundation/entity-storage/commit/b59a380bb7fba2b43610f69074dcdee24a4737da))
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
### Dependencies
|
|
76
|
+
|
|
77
|
+
* The following workspace dependencies were updated
|
|
78
|
+
* dependencies
|
|
79
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.5 to 0.0.2-next.6
|
|
80
|
+
* devDependencies
|
|
81
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.5 to 0.0.2-next.6
|
|
82
|
+
|
|
83
|
+
## [0.0.2-next.5](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.2-next.4...entity-storage-connector-dynamodb-v0.0.2-next.5) (2025-08-11)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
### Miscellaneous Chores
|
|
87
|
+
|
|
88
|
+
* **entity-storage-connector-dynamodb:** Synchronize repo versions
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
### Dependencies
|
|
92
|
+
|
|
93
|
+
* The following workspace dependencies were updated
|
|
94
|
+
* dependencies
|
|
95
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.4 to 0.0.2-next.5
|
|
96
|
+
* devDependencies
|
|
97
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.4 to 0.0.2-next.5
|
|
98
|
+
|
|
99
|
+
## [0.0.2-next.4](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.2-next.3...entity-storage-connector-dynamodb-v0.0.2-next.4) (2025-08-08)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
### Miscellaneous Chores
|
|
103
|
+
|
|
104
|
+
* **entity-storage-connector-dynamodb:** Synchronize repo versions
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
### Dependencies
|
|
108
|
+
|
|
109
|
+
* The following workspace dependencies were updated
|
|
110
|
+
* dependencies
|
|
111
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.3 to 0.0.2-next.4
|
|
112
|
+
* devDependencies
|
|
113
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.3 to 0.0.2-next.4
|
|
114
|
+
|
|
115
|
+
## [0.0.2-next.3](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.2-next.2...entity-storage-connector-dynamodb-v0.0.2-next.3) (2025-07-25)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
### Features
|
|
119
|
+
|
|
120
|
+
* add synchronised to release configs ([e1e749c](https://github.com/twinfoundation/entity-storage/commit/e1e749cf261b58c8c36729686861e29c7d5e068e))
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
### Dependencies
|
|
124
|
+
|
|
125
|
+
* The following workspace dependencies were updated
|
|
126
|
+
* dependencies
|
|
127
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.2 to 0.0.2-next.3
|
|
128
|
+
* devDependencies
|
|
129
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.2 to 0.0.2-next.3
|
|
130
|
+
|
|
131
|
+
## [0.0.2-next.2](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.2-next.1...entity-storage-connector-dynamodb-v0.0.2-next.2) (2025-07-24)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
### Features
|
|
135
|
+
|
|
136
|
+
* synchronised storage ([#44](https://github.com/twinfoundation/entity-storage/issues/44)) ([94e10e2](https://github.com/twinfoundation/entity-storage/commit/94e10e26d1feec801449dc04af7a9757ac7495ff))
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
### Dependencies
|
|
140
|
+
|
|
141
|
+
* The following workspace dependencies were updated
|
|
142
|
+
* dependencies
|
|
143
|
+
* @twin.org/entity-storage-models bumped from 0.0.2-next.1 to 0.0.2-next.2
|
|
144
|
+
* devDependencies
|
|
145
|
+
* @twin.org/entity-storage-connector-memory bumped from 0.0.2-next.1 to 0.0.2-next.2
|
|
146
|
+
|
|
3
147
|
## [0.0.2-next.1](https://github.com/twinfoundation/entity-storage/compare/entity-storage-connector-dynamodb-v0.0.2-next.0...entity-storage-connector-dynamodb-v0.0.2-next.1) (2025-07-17)
|
|
4
148
|
|
|
5
149
|
|
|
@@ -36,29 +36,25 @@ The options for the connector.
|
|
|
36
36
|
|
|
37
37
|
### CLASS\_NAME
|
|
38
38
|
|
|
39
|
-
> `readonly` **CLASS\_NAME**: `string`
|
|
39
|
+
> `readonly` `static` **CLASS\_NAME**: `string`
|
|
40
40
|
|
|
41
41
|
Runtime name for the class.
|
|
42
42
|
|
|
43
|
-
#### Implementation of
|
|
44
|
-
|
|
45
|
-
`IEntityStorageConnector.CLASS_NAME`
|
|
46
|
-
|
|
47
43
|
## Methods
|
|
48
44
|
|
|
49
45
|
### bootstrap()
|
|
50
46
|
|
|
51
|
-
> **bootstrap**(`
|
|
47
|
+
> **bootstrap**(`nodeLoggingComponentType?`): `Promise`\<`boolean`\>
|
|
52
48
|
|
|
53
49
|
Bootstrap the component by creating and initializing any resources it needs.
|
|
54
50
|
|
|
55
51
|
#### Parameters
|
|
56
52
|
|
|
57
|
-
#####
|
|
53
|
+
##### nodeLoggingComponentType?
|
|
58
54
|
|
|
59
55
|
`string`
|
|
60
56
|
|
|
61
|
-
The node logging
|
|
57
|
+
The node logging component type.
|
|
62
58
|
|
|
63
59
|
#### Returns
|
|
64
60
|
|
|
@@ -194,7 +190,7 @@ Nothing.
|
|
|
194
190
|
|
|
195
191
|
### query()
|
|
196
192
|
|
|
197
|
-
> **query**(`conditions?`, `sortProperties?`, `properties?`, `cursor?`, `
|
|
193
|
+
> **query**(`conditions?`, `sortProperties?`, `properties?`, `cursor?`, `limit?`): `Promise`\<\{ `entities`: `Partial`\<`T`\>[]; `cursor?`: `string`; \}\>
|
|
198
194
|
|
|
199
195
|
Find all the entities which match the conditions.
|
|
200
196
|
|
|
@@ -222,9 +218,9 @@ The optional properties to return, defaults to all.
|
|
|
222
218
|
|
|
223
219
|
`string`
|
|
224
220
|
|
|
225
|
-
The cursor to request the next
|
|
221
|
+
The cursor to request the next chunk of entities.
|
|
226
222
|
|
|
227
|
-
#####
|
|
223
|
+
##### limit?
|
|
228
224
|
|
|
229
225
|
`number`
|
|
230
226
|
|
|
@@ -12,17 +12,33 @@ The region for the AWS connection.
|
|
|
12
12
|
|
|
13
13
|
***
|
|
14
14
|
|
|
15
|
-
###
|
|
15
|
+
### authMode?
|
|
16
16
|
|
|
17
|
-
> **
|
|
17
|
+
> `optional` **authMode**: `"credentials"` \| `"pod"`
|
|
18
18
|
|
|
19
|
-
The
|
|
19
|
+
The authentication mode.
|
|
20
|
+
- "credentials": Use access key ID and secret access key.
|
|
21
|
+
- "pod": Use IAM role attached to the pod (e.g., in EKS).
|
|
22
|
+
|
|
23
|
+
#### Default
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
credentials
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
***
|
|
30
|
+
|
|
31
|
+
### accessKeyId?
|
|
32
|
+
|
|
33
|
+
> `optional` **accessKeyId**: `string`
|
|
34
|
+
|
|
35
|
+
The AWS access key ID.
|
|
20
36
|
|
|
21
37
|
***
|
|
22
38
|
|
|
23
|
-
### secretAccessKey
|
|
39
|
+
### secretAccessKey?
|
|
24
40
|
|
|
25
|
-
> **secretAccessKey**: `string`
|
|
41
|
+
> `optional` **secretAccessKey**: `string`
|
|
26
42
|
|
|
27
43
|
The AWS secret access key.
|
|
28
44
|
|
|
@@ -40,4 +56,4 @@ The name of the table for the storage.
|
|
|
40
56
|
|
|
41
57
|
> `optional` **endpoint**: `string`
|
|
42
58
|
|
|
43
|
-
AWS endpoint, not usually required but could be used for local DynamoDB instance e.g. http://localhost:
|
|
59
|
+
AWS endpoint, not usually required but could be used for local DynamoDB instance e.g. http://localhost:8500.
|
|
@@ -12,11 +12,11 @@ The schema for the entity
|
|
|
12
12
|
|
|
13
13
|
***
|
|
14
14
|
|
|
15
|
-
###
|
|
15
|
+
### loggingComponentType?
|
|
16
16
|
|
|
17
|
-
> `optional` **
|
|
17
|
+
> `optional` **loggingComponentType**: `string`
|
|
18
18
|
|
|
19
|
-
The type of logging
|
|
19
|
+
The type of logging component to use, defaults to no logging.
|
|
20
20
|
|
|
21
21
|
***
|
|
22
22
|
|
package/locales/en.json
CHANGED
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"comparisonNotSupported": "Comparison operator \"{comparison}\" is not supported",
|
|
18
18
|
"conditionalNotSupported": "Conditional operator \"{operator}\" is not supported",
|
|
19
19
|
"sortSingle": "You can only sort by a single property",
|
|
20
|
-
"sortNotIndexed": "The property \"{property}\" is not indexed and cannot be used for sorting"
|
|
20
|
+
"sortNotIndexed": "The property \"{property}\" is not indexed and cannot be used for sorting",
|
|
21
|
+
"propertyNotFound": "The property \"{property}\" was not found on the entity schema"
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twin.org/entity-storage-connector-dynamodb",
|
|
3
|
-
"version": "0.0.2-next.
|
|
3
|
+
"version": "0.0.2-next.10",
|
|
4
4
|
"description": "Entity Storage connector implementation using DynamoDb storage",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"node": ">=20.0.0"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@aws-sdk/client-dynamodb": "3.
|
|
18
|
-
"@aws-sdk/lib-dynamodb": "3.
|
|
19
|
-
"@aws-sdk/util-dynamodb": "3.
|
|
17
|
+
"@aws-sdk/client-dynamodb": "3.906",
|
|
18
|
+
"@aws-sdk/lib-dynamodb": "3.906",
|
|
19
|
+
"@aws-sdk/util-dynamodb": "3.906",
|
|
20
20
|
"@twin.org/core": "next",
|
|
21
21
|
"@twin.org/entity": "next",
|
|
22
|
-
"@twin.org/entity-storage-models": "0.0.2-next.
|
|
22
|
+
"@twin.org/entity-storage-models": "0.0.2-next.10",
|
|
23
23
|
"@twin.org/logging-models": "next",
|
|
24
24
|
"@twin.org/nameof": "next"
|
|
25
25
|
},
|
|
@@ -40,5 +40,24 @@
|
|
|
40
40
|
"dist/types",
|
|
41
41
|
"locales",
|
|
42
42
|
"docs"
|
|
43
|
-
]
|
|
43
|
+
],
|
|
44
|
+
"keywords": [
|
|
45
|
+
"twin",
|
|
46
|
+
"trade",
|
|
47
|
+
"iota",
|
|
48
|
+
"framework",
|
|
49
|
+
"blockchain",
|
|
50
|
+
"entity-storage",
|
|
51
|
+
"entity",
|
|
52
|
+
"storage",
|
|
53
|
+
"persistence",
|
|
54
|
+
"database",
|
|
55
|
+
"connector",
|
|
56
|
+
"adapter",
|
|
57
|
+
"integration"
|
|
58
|
+
],
|
|
59
|
+
"bugs": {
|
|
60
|
+
"url": "git+https://github.com/twinfoundation/entity-storage/issues"
|
|
61
|
+
},
|
|
62
|
+
"homepage": "https://twindev.org"
|
|
44
63
|
}
|