dynoquery 0.1.20 → 0.1.22
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 +136 -2
- package/dist/partition.d.ts +25 -6
- package/dist/partition.js +72 -15
- 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 = {};
|
|
@@ -181,7 +184,14 @@ class DynoQuery {
|
|
|
181
184
|
const dataToSave = {};
|
|
182
185
|
for (const key in item) {
|
|
183
186
|
if (Object.prototype.hasOwnProperty.call(item, key) &&
|
|
184
|
-
![
|
|
187
|
+
![
|
|
188
|
+
"_indices",
|
|
189
|
+
"_partition",
|
|
190
|
+
"_skValue",
|
|
191
|
+
"_toBeDeleted",
|
|
192
|
+
"_filterBuilder",
|
|
193
|
+
"_conditionBuilder",
|
|
194
|
+
].includes(key) &&
|
|
185
195
|
typeof item[key] !== "function") {
|
|
186
196
|
dataToSave[key] = item[key];
|
|
187
197
|
}
|
|
@@ -271,6 +281,130 @@ class DynoQuery {
|
|
|
271
281
|
return allItems;
|
|
272
282
|
});
|
|
273
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* Transact write items to the table.
|
|
286
|
+
*/
|
|
287
|
+
transactWrite(items) {
|
|
288
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
289
|
+
// Chunk items into 100
|
|
290
|
+
for (let i = 0; i < items.length; i += 100) {
|
|
291
|
+
const chunk = items.slice(i, i + 100);
|
|
292
|
+
const transactItems = chunk.map((item) => {
|
|
293
|
+
const partition = item.getPartition();
|
|
294
|
+
const tableName = partition.getTableName();
|
|
295
|
+
const skValue = item.getSkValue();
|
|
296
|
+
const pkValue = partition.getPkValue();
|
|
297
|
+
const conditionBuilder = item.getConditionBuilder();
|
|
298
|
+
if (item.toBeDeleted()) {
|
|
299
|
+
const deleteItem = {
|
|
300
|
+
Key: {
|
|
301
|
+
[this.pkName]: pkValue,
|
|
302
|
+
[this.skName]: skValue,
|
|
303
|
+
},
|
|
304
|
+
TableName: tableName,
|
|
305
|
+
};
|
|
306
|
+
if (conditionBuilder) {
|
|
307
|
+
const { expression, attributeNames, attributeValues } = conditionBuilder.build();
|
|
308
|
+
deleteItem.ConditionExpression = expression;
|
|
309
|
+
deleteItem.ExpressionAttributeNames = attributeNames;
|
|
310
|
+
deleteItem.ExpressionAttributeValues = attributeValues;
|
|
311
|
+
}
|
|
312
|
+
return {
|
|
313
|
+
Delete: deleteItem,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
const dataToSave = {};
|
|
318
|
+
for (const key in item) {
|
|
319
|
+
if (Object.prototype.hasOwnProperty.call(item, key) &&
|
|
320
|
+
![
|
|
321
|
+
"_indices",
|
|
322
|
+
"_partition",
|
|
323
|
+
"_skValue",
|
|
324
|
+
"_toBeDeleted",
|
|
325
|
+
"_filterBuilder",
|
|
326
|
+
"_conditionBuilder",
|
|
327
|
+
].includes(key) &&
|
|
328
|
+
typeof item[key] !== "function") {
|
|
329
|
+
dataToSave[key] = item[key];
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// Ensure PK and SK are in the data
|
|
333
|
+
dataToSave[this.pkName] = pkValue;
|
|
334
|
+
dataToSave[this.skName] = skValue;
|
|
335
|
+
const putItem = {
|
|
336
|
+
Item: dataToSave,
|
|
337
|
+
TableName: tableName,
|
|
338
|
+
};
|
|
339
|
+
if (conditionBuilder) {
|
|
340
|
+
const { expression, attributeNames, attributeValues } = conditionBuilder.build();
|
|
341
|
+
putItem.ConditionExpression = expression;
|
|
342
|
+
putItem.ExpressionAttributeNames = attributeNames;
|
|
343
|
+
putItem.ExpressionAttributeValues = attributeValues;
|
|
344
|
+
}
|
|
345
|
+
return {
|
|
346
|
+
Put: putItem,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
yield this.docClient.send(new lib_dynamodb_1.TransactWriteCommand({
|
|
351
|
+
TransactItems: transactItems,
|
|
352
|
+
}));
|
|
353
|
+
}
|
|
354
|
+
return items;
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Transact get items from the table.
|
|
359
|
+
*/
|
|
360
|
+
transactRead(items) {
|
|
361
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
362
|
+
const allItems = [];
|
|
363
|
+
// Chunk items into 100
|
|
364
|
+
for (let i = 0; i < items.length; i += 100) {
|
|
365
|
+
const chunk = items.slice(i, i + 100);
|
|
366
|
+
const transactItems = chunk.map((item) => {
|
|
367
|
+
let tableName;
|
|
368
|
+
let pkValue;
|
|
369
|
+
let skValue;
|
|
370
|
+
if (item instanceof index_query_1.IndexQuery) {
|
|
371
|
+
tableName = item.tableName;
|
|
372
|
+
pkValue = item.getPkValue();
|
|
373
|
+
skValue = item.getSkValue() || "";
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
const partition = item.getPartition();
|
|
377
|
+
tableName = partition.getTableName();
|
|
378
|
+
pkValue = partition.getPkValue();
|
|
379
|
+
skValue = item.getSkValue();
|
|
380
|
+
}
|
|
381
|
+
return {
|
|
382
|
+
Get: {
|
|
383
|
+
TableName: tableName,
|
|
384
|
+
Key: {
|
|
385
|
+
[this.pkName]: pkValue,
|
|
386
|
+
[this.skName]: skValue,
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
});
|
|
391
|
+
const response = yield this.docClient.send(new lib_dynamodb_1.TransactGetCommand({
|
|
392
|
+
TransactItems: transactItems,
|
|
393
|
+
}));
|
|
394
|
+
if (response.Responses) {
|
|
395
|
+
response.Responses.forEach((res) => {
|
|
396
|
+
if (res.Item) {
|
|
397
|
+
allItems.push(this.mapItemToModelItem(res.Item));
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
allItems.push(null);
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return allItems;
|
|
406
|
+
});
|
|
407
|
+
}
|
|
274
408
|
/**
|
|
275
409
|
* Maps a raw DynamoDB item to a Model Item if it matches a registered model.
|
|
276
410
|
*/
|
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
|
@@ -25,26 +25,50 @@ class Item {
|
|
|
25
25
|
const dataToSave = {};
|
|
26
26
|
for (const key in target) {
|
|
27
27
|
if (Object.prototype.hasOwnProperty.call(target, key) &&
|
|
28
|
-
!["_indices", "_partition", "_skValue", "_toBeDeleted"].includes(key) &&
|
|
28
|
+
!["_indices", "_partition", "_skValue", "_toBeDeleted", "_filterBuilder", "_conditionBuilder"].includes(key) &&
|
|
29
29
|
typeof target[key] !== "function") {
|
|
30
30
|
dataToSave[key] = target[key];
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
-
return partition.update(skValue, dataToSave, self._indices
|
|
33
|
+
return partition.update(skValue, dataToSave, self._indices, {
|
|
34
|
+
conditionBuilder: self._conditionBuilder,
|
|
35
|
+
});
|
|
34
36
|
};
|
|
35
37
|
}
|
|
36
38
|
if (prop === "create") {
|
|
37
39
|
return (data, indices) => {
|
|
38
40
|
const dataToSave = data || {};
|
|
39
41
|
const finalIndices = indices || self._indices;
|
|
40
|
-
return partition.create(skValue, dataToSave, finalIndices
|
|
42
|
+
return partition.create(skValue, dataToSave, finalIndices, {
|
|
43
|
+
conditionBuilder: self._conditionBuilder,
|
|
44
|
+
});
|
|
41
45
|
};
|
|
42
46
|
}
|
|
43
47
|
if (prop === "update") {
|
|
44
48
|
return (data, indices) => {
|
|
45
|
-
return partition.update(skValue, data, indices
|
|
49
|
+
return partition.update(skValue, data, indices, {
|
|
50
|
+
conditionBuilder: self._conditionBuilder,
|
|
51
|
+
});
|
|
46
52
|
};
|
|
47
53
|
}
|
|
54
|
+
if (prop === "setFilter") {
|
|
55
|
+
return (builder) => {
|
|
56
|
+
self._filterBuilder = builder;
|
|
57
|
+
return receiver;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
if (prop === "setCondition") {
|
|
61
|
+
return (builder) => {
|
|
62
|
+
self._conditionBuilder = builder;
|
|
63
|
+
return receiver;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (prop === "getFilterBuilder") {
|
|
67
|
+
return () => self._filterBuilder;
|
|
68
|
+
}
|
|
69
|
+
if (prop === "getConditionBuilder") {
|
|
70
|
+
return () => self._conditionBuilder;
|
|
71
|
+
}
|
|
48
72
|
if (prop === "setIndex") {
|
|
49
73
|
return (indexObj) => {
|
|
50
74
|
if (Array.isArray(indexObj)) {
|
|
@@ -118,12 +142,21 @@ class Partition {
|
|
|
118
142
|
*/
|
|
119
143
|
getAll(options) {
|
|
120
144
|
return __awaiter(this, void 0, void 0, function* () {
|
|
145
|
+
let filterExpression = options === null || options === void 0 ? void 0 : options.FilterExpression;
|
|
146
|
+
let expressionAttributeNames = Object.assign({ "#pk": this.pkName }, options === null || options === void 0 ? void 0 : options.ExpressionAttributeNames);
|
|
147
|
+
let expressionAttributeValues = Object.assign({ ":pk": this.pkValue }, options === null || options === void 0 ? void 0 : options.ExpressionAttributeValues);
|
|
148
|
+
if (options === null || options === void 0 ? void 0 : options.filterBuilder) {
|
|
149
|
+
const { expression, attributeNames, attributeValues } = options.filterBuilder.build();
|
|
150
|
+
filterExpression = expression;
|
|
151
|
+
expressionAttributeNames = Object.assign(Object.assign({}, expressionAttributeNames), attributeNames);
|
|
152
|
+
expressionAttributeValues = Object.assign(Object.assign({}, expressionAttributeValues), attributeValues);
|
|
153
|
+
}
|
|
121
154
|
const response = yield this.db.query({
|
|
122
155
|
TableName: this.tableName,
|
|
123
156
|
KeyConditionExpression: "#pk = :pk",
|
|
124
|
-
FilterExpression:
|
|
125
|
-
ExpressionAttributeNames:
|
|
126
|
-
ExpressionAttributeValues:
|
|
157
|
+
FilterExpression: filterExpression,
|
|
158
|
+
ExpressionAttributeNames: expressionAttributeNames,
|
|
159
|
+
ExpressionAttributeValues: expressionAttributeValues,
|
|
127
160
|
Limit: options === null || options === void 0 ? void 0 : options.limit,
|
|
128
161
|
ExclusiveStartKey: options === null || options === void 0 ? void 0 : options.exclusiveStartKey,
|
|
129
162
|
});
|
|
@@ -143,7 +176,7 @@ class Partition {
|
|
|
143
176
|
/**
|
|
144
177
|
* Create an item in this partition.
|
|
145
178
|
*/
|
|
146
|
-
create(skValue, data, indices) {
|
|
179
|
+
create(skValue, data, indices, options) {
|
|
147
180
|
return __awaiter(this, void 0, void 0, function* () {
|
|
148
181
|
const item = Object.assign({ [this.pkName]: this.pkValue, [this.skName]: skValue }, data);
|
|
149
182
|
if (indices) {
|
|
@@ -154,10 +187,22 @@ class Partition {
|
|
|
154
187
|
}
|
|
155
188
|
});
|
|
156
189
|
}
|
|
157
|
-
|
|
190
|
+
const createParams = {
|
|
158
191
|
TableName: this.tableName,
|
|
159
192
|
Item: item,
|
|
160
|
-
}
|
|
193
|
+
};
|
|
194
|
+
if (options === null || options === void 0 ? void 0 : options.conditionBuilder) {
|
|
195
|
+
const { expression, attributeNames, attributeValues } = options.conditionBuilder.build();
|
|
196
|
+
createParams.ConditionExpression = expression;
|
|
197
|
+
createParams.ExpressionAttributeNames = Object.assign(Object.assign({}, createParams.ExpressionAttributeNames), attributeNames);
|
|
198
|
+
createParams.ExpressionAttributeValues = Object.assign(Object.assign({}, createParams.ExpressionAttributeValues), attributeValues);
|
|
199
|
+
}
|
|
200
|
+
if (options === null || options === void 0 ? void 0 : options.ConditionExpression) {
|
|
201
|
+
createParams.ConditionExpression = options.ConditionExpression;
|
|
202
|
+
createParams.ExpressionAttributeNames = Object.assign(Object.assign({}, createParams.ExpressionAttributeNames), options.ExpressionAttributeNames);
|
|
203
|
+
createParams.ExpressionAttributeValues = Object.assign(Object.assign({}, createParams.ExpressionAttributeValues), options.ExpressionAttributeValues);
|
|
204
|
+
}
|
|
205
|
+
yield this.db.create(createParams);
|
|
161
206
|
this.cache[skValue] = item;
|
|
162
207
|
return new Item(this, skValue, item);
|
|
163
208
|
});
|
|
@@ -190,25 +235,37 @@ class Partition {
|
|
|
190
235
|
/**
|
|
191
236
|
* Update an existing item in this partition.
|
|
192
237
|
*/
|
|
193
|
-
update(skValue, data, indices) {
|
|
238
|
+
update(skValue, data, indices, options) {
|
|
194
239
|
return __awaiter(this, void 0, void 0, function* () {
|
|
195
240
|
const current = (yield this._getRaw(skValue)) || {};
|
|
196
241
|
const updated = Object.assign(Object.assign({}, current), data);
|
|
197
|
-
return yield this.create(skValue, updated, indices);
|
|
242
|
+
return yield this.create(skValue, updated, indices, options);
|
|
198
243
|
});
|
|
199
244
|
}
|
|
200
245
|
/**
|
|
201
246
|
* Delete an item by its SK within this partition.
|
|
202
247
|
*/
|
|
203
|
-
delete(skValue) {
|
|
248
|
+
delete(skValue, options) {
|
|
204
249
|
return __awaiter(this, void 0, void 0, function* () {
|
|
205
|
-
|
|
250
|
+
const deleteParams = {
|
|
206
251
|
TableName: this.tableName,
|
|
207
252
|
Key: {
|
|
208
253
|
[this.pkName]: this.pkValue,
|
|
209
254
|
[this.skName]: skValue,
|
|
210
255
|
},
|
|
211
|
-
}
|
|
256
|
+
};
|
|
257
|
+
if (options === null || options === void 0 ? void 0 : options.conditionBuilder) {
|
|
258
|
+
const { expression, attributeNames, attributeValues } = options.conditionBuilder.build();
|
|
259
|
+
deleteParams.ConditionExpression = expression;
|
|
260
|
+
deleteParams.ExpressionAttributeNames = Object.assign(Object.assign({}, deleteParams.ExpressionAttributeNames), attributeNames);
|
|
261
|
+
deleteParams.ExpressionAttributeValues = Object.assign(Object.assign({}, deleteParams.ExpressionAttributeValues), attributeValues);
|
|
262
|
+
}
|
|
263
|
+
if (options === null || options === void 0 ? void 0 : options.ConditionExpression) {
|
|
264
|
+
deleteParams.ConditionExpression = options.ConditionExpression;
|
|
265
|
+
deleteParams.ExpressionAttributeNames = Object.assign(Object.assign({}, deleteParams.ExpressionAttributeNames), options.ExpressionAttributeNames);
|
|
266
|
+
deleteParams.ExpressionAttributeValues = Object.assign(Object.assign({}, deleteParams.ExpressionAttributeValues), options.ExpressionAttributeValues);
|
|
267
|
+
}
|
|
268
|
+
yield this.db.delete(deleteParams);
|
|
212
269
|
delete this.cache[skValue];
|
|
213
270
|
});
|
|
214
271
|
}
|