dynoquery 0.1.20 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -9
- package/dist/expression-builder.d.ts +41 -0
- package/dist/expression-builder.js +248 -0
- package/dist/index-query.d.ts +5 -3
- package/dist/index-query.js +10 -3
- package/dist/index.d.ts +10 -0
- package/dist/index.js +115 -9
- package/dist/partition.d.ts +25 -6
- package/dist/partition.js +87 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -215,6 +215,33 @@ const userToDelete = db.User('john@example.com').draftDelete('METADATA');
|
|
|
215
215
|
await db.batchWrite([userToDelete]);
|
|
216
216
|
```
|
|
217
217
|
|
|
218
|
+
### 5. Transaction Operations
|
|
219
|
+
|
|
220
|
+
DynoQuery supports `transactWrite` and `transactRead` for atomic operations across multiple items.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
// 1. Transaction Write (All operations succeed or all fail)
|
|
224
|
+
const user1 = db.User('john@example.com', 'METADATA');
|
|
225
|
+
user1.name = 'John Doe';
|
|
226
|
+
|
|
227
|
+
const userToDelete = db.User('olduser@example.com').draftDelete('METADATA');
|
|
228
|
+
|
|
229
|
+
// You can even set conditions for items in a transaction
|
|
230
|
+
const criticalItem = db.User('admin@example.com', 'METADATA');
|
|
231
|
+
criticalItem.lastLogin = new Date().toISOString();
|
|
232
|
+
criticalItem.setCondition(attr('status').equals('ACTIVE'));
|
|
233
|
+
|
|
234
|
+
await db.transactWrite([user1, userToDelete, criticalItem]);
|
|
235
|
+
|
|
236
|
+
// 2. Transaction Read (Read multiple items atomically)
|
|
237
|
+
const userDraft = db.User('john@example.com', 'METADATA');
|
|
238
|
+
const items = await db.transactRead([userDraft]);
|
|
239
|
+
|
|
240
|
+
if (items[0]) {
|
|
241
|
+
console.log('Found user:', items[0].name);
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
218
245
|
## Optional Configuration Parameters
|
|
219
246
|
|
|
220
247
|
| Parameter | Type | Default | Description |
|
|
@@ -259,6 +286,55 @@ if (token) {
|
|
|
259
286
|
}
|
|
260
287
|
```
|
|
261
288
|
|
|
289
|
+
### Expression Builder (Filters & Conditions)
|
|
290
|
+
|
|
291
|
+
Use `ExpressionBuilder` to build complex filter and condition expressions in a type-safe way.
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
import { attr, ExpressionBuilder } from 'dynoquery';
|
|
295
|
+
|
|
296
|
+
// 1. Filtering in queries
|
|
297
|
+
const builder = attr('age').greaterThan(25).and(attr('status').equals('ACTIVE'));
|
|
298
|
+
const activeUsers = await db.User('some-id').getAll({ filterBuilder: builder });
|
|
299
|
+
|
|
300
|
+
// 2. Conditional Updates
|
|
301
|
+
const johnMeta = db.User('john@example.com', 'METADATA');
|
|
302
|
+
const condition = attr('version').equals(1);
|
|
303
|
+
|
|
304
|
+
johnMeta.setCondition(condition);
|
|
305
|
+
johnMeta.name = 'John New Name';
|
|
306
|
+
johnMeta.version = 2;
|
|
307
|
+
|
|
308
|
+
await johnMeta.save(); // Fails if version is not 1
|
|
309
|
+
|
|
310
|
+
// 3. Raw Condition Expressions
|
|
311
|
+
await db.User('john@example.com').update({ status: 'INACTIVE' }, [], {
|
|
312
|
+
ConditionExpression: '#v = :v',
|
|
313
|
+
ExpressionAttributeNames: { '#v': 'version' },
|
|
314
|
+
ExpressionAttributeValues: { ':v': 2 }
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
// Or using Item object
|
|
318
|
+
johnMeta.setCondition(attr('name').exists());
|
|
319
|
+
await johnMeta.save();
|
|
320
|
+
|
|
321
|
+
// 4. Supported Operators
|
|
322
|
+
// - attr('name').equals('val') / notEquals('val')
|
|
323
|
+
// - .lessThan(val) / lessThanOrEqual(val)
|
|
324
|
+
// - .greaterThan(val) / greaterThanOrEqual(val)
|
|
325
|
+
// - .between(start, end)
|
|
326
|
+
// - .in([val1, val2])
|
|
327
|
+
// - logical: .and(otherBuilder), .or(otherBuilder), ExpressionBuilder.not(builder)
|
|
328
|
+
|
|
329
|
+
// 4. Supported Functions
|
|
330
|
+
// - attr('field').exists()
|
|
331
|
+
// - attr('field').notExists()
|
|
332
|
+
// - attr('field').type('S')
|
|
333
|
+
// - attr('field').beginsWith('prefix')
|
|
334
|
+
// - attr('field').contains('value')
|
|
335
|
+
// - attr('field').size().greaterThan(5)
|
|
336
|
+
```
|
|
337
|
+
|
|
262
338
|
## API Reference
|
|
263
339
|
|
|
264
340
|
### DynoQuery
|
|
@@ -270,15 +346,17 @@ if (token) {
|
|
|
270
346
|
- `scan(params)`: Low-level ScanCommand wrapper.
|
|
271
347
|
- `batchWrite(items)`: Batch persists multiple `Item` objects.
|
|
272
348
|
- `batchRead(items)`: Batch fetches multiple `Item` or `IndexQuery` objects.
|
|
349
|
+
- `transactWrite(items)`: Performs atomic write operations (Put/Delete) for up to 100 items.
|
|
350
|
+
- `transactRead(items)`: Performs atomic read operations (Get) for up to 100 items.
|
|
273
351
|
- `[ModelName](id, skValue?)`: Returns a `Partition` instance for the given ID. If `skValue` is provided, returns an `Item` object directly.
|
|
274
352
|
- `findBy[IndexName](id, skValue?)`: Returns an `IndexQuery` instance.
|
|
275
353
|
|
|
276
354
|
### Partition
|
|
277
355
|
- `get(skValue)`: Fetches data for a specific Sort Key value (returns a Promise).
|
|
278
|
-
- `getAll(options?)`: Fetches items in the partition. Options: `{ limit, exclusiveStartKey }`.
|
|
279
|
-
- `create(skValue, data, indices?)`: Creates an item. `
|
|
280
|
-
- `update(skValue, data)`: Partial update of an item.
|
|
281
|
-
- `delete(skValue)`: Deletes an item.
|
|
356
|
+
- `getAll(options?)`: Fetches items in the partition. Options: `{ limit, exclusiveStartKey, filterBuilder, FilterExpression, ExpressionAttributeNames, ExpressionAttributeValues }`.
|
|
357
|
+
- `create(skValue, data, indices?, options?)`: Creates an item. `options`: `{ conditionBuilder, ConditionExpression, ExpressionAttributeNames, ExpressionAttributeValues }`.
|
|
358
|
+
- `update(skValue, data, indices?, options?)`: Partial update of an item. `options`: `{ conditionBuilder, ConditionExpression, ExpressionAttributeNames, ExpressionAttributeValues }`.
|
|
359
|
+
- `delete(skValue, options?)`: Deletes an item. `options`: `{ conditionBuilder, ConditionExpression, ExpressionAttributeNames, ExpressionAttributeValues }`.
|
|
282
360
|
- `draft(skValue, data?)`: Returns an `Item` object initialized with `data` (optional).
|
|
283
361
|
- `draftDelete(skValue)`: Returns an `Item` object marked for deletion (for use with `batchWrite`).
|
|
284
362
|
- `deleteAll()`: Deletes all items in the partition.
|
|
@@ -286,14 +364,16 @@ if (token) {
|
|
|
286
364
|
|
|
287
365
|
### IndexQuery
|
|
288
366
|
- `get(skValue?)`: Get a single item from the index.
|
|
289
|
-
- `getAll(options?)`: Query index. Options: `{ limit, scanIndexForward, exclusiveStartKey, skValue }`.
|
|
367
|
+
- `getAll(options?)`: Query index. Options: `{ limit, scanIndexForward, exclusiveStartKey, skValue, filterBuilder, FilterExpression, ExpressionAttributeNames, ExpressionAttributeValues }`.
|
|
290
368
|
- `getLastEvaluatedKey()`: Returns the pagination token from the last `getAll()`.
|
|
291
369
|
|
|
292
370
|
### Item (returned by Partition.get or draft)
|
|
293
|
-
- `create(data?, indices?)`: Persists the item as a new record with the provided data. Supports GSI indices
|
|
294
|
-
- `update(data, indices?)`: Partial update of the item. Supports GSI indices
|
|
295
|
-
- `save()`: Persists the current state of the item
|
|
296
|
-
- `setIndex(indices)`: Attaches one or more `IndexQuery` objects to the item
|
|
371
|
+
- `create(data?, indices?)`: Persists the item as a new record with the provided data. Supports GSI indices and internal `conditionBuilder`.
|
|
372
|
+
- `update(data, indices?)`: Partial update of the item. Supports GSI indices and internal `conditionBuilder`.
|
|
373
|
+
- `save()`: Persists the current state of the item. Uses indices attached via `setIndex()` and internal `conditionBuilder`.
|
|
374
|
+
- `setIndex(indices)`: Attaches one or more `IndexQuery` objects to the item.
|
|
375
|
+
- `setFilter(builder)`: Sets a filter expression builder for the item.
|
|
376
|
+
- `setCondition(builder)`: Sets a condition for the item using an `ExpressionBuilder`.
|
|
297
377
|
|
|
298
378
|
## License
|
|
299
379
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export type Operand = string | number | ExpressionBuilder;
|
|
2
|
+
export declare class ExpressionBuilder {
|
|
3
|
+
private parts;
|
|
4
|
+
private attributeNames;
|
|
5
|
+
private attributeValues;
|
|
6
|
+
private valueCounter;
|
|
7
|
+
private nameCounter;
|
|
8
|
+
constructor();
|
|
9
|
+
static field(name: string): ExpressionBuilder;
|
|
10
|
+
static value(val: any): ExpressionBuilder;
|
|
11
|
+
where(field: string, operator: string, value: any): ExpressionBuilder;
|
|
12
|
+
equals(value: any): ExpressionBuilder;
|
|
13
|
+
notEquals(value: any): ExpressionBuilder;
|
|
14
|
+
lessThan(value: any): ExpressionBuilder;
|
|
15
|
+
lessThanOrEqual(value: any): ExpressionBuilder;
|
|
16
|
+
greaterThan(value: any): ExpressionBuilder;
|
|
17
|
+
greaterThanOrEqual(value: any): ExpressionBuilder;
|
|
18
|
+
between(start: any, end: any): ExpressionBuilder;
|
|
19
|
+
in(values: any[]): ExpressionBuilder;
|
|
20
|
+
exists(): ExpressionBuilder;
|
|
21
|
+
notExists(): ExpressionBuilder;
|
|
22
|
+
type(type: string): ExpressionBuilder;
|
|
23
|
+
attributeExists(path: string): ExpressionBuilder;
|
|
24
|
+
attributeNotExists(path: string): ExpressionBuilder;
|
|
25
|
+
attributeType(path: string, type: string): ExpressionBuilder;
|
|
26
|
+
beginsWith(pathOrSubstr: string, substr?: string): ExpressionBuilder;
|
|
27
|
+
contains(pathOrValue: string, value?: any): ExpressionBuilder;
|
|
28
|
+
size(path?: string): ExpressionBuilder;
|
|
29
|
+
and(other: ExpressionBuilder): ExpressionBuilder;
|
|
30
|
+
or(other: ExpressionBuilder): ExpressionBuilder;
|
|
31
|
+
static not(condition: ExpressionBuilder): ExpressionBuilder;
|
|
32
|
+
build(attributeNames?: Record<string, string>, attributeValues?: Record<string, any>, counters?: {
|
|
33
|
+
name: number;
|
|
34
|
+
value: number;
|
|
35
|
+
}): {
|
|
36
|
+
expression: string;
|
|
37
|
+
attributeNames: Record<string, string>;
|
|
38
|
+
attributeValues: Record<string, any>;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export declare function attr(name: string): ExpressionBuilder;
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExpressionBuilder = void 0;
|
|
4
|
+
exports.attr = attr;
|
|
5
|
+
class ExpressionBuilder {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.parts = [];
|
|
8
|
+
this.attributeNames = {};
|
|
9
|
+
this.attributeValues = {};
|
|
10
|
+
this.valueCounter = 0;
|
|
11
|
+
this.nameCounter = 0;
|
|
12
|
+
}
|
|
13
|
+
static field(name) {
|
|
14
|
+
const builder = new ExpressionBuilder();
|
|
15
|
+
builder.parts.push({ type: 'field', name });
|
|
16
|
+
return builder;
|
|
17
|
+
}
|
|
18
|
+
static value(val) {
|
|
19
|
+
const builder = new ExpressionBuilder();
|
|
20
|
+
builder.parts.push({ type: 'value', value: val });
|
|
21
|
+
return builder;
|
|
22
|
+
}
|
|
23
|
+
where(field, operator, value) {
|
|
24
|
+
this.parts.push({ type: 'condition', field, operator, value });
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
equals(value) {
|
|
28
|
+
this.parts.push({ type: 'operator', operator: '=', value });
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
notEquals(value) {
|
|
32
|
+
this.parts.push({ type: 'operator', operator: '<>', value });
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
lessThan(value) {
|
|
36
|
+
this.parts.push({ type: 'operator', operator: '<', value });
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
lessThanOrEqual(value) {
|
|
40
|
+
this.parts.push({ type: 'operator', operator: '<=', value });
|
|
41
|
+
return this;
|
|
42
|
+
}
|
|
43
|
+
greaterThan(value) {
|
|
44
|
+
this.parts.push({ type: 'operator', operator: '>', value });
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
47
|
+
greaterThanOrEqual(value) {
|
|
48
|
+
this.parts.push({ type: 'operator', operator: '>=', value });
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
between(start, end) {
|
|
52
|
+
this.parts.push({ type: 'between', start, end });
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
in(values) {
|
|
56
|
+
this.parts.push({ type: 'in', values });
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
exists() {
|
|
60
|
+
const last = this.parts.pop();
|
|
61
|
+
if (last && last.type === 'field') {
|
|
62
|
+
this.parts.push({ type: 'function', name: 'attribute_exists', args: [last] });
|
|
63
|
+
}
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
notExists() {
|
|
67
|
+
const last = this.parts.pop();
|
|
68
|
+
if (last && last.type === 'field') {
|
|
69
|
+
this.parts.push({ type: 'function', name: 'attribute_not_exists', args: [last] });
|
|
70
|
+
}
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
type(type) {
|
|
74
|
+
const last = this.parts.pop();
|
|
75
|
+
if (last && last.type === 'field') {
|
|
76
|
+
this.parts.push({ type: 'function', name: 'attribute_type', args: [last, { type: 'value', value: type }] });
|
|
77
|
+
}
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
attributeExists(path) {
|
|
81
|
+
this.parts.push({ type: 'function', name: 'attribute_exists', args: [{ type: 'field', name: path }] });
|
|
82
|
+
return this;
|
|
83
|
+
}
|
|
84
|
+
attributeNotExists(path) {
|
|
85
|
+
this.parts.push({ type: 'function', name: 'attribute_not_exists', args: [{ type: 'field', name: path }] });
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
attributeType(path, type) {
|
|
89
|
+
this.parts.push({ type: 'function', name: 'attribute_type', args: [{ type: 'field', name: path }, { type: 'value', value: type }] });
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
92
|
+
beginsWith(pathOrSubstr, substr) {
|
|
93
|
+
if (substr !== undefined) {
|
|
94
|
+
// Legacy static-like call: builder.beginsWith('field', 'prefix')
|
|
95
|
+
this.parts.push({ type: 'function', name: 'begins_with', args: [{ type: 'field', name: pathOrSubstr }, { type: 'value', value: substr }] });
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
// Fluent call: attr('field').beginsWith('prefix')
|
|
99
|
+
const last = this.parts.pop();
|
|
100
|
+
if (last && last.type === 'field') {
|
|
101
|
+
this.parts.push({ type: 'function', name: 'begins_with', args: [last, { type: 'value', value: pathOrSubstr }] });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return this;
|
|
105
|
+
}
|
|
106
|
+
contains(pathOrValue, value) {
|
|
107
|
+
if (value !== undefined) {
|
|
108
|
+
// Legacy static-like call: builder.contains('field', 'value')
|
|
109
|
+
this.parts.push({ type: 'function', name: 'contains', args: [{ type: 'field', name: pathOrValue }, { type: 'value', value }] });
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Fluent call: attr('field').contains('value')
|
|
113
|
+
const last = this.parts.pop();
|
|
114
|
+
if (last && last.type === 'field') {
|
|
115
|
+
this.parts.push({ type: 'function', name: 'contains', args: [last, { type: 'value', value: pathOrValue }] });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return this;
|
|
119
|
+
}
|
|
120
|
+
size(path) {
|
|
121
|
+
if (path) {
|
|
122
|
+
// Legacy: builder.size('field')
|
|
123
|
+
const builder = new ExpressionBuilder();
|
|
124
|
+
builder.parts.push({ type: 'function', name: 'size', args: [{ type: 'field', name: path }] });
|
|
125
|
+
return builder;
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// Fluent: attr('field').size()
|
|
129
|
+
const last = this.parts.pop();
|
|
130
|
+
if (last && last.type === 'field') {
|
|
131
|
+
this.parts.push({ type: 'function', name: 'size', args: [last] });
|
|
132
|
+
}
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
and(other) {
|
|
137
|
+
const newBuilder = new ExpressionBuilder();
|
|
138
|
+
newBuilder.parts.push({ type: 'group', builder: this });
|
|
139
|
+
newBuilder.parts.push({ type: 'logical', operator: 'AND' });
|
|
140
|
+
newBuilder.parts.push({ type: 'group', builder: other });
|
|
141
|
+
return newBuilder;
|
|
142
|
+
}
|
|
143
|
+
or(other) {
|
|
144
|
+
const newBuilder = new ExpressionBuilder();
|
|
145
|
+
newBuilder.parts.push({ type: 'group', builder: this });
|
|
146
|
+
newBuilder.parts.push({ type: 'logical', operator: 'OR' });
|
|
147
|
+
newBuilder.parts.push({ type: 'group', builder: other });
|
|
148
|
+
return newBuilder;
|
|
149
|
+
}
|
|
150
|
+
static not(condition) {
|
|
151
|
+
const builder = new ExpressionBuilder();
|
|
152
|
+
builder.parts.push({ type: 'logical', operator: 'NOT' });
|
|
153
|
+
builder.parts.push({ type: 'group', builder: condition });
|
|
154
|
+
return builder;
|
|
155
|
+
}
|
|
156
|
+
build(attributeNames = {}, attributeValues = {}, counters = { name: 0, value: 0 }) {
|
|
157
|
+
let expressionParts = [];
|
|
158
|
+
for (const part of this.parts) {
|
|
159
|
+
switch (part.type) {
|
|
160
|
+
case 'field': {
|
|
161
|
+
const namePlaceholder = `#n${counters.name++}`;
|
|
162
|
+
attributeNames[namePlaceholder] = part.name;
|
|
163
|
+
expressionParts.push(namePlaceholder);
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
case 'value': {
|
|
167
|
+
const valuePlaceholder = `:v${counters.value++}`;
|
|
168
|
+
attributeValues[valuePlaceholder] = part.value;
|
|
169
|
+
expressionParts.push(valuePlaceholder);
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
case 'condition': {
|
|
173
|
+
const namePlaceholder = `#n${counters.name++}`;
|
|
174
|
+
attributeNames[namePlaceholder] = part.field;
|
|
175
|
+
const valuePlaceholder = `:v${counters.value++}`;
|
|
176
|
+
attributeValues[valuePlaceholder] = part.value;
|
|
177
|
+
expressionParts.push(`${namePlaceholder} ${part.operator} ${valuePlaceholder}`);
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
case 'operator': {
|
|
181
|
+
const valuePlaceholder = `:v${counters.value++}`;
|
|
182
|
+
attributeValues[valuePlaceholder] = part.value;
|
|
183
|
+
const last = expressionParts.pop();
|
|
184
|
+
expressionParts.push(`${last} ${part.operator} ${valuePlaceholder}`);
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
case 'between': {
|
|
188
|
+
const startPlaceholder = `:v${counters.value++}`;
|
|
189
|
+
attributeValues[startPlaceholder] = part.start;
|
|
190
|
+
const endPlaceholder = `:v${counters.value++}`;
|
|
191
|
+
attributeValues[endPlaceholder] = part.end;
|
|
192
|
+
const last = expressionParts.pop();
|
|
193
|
+
expressionParts.push(`${last} BETWEEN ${startPlaceholder} AND ${endPlaceholder}`);
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
case 'in': {
|
|
197
|
+
const placeholders = part.values.map((v) => {
|
|
198
|
+
const vp = `:v${counters.value++}`;
|
|
199
|
+
attributeValues[vp] = v;
|
|
200
|
+
return vp;
|
|
201
|
+
});
|
|
202
|
+
const last = expressionParts.pop();
|
|
203
|
+
expressionParts.push(`${last} IN (${placeholders.join(', ')})`);
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
case 'function': {
|
|
207
|
+
const args = part.args.map((arg) => {
|
|
208
|
+
if (arg.type === 'field') {
|
|
209
|
+
const np = `#n${counters.name++}`;
|
|
210
|
+
attributeNames[np] = arg.name;
|
|
211
|
+
return np;
|
|
212
|
+
}
|
|
213
|
+
else if (arg.type === 'value') {
|
|
214
|
+
const vp = `:v${counters.value++}`;
|
|
215
|
+
attributeValues[vp] = arg.value;
|
|
216
|
+
return vp;
|
|
217
|
+
}
|
|
218
|
+
else if (arg instanceof ExpressionBuilder) {
|
|
219
|
+
const sub = arg.build(attributeNames, attributeValues, counters);
|
|
220
|
+
return sub.expression;
|
|
221
|
+
}
|
|
222
|
+
return arg;
|
|
223
|
+
});
|
|
224
|
+
expressionParts.push(`${part.name}(${args.join(', ')})`);
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
case 'logical': {
|
|
228
|
+
expressionParts.push(part.operator);
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
case 'group': {
|
|
232
|
+
const sub = part.builder.build(attributeNames, attributeValues, counters);
|
|
233
|
+
expressionParts.push(`(${sub.expression})`);
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
expression: expressionParts.join(' '),
|
|
240
|
+
attributeNames,
|
|
241
|
+
attributeValues
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
exports.ExpressionBuilder = ExpressionBuilder;
|
|
246
|
+
function attr(name) {
|
|
247
|
+
return ExpressionBuilder.field(name);
|
|
248
|
+
}
|
package/dist/index-query.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DynoQuery } from "./index";
|
|
2
|
+
import { ExpressionBuilder } from "./expression-builder";
|
|
2
3
|
export interface IndexQueryConfig {
|
|
3
4
|
tableName?: string;
|
|
4
5
|
indexName: string;
|
|
@@ -23,9 +24,10 @@ export declare class IndexQuery {
|
|
|
23
24
|
scanIndexForward?: boolean;
|
|
24
25
|
exclusiveStartKey?: any;
|
|
25
26
|
skValue?: string;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
filterBuilder?: ExpressionBuilder;
|
|
28
|
+
FilterExpression?: string;
|
|
29
|
+
ExpressionAttributeNames?: Record<string, string>;
|
|
30
|
+
ExpressionAttributeValues?: Record<string, any>;
|
|
29
31
|
}): Promise<T[]>;
|
|
30
32
|
get<T = any>(skValue?: string): Promise<T | null>;
|
|
31
33
|
getPkValue(): string;
|
package/dist/index-query.js
CHANGED
|
@@ -34,18 +34,25 @@ class IndexQuery {
|
|
|
34
34
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
35
|
const finalSkValue = (options === null || options === void 0 ? void 0 : options.skValue) || this.skValue;
|
|
36
36
|
let keyCondition = "#pk = :pk";
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
let expressionAttributeNames = Object.assign({ "#pk": this.pkName }, options === null || options === void 0 ? void 0 : options.ExpressionAttributeNames);
|
|
38
|
+
let expressionAttributeValues = Object.assign({ ":pk": this.pkValue }, options === null || options === void 0 ? void 0 : options.ExpressionAttributeValues);
|
|
39
39
|
if (finalSkValue) {
|
|
40
40
|
keyCondition += " AND begins_with(#sk, :sk)";
|
|
41
41
|
expressionAttributeNames["#sk"] = this.skName;
|
|
42
42
|
expressionAttributeValues[":sk"] = finalSkValue;
|
|
43
43
|
}
|
|
44
|
+
let filterExpression = options === null || options === void 0 ? void 0 : options.FilterExpression;
|
|
45
|
+
if (options === null || options === void 0 ? void 0 : options.filterBuilder) {
|
|
46
|
+
const { expression, attributeNames, attributeValues } = options.filterBuilder.build();
|
|
47
|
+
filterExpression = expression;
|
|
48
|
+
expressionAttributeNames = Object.assign(Object.assign({}, expressionAttributeNames), attributeNames);
|
|
49
|
+
expressionAttributeValues = Object.assign(Object.assign({}, expressionAttributeValues), attributeValues);
|
|
50
|
+
}
|
|
44
51
|
const response = yield this.db.query({
|
|
45
52
|
TableName: this.tableName,
|
|
46
53
|
IndexName: this.indexName,
|
|
47
54
|
KeyConditionExpression: keyCondition,
|
|
48
|
-
FilterExpression:
|
|
55
|
+
FilterExpression: filterExpression,
|
|
49
56
|
ExpressionAttributeNames: expressionAttributeNames,
|
|
50
57
|
ExpressionAttributeValues: expressionAttributeValues,
|
|
51
58
|
Limit: options === null || options === void 0 ? void 0 : options.limit,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { PutCommandInput, GetCommandInput, UpdateCommandInput, DeleteCommandInput, QueryCommandInput, ScanCommandInput } from "@aws-sdk/lib-dynamodb";
|
|
2
2
|
import { Item } from "./partition";
|
|
3
3
|
import { IndexQuery } from "./index-query";
|
|
4
|
+
import { ExpressionBuilder, attr } from "./expression-builder";
|
|
5
|
+
export { ExpressionBuilder, attr };
|
|
4
6
|
export interface DynoQueryConfig {
|
|
5
7
|
tableName?: string;
|
|
6
8
|
pkName?: string;
|
|
@@ -65,6 +67,14 @@ export declare class DynoQuery {
|
|
|
65
67
|
* Batch get items from the table.
|
|
66
68
|
*/
|
|
67
69
|
batchRead(items: (Item | IndexQuery)[]): Promise<any[]>;
|
|
70
|
+
/**
|
|
71
|
+
* Transact write items to the table.
|
|
72
|
+
*/
|
|
73
|
+
transactWrite(items: Item[]): Promise<Item[]>;
|
|
74
|
+
/**
|
|
75
|
+
* Transact get items from the table.
|
|
76
|
+
*/
|
|
77
|
+
transactRead(items: (Item | IndexQuery)[]): Promise<any[]>;
|
|
68
78
|
/**
|
|
69
79
|
* Maps a raw DynamoDB item to a Model Item if it matches a registered model.
|
|
70
80
|
*/
|
package/dist/index.js
CHANGED
|
@@ -34,11 +34,14 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
34
34
|
return t;
|
|
35
35
|
};
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
-
exports.Item = exports.DynoQuery = void 0;
|
|
37
|
+
exports.Item = exports.DynoQuery = exports.attr = exports.ExpressionBuilder = void 0;
|
|
38
38
|
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
39
39
|
const lib_dynamodb_1 = require("@aws-sdk/lib-dynamodb");
|
|
40
40
|
const partition_1 = require("./partition");
|
|
41
41
|
const index_query_1 = require("./index-query");
|
|
42
|
+
const expression_builder_1 = require("./expression-builder");
|
|
43
|
+
Object.defineProperty(exports, "ExpressionBuilder", { enumerable: true, get: function () { return expression_builder_1.ExpressionBuilder; } });
|
|
44
|
+
Object.defineProperty(exports, "attr", { enumerable: true, get: function () { return expression_builder_1.attr; } });
|
|
42
45
|
class DynoQuery {
|
|
43
46
|
constructor(config = {}) {
|
|
44
47
|
this.registeredModels = {};
|
|
@@ -178,14 +181,7 @@ class DynoQuery {
|
|
|
178
181
|
});
|
|
179
182
|
}
|
|
180
183
|
else {
|
|
181
|
-
const dataToSave =
|
|
182
|
-
for (const key in item) {
|
|
183
|
-
if (Object.prototype.hasOwnProperty.call(item, key) &&
|
|
184
|
-
!["_indices", "_partition", "_skValue", "_toBeDeleted"].includes(key) &&
|
|
185
|
-
typeof item[key] !== "function") {
|
|
186
|
-
dataToSave[key] = item[key];
|
|
187
|
-
}
|
|
188
|
-
}
|
|
184
|
+
const dataToSave = item.getData();
|
|
189
185
|
// Ensure PK and SK are in the data
|
|
190
186
|
dataToSave[this.pkName] = partition.getPkValue();
|
|
191
187
|
dataToSave[this.skName] = skValue;
|
|
@@ -271,6 +267,116 @@ class DynoQuery {
|
|
|
271
267
|
return allItems;
|
|
272
268
|
});
|
|
273
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Transact write items to the table.
|
|
272
|
+
*/
|
|
273
|
+
transactWrite(items) {
|
|
274
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
275
|
+
// Chunk items into 100
|
|
276
|
+
for (let i = 0; i < items.length; i += 100) {
|
|
277
|
+
const chunk = items.slice(i, i + 100);
|
|
278
|
+
const transactItems = chunk.map((item) => {
|
|
279
|
+
const partition = item.getPartition();
|
|
280
|
+
const tableName = partition.getTableName();
|
|
281
|
+
const skValue = item.getSkValue();
|
|
282
|
+
const pkValue = partition.getPkValue();
|
|
283
|
+
const conditionBuilder = item.getConditionBuilder();
|
|
284
|
+
if (item.toBeDeleted()) {
|
|
285
|
+
const deleteItem = {
|
|
286
|
+
Key: {
|
|
287
|
+
[this.pkName]: pkValue,
|
|
288
|
+
[this.skName]: skValue,
|
|
289
|
+
},
|
|
290
|
+
TableName: tableName,
|
|
291
|
+
};
|
|
292
|
+
if (conditionBuilder) {
|
|
293
|
+
const { expression, attributeNames, attributeValues } = conditionBuilder.build();
|
|
294
|
+
deleteItem.ConditionExpression = expression;
|
|
295
|
+
deleteItem.ExpressionAttributeNames = attributeNames;
|
|
296
|
+
deleteItem.ExpressionAttributeValues = attributeValues;
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
Delete: deleteItem,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
const dataToSave = item.getData();
|
|
304
|
+
// Ensure PK and SK are in the data
|
|
305
|
+
dataToSave[this.pkName] = pkValue;
|
|
306
|
+
dataToSave[this.skName] = skValue;
|
|
307
|
+
const putItem = {
|
|
308
|
+
Item: dataToSave,
|
|
309
|
+
TableName: tableName,
|
|
310
|
+
};
|
|
311
|
+
if (conditionBuilder) {
|
|
312
|
+
const { expression, attributeNames, attributeValues } = conditionBuilder.build();
|
|
313
|
+
putItem.ConditionExpression = expression;
|
|
314
|
+
putItem.ExpressionAttributeNames = attributeNames;
|
|
315
|
+
putItem.ExpressionAttributeValues = attributeValues;
|
|
316
|
+
}
|
|
317
|
+
return {
|
|
318
|
+
Put: putItem,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
yield this.docClient.send(new lib_dynamodb_1.TransactWriteCommand({
|
|
323
|
+
TransactItems: transactItems,
|
|
324
|
+
}));
|
|
325
|
+
}
|
|
326
|
+
return items;
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Transact get items from the table.
|
|
331
|
+
*/
|
|
332
|
+
transactRead(items) {
|
|
333
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
334
|
+
const allItems = [];
|
|
335
|
+
// Chunk items into 100
|
|
336
|
+
for (let i = 0; i < items.length; i += 100) {
|
|
337
|
+
const chunk = items.slice(i, i + 100);
|
|
338
|
+
const transactItems = chunk.map((item) => {
|
|
339
|
+
let tableName;
|
|
340
|
+
let pkValue;
|
|
341
|
+
let skValue;
|
|
342
|
+
if (item instanceof index_query_1.IndexQuery) {
|
|
343
|
+
tableName = item.tableName;
|
|
344
|
+
pkValue = item.getPkValue();
|
|
345
|
+
skValue = item.getSkValue() || "";
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
const partition = item.getPartition();
|
|
349
|
+
tableName = partition.getTableName();
|
|
350
|
+
pkValue = partition.getPkValue();
|
|
351
|
+
skValue = item.getSkValue();
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
Get: {
|
|
355
|
+
TableName: tableName,
|
|
356
|
+
Key: {
|
|
357
|
+
[this.pkName]: pkValue,
|
|
358
|
+
[this.skName]: skValue,
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
};
|
|
362
|
+
});
|
|
363
|
+
const response = yield this.docClient.send(new lib_dynamodb_1.TransactGetCommand({
|
|
364
|
+
TransactItems: transactItems,
|
|
365
|
+
}));
|
|
366
|
+
if (response.Responses) {
|
|
367
|
+
response.Responses.forEach((res) => {
|
|
368
|
+
if (res.Item) {
|
|
369
|
+
allItems.push(this.mapItemToModelItem(res.Item));
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
allItems.push(null);
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return allItems;
|
|
378
|
+
});
|
|
379
|
+
}
|
|
274
380
|
/**
|
|
275
381
|
* Maps a raw DynamoDB item to a Model Item if it matches a registered model.
|
|
276
382
|
*/
|
package/dist/partition.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DynoQuery } from "./index";
|
|
2
2
|
import { IndexQuery } from "./index-query";
|
|
3
|
+
import { ExpressionBuilder } from "./expression-builder";
|
|
3
4
|
export interface PartitionConfig {
|
|
4
5
|
tableName?: string;
|
|
5
6
|
pk?: string;
|
|
@@ -11,6 +12,8 @@ export declare class Item {
|
|
|
11
12
|
private _partition;
|
|
12
13
|
private _skValue;
|
|
13
14
|
private _toBeDeleted;
|
|
15
|
+
private _filterBuilder?;
|
|
16
|
+
private _conditionBuilder?;
|
|
14
17
|
constructor(partition: Partition, skValue: string, data: any);
|
|
15
18
|
}
|
|
16
19
|
export declare class Partition {
|
|
@@ -30,14 +33,20 @@ export declare class Partition {
|
|
|
30
33
|
getAll<T = any>(options?: {
|
|
31
34
|
limit?: number;
|
|
32
35
|
exclusiveStartKey?: any;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
filterBuilder?: ExpressionBuilder;
|
|
37
|
+
FilterExpression?: string;
|
|
38
|
+
ExpressionAttributeNames?: Record<string, string>;
|
|
39
|
+
ExpressionAttributeValues?: Record<string, any>;
|
|
36
40
|
}): Promise<T[]>;
|
|
37
41
|
/**
|
|
38
42
|
* Create an item in this partition.
|
|
39
43
|
*/
|
|
40
|
-
create<T = any>(skValue: string, data: T, indices?: IndexQuery[]
|
|
44
|
+
create<T = any>(skValue: string, data: T, indices?: IndexQuery[], options?: {
|
|
45
|
+
conditionBuilder?: ExpressionBuilder;
|
|
46
|
+
ConditionExpression?: string;
|
|
47
|
+
ExpressionAttributeNames?: Record<string, string>;
|
|
48
|
+
ExpressionAttributeValues?: Record<string, any>;
|
|
49
|
+
}): Promise<T>;
|
|
41
50
|
/**
|
|
42
51
|
* Internal method to get raw data for a specific SK.
|
|
43
52
|
*/
|
|
@@ -45,11 +54,21 @@ export declare class Partition {
|
|
|
45
54
|
/**
|
|
46
55
|
* Update an existing item in this partition.
|
|
47
56
|
*/
|
|
48
|
-
update<T = any>(skValue: string, data: Partial<T>, indices?: IndexQuery[]
|
|
57
|
+
update<T = any>(skValue: string, data: Partial<T>, indices?: IndexQuery[], options?: {
|
|
58
|
+
conditionBuilder?: ExpressionBuilder;
|
|
59
|
+
ConditionExpression?: string;
|
|
60
|
+
ExpressionAttributeNames?: Record<string, string>;
|
|
61
|
+
ExpressionAttributeValues?: Record<string, any>;
|
|
62
|
+
}): Promise<T>;
|
|
49
63
|
/**
|
|
50
64
|
* Delete an item by its SK within this partition.
|
|
51
65
|
*/
|
|
52
|
-
delete(skValue: string
|
|
66
|
+
delete(skValue: string, options?: {
|
|
67
|
+
conditionBuilder?: ExpressionBuilder;
|
|
68
|
+
ConditionExpression?: string;
|
|
69
|
+
ExpressionAttributeNames?: Record<string, string>;
|
|
70
|
+
ExpressionAttributeValues?: Record<string, any>;
|
|
71
|
+
}): Promise<void>;
|
|
53
72
|
/**
|
|
54
73
|
* Get data for a specific SK and return it wrapped in a Item object.
|
|
55
74
|
*/
|
package/dist/partition.js
CHANGED
|
@@ -20,31 +20,67 @@ class Item {
|
|
|
20
20
|
const self = this;
|
|
21
21
|
return new Proxy(this, {
|
|
22
22
|
get(target, prop, receiver) {
|
|
23
|
-
if (prop === "
|
|
23
|
+
if (prop === "getData") {
|
|
24
24
|
return () => {
|
|
25
|
-
const
|
|
25
|
+
const data = {};
|
|
26
26
|
for (const key in target) {
|
|
27
27
|
if (Object.prototype.hasOwnProperty.call(target, key) &&
|
|
28
|
-
![
|
|
28
|
+
![
|
|
29
|
+
"_indices",
|
|
30
|
+
"_partition",
|
|
31
|
+
"_skValue",
|
|
32
|
+
"_toBeDeleted",
|
|
33
|
+
"_filterBuilder",
|
|
34
|
+
"_conditionBuilder",
|
|
35
|
+
].includes(key) &&
|
|
29
36
|
typeof target[key] !== "function") {
|
|
30
|
-
|
|
37
|
+
data[key] = target[key];
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
|
-
return
|
|
40
|
+
return data;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (prop === "save") {
|
|
44
|
+
return () => {
|
|
45
|
+
return partition.update(skValue, receiver.getData(), self._indices, {
|
|
46
|
+
conditionBuilder: self._conditionBuilder,
|
|
47
|
+
});
|
|
34
48
|
};
|
|
35
49
|
}
|
|
36
50
|
if (prop === "create") {
|
|
37
51
|
return (data, indices) => {
|
|
38
52
|
const dataToSave = data || {};
|
|
39
53
|
const finalIndices = indices || self._indices;
|
|
40
|
-
return partition.create(skValue, dataToSave, finalIndices
|
|
54
|
+
return partition.create(skValue, dataToSave, finalIndices, {
|
|
55
|
+
conditionBuilder: self._conditionBuilder,
|
|
56
|
+
});
|
|
41
57
|
};
|
|
42
58
|
}
|
|
43
59
|
if (prop === "update") {
|
|
44
60
|
return (data, indices) => {
|
|
45
|
-
return partition.update(skValue, data, indices
|
|
61
|
+
return partition.update(skValue, data, indices, {
|
|
62
|
+
conditionBuilder: self._conditionBuilder,
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (prop === "setFilter") {
|
|
67
|
+
return (builder) => {
|
|
68
|
+
self._filterBuilder = builder;
|
|
69
|
+
return receiver;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (prop === "setCondition") {
|
|
73
|
+
return (builder) => {
|
|
74
|
+
self._conditionBuilder = builder;
|
|
75
|
+
return receiver;
|
|
46
76
|
};
|
|
47
77
|
}
|
|
78
|
+
if (prop === "getFilterBuilder") {
|
|
79
|
+
return () => self._filterBuilder;
|
|
80
|
+
}
|
|
81
|
+
if (prop === "getConditionBuilder") {
|
|
82
|
+
return () => self._conditionBuilder;
|
|
83
|
+
}
|
|
48
84
|
if (prop === "setIndex") {
|
|
49
85
|
return (indexObj) => {
|
|
50
86
|
if (Array.isArray(indexObj)) {
|
|
@@ -118,12 +154,21 @@ class Partition {
|
|
|
118
154
|
*/
|
|
119
155
|
getAll(options) {
|
|
120
156
|
return __awaiter(this, void 0, void 0, function* () {
|
|
157
|
+
let filterExpression = options === null || options === void 0 ? void 0 : options.FilterExpression;
|
|
158
|
+
let expressionAttributeNames = Object.assign({ "#pk": this.pkName }, options === null || options === void 0 ? void 0 : options.ExpressionAttributeNames);
|
|
159
|
+
let expressionAttributeValues = Object.assign({ ":pk": this.pkValue }, options === null || options === void 0 ? void 0 : options.ExpressionAttributeValues);
|
|
160
|
+
if (options === null || options === void 0 ? void 0 : options.filterBuilder) {
|
|
161
|
+
const { expression, attributeNames, attributeValues } = options.filterBuilder.build();
|
|
162
|
+
filterExpression = expression;
|
|
163
|
+
expressionAttributeNames = Object.assign(Object.assign({}, expressionAttributeNames), attributeNames);
|
|
164
|
+
expressionAttributeValues = Object.assign(Object.assign({}, expressionAttributeValues), attributeValues);
|
|
165
|
+
}
|
|
121
166
|
const response = yield this.db.query({
|
|
122
167
|
TableName: this.tableName,
|
|
123
168
|
KeyConditionExpression: "#pk = :pk",
|
|
124
|
-
FilterExpression:
|
|
125
|
-
ExpressionAttributeNames:
|
|
126
|
-
ExpressionAttributeValues:
|
|
169
|
+
FilterExpression: filterExpression,
|
|
170
|
+
ExpressionAttributeNames: expressionAttributeNames,
|
|
171
|
+
ExpressionAttributeValues: expressionAttributeValues,
|
|
127
172
|
Limit: options === null || options === void 0 ? void 0 : options.limit,
|
|
128
173
|
ExclusiveStartKey: options === null || options === void 0 ? void 0 : options.exclusiveStartKey,
|
|
129
174
|
});
|
|
@@ -143,7 +188,7 @@ class Partition {
|
|
|
143
188
|
/**
|
|
144
189
|
* Create an item in this partition.
|
|
145
190
|
*/
|
|
146
|
-
create(skValue, data, indices) {
|
|
191
|
+
create(skValue, data, indices, options) {
|
|
147
192
|
return __awaiter(this, void 0, void 0, function* () {
|
|
148
193
|
const item = Object.assign({ [this.pkName]: this.pkValue, [this.skName]: skValue }, data);
|
|
149
194
|
if (indices) {
|
|
@@ -154,10 +199,22 @@ class Partition {
|
|
|
154
199
|
}
|
|
155
200
|
});
|
|
156
201
|
}
|
|
157
|
-
|
|
202
|
+
const createParams = {
|
|
158
203
|
TableName: this.tableName,
|
|
159
204
|
Item: item,
|
|
160
|
-
}
|
|
205
|
+
};
|
|
206
|
+
if (options === null || options === void 0 ? void 0 : options.conditionBuilder) {
|
|
207
|
+
const { expression, attributeNames, attributeValues } = options.conditionBuilder.build();
|
|
208
|
+
createParams.ConditionExpression = expression;
|
|
209
|
+
createParams.ExpressionAttributeNames = Object.assign(Object.assign({}, createParams.ExpressionAttributeNames), attributeNames);
|
|
210
|
+
createParams.ExpressionAttributeValues = Object.assign(Object.assign({}, createParams.ExpressionAttributeValues), attributeValues);
|
|
211
|
+
}
|
|
212
|
+
if (options === null || options === void 0 ? void 0 : options.ConditionExpression) {
|
|
213
|
+
createParams.ConditionExpression = options.ConditionExpression;
|
|
214
|
+
createParams.ExpressionAttributeNames = Object.assign(Object.assign({}, createParams.ExpressionAttributeNames), options.ExpressionAttributeNames);
|
|
215
|
+
createParams.ExpressionAttributeValues = Object.assign(Object.assign({}, createParams.ExpressionAttributeValues), options.ExpressionAttributeValues);
|
|
216
|
+
}
|
|
217
|
+
yield this.db.create(createParams);
|
|
161
218
|
this.cache[skValue] = item;
|
|
162
219
|
return new Item(this, skValue, item);
|
|
163
220
|
});
|
|
@@ -190,25 +247,37 @@ class Partition {
|
|
|
190
247
|
/**
|
|
191
248
|
* Update an existing item in this partition.
|
|
192
249
|
*/
|
|
193
|
-
update(skValue, data, indices) {
|
|
250
|
+
update(skValue, data, indices, options) {
|
|
194
251
|
return __awaiter(this, void 0, void 0, function* () {
|
|
195
252
|
const current = (yield this._getRaw(skValue)) || {};
|
|
196
253
|
const updated = Object.assign(Object.assign({}, current), data);
|
|
197
|
-
return yield this.create(skValue, updated, indices);
|
|
254
|
+
return yield this.create(skValue, updated, indices, options);
|
|
198
255
|
});
|
|
199
256
|
}
|
|
200
257
|
/**
|
|
201
258
|
* Delete an item by its SK within this partition.
|
|
202
259
|
*/
|
|
203
|
-
delete(skValue) {
|
|
260
|
+
delete(skValue, options) {
|
|
204
261
|
return __awaiter(this, void 0, void 0, function* () {
|
|
205
|
-
|
|
262
|
+
const deleteParams = {
|
|
206
263
|
TableName: this.tableName,
|
|
207
264
|
Key: {
|
|
208
265
|
[this.pkName]: this.pkValue,
|
|
209
266
|
[this.skName]: skValue,
|
|
210
267
|
},
|
|
211
|
-
}
|
|
268
|
+
};
|
|
269
|
+
if (options === null || options === void 0 ? void 0 : options.conditionBuilder) {
|
|
270
|
+
const { expression, attributeNames, attributeValues } = options.conditionBuilder.build();
|
|
271
|
+
deleteParams.ConditionExpression = expression;
|
|
272
|
+
deleteParams.ExpressionAttributeNames = Object.assign(Object.assign({}, deleteParams.ExpressionAttributeNames), attributeNames);
|
|
273
|
+
deleteParams.ExpressionAttributeValues = Object.assign(Object.assign({}, deleteParams.ExpressionAttributeValues), attributeValues);
|
|
274
|
+
}
|
|
275
|
+
if (options === null || options === void 0 ? void 0 : options.ConditionExpression) {
|
|
276
|
+
deleteParams.ConditionExpression = options.ConditionExpression;
|
|
277
|
+
deleteParams.ExpressionAttributeNames = Object.assign(Object.assign({}, deleteParams.ExpressionAttributeNames), options.ExpressionAttributeNames);
|
|
278
|
+
deleteParams.ExpressionAttributeValues = Object.assign(Object.assign({}, deleteParams.ExpressionAttributeValues), options.ExpressionAttributeValues);
|
|
279
|
+
}
|
|
280
|
+
yield this.db.delete(deleteParams);
|
|
212
281
|
delete this.cache[skValue];
|
|
213
282
|
});
|
|
214
283
|
}
|