@lafken/dynamo 0.12.12 → 0.12.13
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/lib/service/query-builder/base/base.js +6 -0
- package/lib/service/query-builder/dynamo-index/dynamo-index.js +5 -3
- package/lib/service/query-builder/find/find.js +0 -6
- package/lib/service/query-builder/find-all/find-all.js +0 -1
- package/lib/service/query-builder/find-one/find-one.js +0 -1
- package/lib/service/repository/repository.types.d.ts +137 -0
- package/lib/service/transaction/transaction.d.ts +26 -0
- package/lib/service/transaction/transaction.js +26 -0
- package/package.json +8 -8
|
@@ -19,6 +19,9 @@ class QueryBuilderBase {
|
|
|
19
19
|
sort && this.validateGlobalKey(Object.keys(sort), isGlobalIndex);
|
|
20
20
|
const partitionFilters = [];
|
|
21
21
|
for (const key in partition) {
|
|
22
|
+
if (partition[key] === undefined) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
22
25
|
partitionFilters.push(this.resolveFilter({
|
|
23
26
|
expressionName: key,
|
|
24
27
|
value: partition[key],
|
|
@@ -50,6 +53,9 @@ class QueryBuilderBase {
|
|
|
50
53
|
}
|
|
51
54
|
}
|
|
52
55
|
for (const key in sortValues) {
|
|
56
|
+
if (sortValues[key] === undefined) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
53
59
|
let filterExpressionKey = 'equal';
|
|
54
60
|
let sortValue = sort[key];
|
|
55
61
|
if (typeof sortValue === 'object') {
|
|
@@ -41,12 +41,14 @@ class DynamoIndexes {
|
|
|
41
41
|
}
|
|
42
42
|
return index;
|
|
43
43
|
}
|
|
44
|
-
const partitionKeys = Object.keys(partition);
|
|
45
|
-
const sortKeys = Object.keys(sort || {});
|
|
44
|
+
const partitionKeys = Object.keys(partition).filter((key) => partition[key] !== undefined);
|
|
45
|
+
const sortKeys = Object.keys(sort || {}).filter((key) => sort?.[key] !== undefined);
|
|
46
46
|
if (partitionKeys.length > 1 || sortKeys.length > 1) {
|
|
47
47
|
return this.getGlobalIndex(new Set(partitionKeys), new Set(sortKeys));
|
|
48
48
|
}
|
|
49
|
-
if (this.partitionKey === partitionKeys[0] &&
|
|
49
|
+
if (this.partitionKey === partitionKeys[0] &&
|
|
50
|
+
this.sortKey !== sortKeys[0] &&
|
|
51
|
+
sortKeys[0] !== undefined) {
|
|
50
52
|
const index = this.getLocalIndex(sortKeys[0]);
|
|
51
53
|
if (index) {
|
|
52
54
|
return index;
|
|
@@ -42,12 +42,6 @@ class FindBuilder extends base_1.QueryBuilderBase {
|
|
|
42
42
|
const command = new client_dynamodb_1.QueryCommand(input);
|
|
43
43
|
const { Items = [], LastEvaluatedKey } = await this.queryOptions.client.send(command);
|
|
44
44
|
const resultData = Items.map((item) => (0, util_dynamodb_1.unmarshall)(item));
|
|
45
|
-
if (input.Limit === 1) {
|
|
46
|
-
return {
|
|
47
|
-
data: [resultData[0]],
|
|
48
|
-
cursor: LastEvaluatedKey ? (0, util_dynamodb_1.unmarshall)(LastEvaluatedKey) : undefined,
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
45
|
const items = data.concat(resultData);
|
|
52
46
|
if (LastEvaluatedKey && (!input.Limit || items.length < input.Limit)) {
|
|
53
47
|
return this.runQuery({
|
|
@@ -16,19 +16,156 @@ import type { ScanBuilder } from '../query-builder/scan/scan';
|
|
|
16
16
|
import type { UpdateBuilder } from '../query-builder/update/update';
|
|
17
17
|
import type { UpsertBuilder } from '../query-builder/upsert/upsert';
|
|
18
18
|
export type RepositoryReturn<E extends ClassResource> = {
|
|
19
|
+
/**
|
|
20
|
+
* Queries a single item using `QueryCommand`.
|
|
21
|
+
*
|
|
22
|
+
* Builds a `KeyConditionExpression` from `keyCondition` and automatically resolves the
|
|
23
|
+
* secondary index (GSI/LSI) to use when applicable. Optionally applies a `FilterExpression`
|
|
24
|
+
* on the results and enforces `Limit: 1`. If `cacheTtl` is provided, the result is stored
|
|
25
|
+
* in the in-memory cache keyed by table name and `inputProps`.
|
|
26
|
+
*
|
|
27
|
+
* @param inputProps - Query conditions: `keyCondition`, `filter`, `projection`, `cursor`, `limit`, `sortDirection`.
|
|
28
|
+
* @param cacheTtl - In-memory cache TTL in seconds. If omitted, no caching is applied.
|
|
29
|
+
* @returns Thenable builder that resolves with the first matching item or `undefined`.
|
|
30
|
+
*/
|
|
19
31
|
findOne(inputProps: QueryOneProps<E>, cacheTtl?: number): FindOneBuilder<E>;
|
|
32
|
+
/**
|
|
33
|
+
* Queries multiple items using `QueryCommand`.
|
|
34
|
+
*
|
|
35
|
+
* Builds a `KeyConditionExpression` from `keyCondition` and automatically resolves the
|
|
36
|
+
* secondary index (GSI/LSI) to use when applicable. Optionally applies a `FilterExpression`,
|
|
37
|
+
* pagination via `ExclusiveStartKey` (cursor), `Limit`, `ProjectionExpression`, and sort
|
|
38
|
+
* direction. Automatically paginates until all results are retrieved. If `cacheTtl` is
|
|
39
|
+
* provided, the result is stored in the in-memory cache.
|
|
40
|
+
*
|
|
41
|
+
* @param inputProps - Query conditions: `keyCondition`, `filter`, `projection`, `cursor`, `limit`, `sortDirection`.
|
|
42
|
+
* @param cacheTtl - In-memory cache TTL in seconds. If omitted, no caching is applied.
|
|
43
|
+
* @returns Thenable builder that resolves with `{ data, cursor }`.
|
|
44
|
+
*/
|
|
20
45
|
findAll(inputProps: QueryProps<E>, cacheTtl?: number): FindAllBuilder<E>;
|
|
46
|
+
/**
|
|
47
|
+
* Scans the entire table using `ScanCommand`.
|
|
48
|
+
*
|
|
49
|
+
* Unlike `findAll`, does not require a `keyCondition` and reads every item in the table.
|
|
50
|
+
* Optionally applies a `FilterExpression`, pagination via `ExclusiveStartKey` (cursor),
|
|
51
|
+
* `Limit`, and `ProjectionExpression`. Automatically paginates until the requested limit is
|
|
52
|
+
* reached. **Avoid on large tables due to high read capacity consumption.**
|
|
53
|
+
*
|
|
54
|
+
* @param inputProps - Optional parameters: `filter`, `projection`, `cursor`, `limit`.
|
|
55
|
+
* @returns Thenable builder that resolves with `{ data, cursor }`.
|
|
56
|
+
*/
|
|
21
57
|
scan(inputProps?: FindProps<E>): ScanBuilder<E>;
|
|
58
|
+
/**
|
|
59
|
+
* Creates or replaces an item using `PutItemCommand`.
|
|
60
|
+
*
|
|
61
|
+
* If an item with the same primary key already exists, it is fully overwritten.
|
|
62
|
+
* Optionally accepts a `ConditionExpression` via `inputProps.condition` to guard the write
|
|
63
|
+
* (e.g. verify an attribute has a specific value before writing).
|
|
64
|
+
*
|
|
65
|
+
* @param item - The full item to write to the table.
|
|
66
|
+
* @param inputProps - Optional parameters: `condition` for `ConditionExpression`.
|
|
67
|
+
* @returns Thenable builder that resolves with the written item.
|
|
68
|
+
*/
|
|
22
69
|
upsert(item: Item<E>, inputProps?: UpsertProps<E>): UpsertBuilder<E>;
|
|
70
|
+
/**
|
|
71
|
+
* Creates a new item using `PutItemCommand`, ensuring it does not already exist.
|
|
72
|
+
*
|
|
73
|
+
* Internally adds an automatic `ConditionExpression` using `attribute_not_exists` on the
|
|
74
|
+
* partition key (and sort key if present), causing the operation to fail if the item already
|
|
75
|
+
* exists. Does not accept additional conditions.
|
|
76
|
+
*
|
|
77
|
+
* @param item - The item to create. Throws a DynamoDB error if the item already exists.
|
|
78
|
+
* @returns Thenable builder that resolves with the created item.
|
|
79
|
+
*/
|
|
23
80
|
create(item: Item<E>): CreateBuilder<E>;
|
|
81
|
+
/**
|
|
82
|
+
* Updates attributes of an existing item using `UpdateItemCommand`.
|
|
83
|
+
*
|
|
84
|
+
* Builds an `UpdateExpression` with `SET` clauses (for `setValues` and `replaceValues`) and
|
|
85
|
+
* `REMOVE` clauses (for `removeValues`). The difference between `setValues` and `replaceValues`
|
|
86
|
+
* is that `setValues` performs a deep merge on nested objects, while `replaceValues` overwrites
|
|
87
|
+
* the attribute entirely. Optionally applies a `ConditionExpression` via `condition` and returns
|
|
88
|
+
* previous or new attributes when `returnValue` is specified.
|
|
89
|
+
*
|
|
90
|
+
* @param inputProps - `keyCondition` (primary key of the item to update), `setValues`,
|
|
91
|
+
* `replaceValues`, `removeValues`, `condition` for `ConditionExpression`, and `returnValue`
|
|
92
|
+
* (`'all_old'` | `'all_new'` | `'updated_old'` | `'updated_new'`).
|
|
93
|
+
* @returns Thenable builder that resolves with the updated item if `returnValue` was specified, or `undefined`.
|
|
94
|
+
*/
|
|
24
95
|
update<R extends ReturnValueOption | undefined = undefined>(inputProps: Omit<UpdateProps<E>, 'returnValue'> & {
|
|
25
96
|
returnValue?: R;
|
|
26
97
|
}): UpdateBuilder<E, R>;
|
|
98
|
+
/**
|
|
99
|
+
* Fetches a single item by its exact primary key using `GetItemCommand`.
|
|
100
|
+
*
|
|
101
|
+
* Unlike `findOne`, uses `GetItemCommand` instead of `QueryCommand`, making it more efficient
|
|
102
|
+
* for exact-key lookups. Supports `ConsistentRead` for strongly consistent reads and
|
|
103
|
+
* `ProjectionExpression` to return only specific attributes. If `cacheTtl` is provided,
|
|
104
|
+
* the result is stored in the in-memory cache.
|
|
105
|
+
*
|
|
106
|
+
* @param key - Primary key of the item (partition key and sort key if applicable).
|
|
107
|
+
* @param options - Options: `consistentRead`, `projection`, `cacheTtl` for in-memory caching.
|
|
108
|
+
* @returns Thenable builder that resolves with the found item or `undefined`.
|
|
109
|
+
*/
|
|
27
110
|
getItem(key: TablePartition<Item<E>>, options?: GetItemOptions<E>): GetItemBuilder<E>;
|
|
111
|
+
/**
|
|
112
|
+
* Deletes an item by its primary key using `DeleteItemCommand`.
|
|
113
|
+
*
|
|
114
|
+
* Does not apply any `ConditionExpression`. If the item does not exist, the operation
|
|
115
|
+
* completes without error.
|
|
116
|
+
*
|
|
117
|
+
* @param key - Primary key of the item to delete (partition key and sort key if applicable).
|
|
118
|
+
* @returns Thenable builder that resolves with `true` on completion.
|
|
119
|
+
*/
|
|
28
120
|
delete(key: TablePartition<Item<E>>): DeleteBuilder<E>;
|
|
121
|
+
/**
|
|
122
|
+
* Fetches multiple items by their primary keys using `BatchGetItemCommand`.
|
|
123
|
+
*
|
|
124
|
+
* Automatically splits keys into batches of up to 100 items (DynamoDB limit) and executes
|
|
125
|
+
* all batches in parallel. Automatically retries `UnprocessedKeys` up to `maxAttempt` times
|
|
126
|
+
* (default 5). Supports `ConsistentRead` and `ProjectionExpression`.
|
|
127
|
+
*
|
|
128
|
+
* @param keys - List of primary keys to retrieve.
|
|
129
|
+
* @param options - Options: `consistentRead`, `projection`, `maxAttempt` (default: 5).
|
|
130
|
+
* @returns Thenable builder that resolves with the array of found items.
|
|
131
|
+
*/
|
|
29
132
|
batchGet(keys: TablePartition<Item<E>>[], options?: BatchGetOptions<E>): BatchGetBuilder<E>;
|
|
133
|
+
/**
|
|
134
|
+
* Creates multiple items using `BatchWriteItemCommand` with `PutRequest`.
|
|
135
|
+
*
|
|
136
|
+
* Automatically splits items into batches of up to 25 (DynamoDB limit) and sends them in
|
|
137
|
+
* parallel. Automatically retries `UnprocessedItems` up to `maxAttempt` times (default 5).
|
|
138
|
+
* Does not apply a `ConditionExpression`; if an item already exists, it is overwritten.
|
|
139
|
+
*
|
|
140
|
+
* @param items - List of items to write to the table.
|
|
141
|
+
* @returns Thenable builder that resolves when all writes are complete.
|
|
142
|
+
*/
|
|
30
143
|
bulkCreate(items: Item<E>[]): BulkCreateBuilder<E>;
|
|
144
|
+
/**
|
|
145
|
+
* Deletes multiple items using `BatchWriteItemCommand` with `DeleteRequest`.
|
|
146
|
+
*
|
|
147
|
+
* Automatically splits keys into batches of up to 25 (DynamoDB limit) and sends them in
|
|
148
|
+
* parallel. Automatically retries `UnprocessedItems` up to `maxAttempt` times (default 5).
|
|
149
|
+
* If a key does not exist, the operation completes without error.
|
|
150
|
+
*
|
|
151
|
+
* @param keys - List of primary keys of the items to delete.
|
|
152
|
+
* @returns Thenable builder that resolves when all deletions are complete.
|
|
153
|
+
*/
|
|
31
154
|
bulkDelete(keys: TablePartition<Item<E>>[]): BulkDeleteBuilder<E>;
|
|
155
|
+
/**
|
|
156
|
+
* Sends an arbitrary command directly to the DynamoDB client.
|
|
157
|
+
*
|
|
158
|
+
* Allows executing SDK commands not covered by the repository methods.
|
|
159
|
+
*
|
|
160
|
+
* @param command - Any DynamoDB SDK command (`@aws-sdk/client-dynamodb`).
|
|
161
|
+
* @returns Promise that resolves with the typed command response.
|
|
162
|
+
*/
|
|
32
163
|
sendRawCommand<T = unknown>(command: Parameters<DynamoDBClient['send']>[0]): Promise<T>;
|
|
164
|
+
/**
|
|
165
|
+
* Clears the in-memory cache shared by `findOne`, `findAll`, and `getItem`.
|
|
166
|
+
*
|
|
167
|
+
* All cached results are invalidated immediately. Useful after write operations that may
|
|
168
|
+
* leave stale data in the cache.
|
|
169
|
+
*/
|
|
33
170
|
clearCache(): void;
|
|
34
171
|
};
|
|
@@ -1,4 +1,30 @@
|
|
|
1
1
|
import { type TransactWriteItem } from '@aws-sdk/client-dynamodb';
|
|
2
2
|
import type { QueryTransactions } from './transaction.types';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the `TransactWriteItem` operation type for a given query builder.
|
|
5
|
+
*
|
|
6
|
+
* Maps builder instances to their corresponding DynamoDB transactional operation key:
|
|
7
|
+
* - `CreateBuilder` / `UpsertBuilder` → `'Put'`
|
|
8
|
+
* - `UpdateBuilder` → `'Update'`
|
|
9
|
+
* - `DeleteBuilder` → `'Delete'`
|
|
10
|
+
*
|
|
11
|
+
* @param builder - A query builder instance representing one transactional operation.
|
|
12
|
+
* @throws If the builder type is not supported within a transaction.
|
|
13
|
+
* @returns The `TransactWriteItem` key (`'Put'` | `'Update'` | `'Delete'`).
|
|
14
|
+
*/
|
|
3
15
|
export declare const getTransactionType: (builder: QueryTransactions) => keyof TransactWriteItem;
|
|
16
|
+
/**
|
|
17
|
+
* Executes multiple write operations atomically using `TransactWriteItemsCommand`.
|
|
18
|
+
*
|
|
19
|
+
* Accepts an array of query builders (`CreateBuilder`, `UpsertBuilder`, `UpdateBuilder`, or
|
|
20
|
+
* `DeleteBuilder`) and groups them into a single transactional request. DynamoDB guarantees
|
|
21
|
+
* all operations either succeed or fail together. Supports up to 100 items per transaction
|
|
22
|
+
* (DynamoDB limit). Does not apply any `ConditionExpression` beyond what each builder already
|
|
23
|
+
* carries; each builder's command is extracted via `getCommand()` and mapped to the appropriate
|
|
24
|
+
* `TransactWriteItem` operation type.
|
|
25
|
+
*
|
|
26
|
+
* @param queryBuilders - Array of write builders to include in the transaction.
|
|
27
|
+
* @throws If any builder type is unsupported or if the transaction is rejected by DynamoDB
|
|
28
|
+
* (e.g. a condition check fails in one of the items).
|
|
29
|
+
*/
|
|
4
30
|
export declare const transaction: (queryBuilders: QueryTransactions[]) => Promise<void>;
|
|
@@ -7,6 +7,18 @@ const create_1 = require("../query-builder/create/create");
|
|
|
7
7
|
const delete_1 = require("../query-builder/delete/delete");
|
|
8
8
|
const update_1 = require("../query-builder/update/update");
|
|
9
9
|
const upsert_1 = require("../query-builder/upsert/upsert");
|
|
10
|
+
/**
|
|
11
|
+
* Resolves the `TransactWriteItem` operation type for a given query builder.
|
|
12
|
+
*
|
|
13
|
+
* Maps builder instances to their corresponding DynamoDB transactional operation key:
|
|
14
|
+
* - `CreateBuilder` / `UpsertBuilder` → `'Put'`
|
|
15
|
+
* - `UpdateBuilder` → `'Update'`
|
|
16
|
+
* - `DeleteBuilder` → `'Delete'`
|
|
17
|
+
*
|
|
18
|
+
* @param builder - A query builder instance representing one transactional operation.
|
|
19
|
+
* @throws If the builder type is not supported within a transaction.
|
|
20
|
+
* @returns The `TransactWriteItem` key (`'Put'` | `'Update'` | `'Delete'`).
|
|
21
|
+
*/
|
|
10
22
|
const getTransactionType = (builder) => {
|
|
11
23
|
let type;
|
|
12
24
|
if (builder instanceof create_1.CreateBuilder || builder instanceof upsert_1.UpsertBuilder) {
|
|
@@ -24,6 +36,20 @@ const getTransactionType = (builder) => {
|
|
|
24
36
|
return type;
|
|
25
37
|
};
|
|
26
38
|
exports.getTransactionType = getTransactionType;
|
|
39
|
+
/**
|
|
40
|
+
* Executes multiple write operations atomically using `TransactWriteItemsCommand`.
|
|
41
|
+
*
|
|
42
|
+
* Accepts an array of query builders (`CreateBuilder`, `UpsertBuilder`, `UpdateBuilder`, or
|
|
43
|
+
* `DeleteBuilder`) and groups them into a single transactional request. DynamoDB guarantees
|
|
44
|
+
* all operations either succeed or fail together. Supports up to 100 items per transaction
|
|
45
|
+
* (DynamoDB limit). Does not apply any `ConditionExpression` beyond what each builder already
|
|
46
|
+
* carries; each builder's command is extracted via `getCommand()` and mapped to the appropriate
|
|
47
|
+
* `TransactWriteItem` operation type.
|
|
48
|
+
*
|
|
49
|
+
* @param queryBuilders - Array of write builders to include in the transaction.
|
|
50
|
+
* @throws If any builder type is unsupported or if the transaction is rejected by DynamoDB
|
|
51
|
+
* (e.g. a condition check fails in one of the items).
|
|
52
|
+
*/
|
|
27
53
|
const transaction = async (queryBuilders) => {
|
|
28
54
|
const transactionCommands = queryBuilders.map((builder) => {
|
|
29
55
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lafken/dynamo",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.13",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Define DynamoDB tables using TypeScript decorators - type-safe, declarative infrastructure with Lafken",
|
|
6
6
|
"keywords": [
|
|
@@ -56,31 +56,31 @@
|
|
|
56
56
|
"lib"
|
|
57
57
|
],
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@aws-sdk/client-dynamodb": "^3.
|
|
59
|
+
"@aws-sdk/client-dynamodb": "^3.1062.0",
|
|
60
60
|
"@aws-sdk/util-dynamodb": "^3.996.2",
|
|
61
61
|
"aws-xray-sdk": "^3.12.0",
|
|
62
62
|
"reflect-metadata": "^0.2.2",
|
|
63
|
-
"@lafken/resolver": "0.12.
|
|
63
|
+
"@lafken/resolver": "0.12.13"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@cdktn/provider-aws": "^24.
|
|
66
|
+
"@cdktn/provider-aws": "^24.4.0",
|
|
67
67
|
"@swc/core": "^1.15.40",
|
|
68
68
|
"@swc/helpers": "^0.5.23",
|
|
69
|
-
"@vitest/runner": "^4.1.
|
|
69
|
+
"@vitest/runner": "^4.1.8",
|
|
70
70
|
"aws-sdk-client-mock": "^4.1.0",
|
|
71
71
|
"cdktn": "^0.23.2",
|
|
72
72
|
"cdktn-vitest": "^1.0.0",
|
|
73
73
|
"constructs": "^10.6.0",
|
|
74
74
|
"typescript": "6.0.3",
|
|
75
75
|
"unplugin-swc": "^1.5.9",
|
|
76
|
-
"vitest": "^4.1.
|
|
77
|
-
"@lafken/common": "0.12.
|
|
76
|
+
"vitest": "^4.1.8",
|
|
77
|
+
"@lafken/common": "0.12.13"
|
|
78
78
|
},
|
|
79
79
|
"peerDependencies": {
|
|
80
80
|
"@cdktn/provider-aws": ">=23.0.0",
|
|
81
81
|
"cdktn": ">=0.22.0",
|
|
82
82
|
"constructs": "^10.4.5",
|
|
83
|
-
"@lafken/common": "0.12.
|
|
83
|
+
"@lafken/common": "0.12.13"
|
|
84
84
|
},
|
|
85
85
|
"engines": {
|
|
86
86
|
"node": ">=20.19"
|