dinah 0.11.1 → 0.13.0
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 +7 -2
- package/dist/cdk.cjs +1 -1
- package/dist/cdk.d.cts +1 -1
- package/dist/cdk.d.mts +1 -1
- package/dist/cdk.mjs +1 -1
- package/dist/index.cjs +247 -80
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +134 -75
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +134 -75
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +246 -82
- package/dist/index.mjs.map +1 -1
- package/dist/streams.cjs +1 -1
- package/dist/{table-BQvKnaNX.d.cts → table-CatYaz7J.d.mts} +9 -2
- package/dist/table-CatYaz7J.d.mts.map +1 -0
- package/dist/{table-D_frY5EF.d.mts → table-D814Vwjm.d.cts} +9 -2
- package/dist/table-D814Vwjm.d.cts.map +1 -0
- package/dist/{util-BfKXObBN.mjs → util-0kc6E2VD.mjs} +3 -2
- package/dist/{util-BfKXObBN.mjs.map → util-0kc6E2VD.mjs.map} +1 -1
- package/dist/{util-D88GS6Gt.cjs → util-DT6vwquI.cjs} +8 -1
- package/dist/{util-D88GS6Gt.cjs.map → util-DT6vwquI.cjs.map} +1 -1
- package/package.json +3 -2
- package/dist/table-BQvKnaNX.d.cts.map +0 -1
- package/dist/table-D_frY5EF.d.mts.map +0 -1
package/README.md
CHANGED
|
@@ -99,13 +99,18 @@ const UserTable = new Table(
|
|
|
99
99
|
|
|
100
100
|
### Using the Repository Class
|
|
101
101
|
|
|
102
|
-
`Repo` is the recommended way to interact with DynamoDB.
|
|
102
|
+
`Repo` is the recommended way to interact with DynamoDB. Use `db.makeRepo` to create a repo inline, with or without configuration:
|
|
103
103
|
|
|
104
104
|
```typescript
|
|
105
105
|
const userRepo = db.makeRepo(UserTable);
|
|
106
|
+
|
|
107
|
+
const userRepo = db.makeRepo(UserTable, {
|
|
108
|
+
defaultPutData: () => ({ createdAt: Date.now() }),
|
|
109
|
+
defaultUpdateData: () => ({ updatedAt: Date.now() }),
|
|
110
|
+
});
|
|
106
111
|
```
|
|
107
112
|
|
|
108
|
-
|
|
113
|
+
To create a named, reusable repo class, use the standalone `makeRepo` (see [Repository Configuration](#repository-configuration)):
|
|
109
114
|
|
|
110
115
|
```typescript
|
|
111
116
|
import { makeRepo } from "dinah";
|
package/dist/cdk.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_util = require("./util-
|
|
2
|
+
const require_util = require("./util-DT6vwquI.cjs");
|
|
3
3
|
let aws_cdk_lib_aws_dynamodb = require("aws-cdk-lib/aws-dynamodb");
|
|
4
4
|
aws_cdk_lib_aws_dynamodb = require_util.__toESM(aws_cdk_lib_aws_dynamodb, 1);
|
|
5
5
|
//#region src/cdk.ts
|
package/dist/cdk.d.cts
CHANGED
package/dist/cdk.d.mts
CHANGED
package/dist/cdk.mjs
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_util = require("./util-
|
|
2
|
+
const require_util = require("./util-DT6vwquI.cjs");
|
|
3
3
|
let _aws_sdk_client_dynamodb = require("@aws-sdk/client-dynamodb");
|
|
4
4
|
let _aws_sdk_lib_dynamodb = require("@aws-sdk/lib-dynamodb");
|
|
5
5
|
_aws_sdk_lib_dynamodb = require_util.__toESM(_aws_sdk_lib_dynamodb, 1);
|
|
6
|
+
//#region src/error.ts
|
|
7
|
+
function dinahErrorMessage(details) {
|
|
8
|
+
switch (details.type) {
|
|
9
|
+
case "NOT_FOUND": return `${details.resource ?? "Item"} not found: ${JSON.stringify(details.key)}`;
|
|
10
|
+
case "CONDITIONAL_CHECK_FAILED": return details.key ? `${details.resource ?? "Item"} condition check failed: ${JSON.stringify(details.key)}` : `${details.resource ?? "Item"} condition check failed`;
|
|
11
|
+
case "VALIDATION": return `Validation error: ${details.message}`;
|
|
12
|
+
case "DATA_INTEGRITY": return `Data integrity error: ${details.message}`;
|
|
13
|
+
case "TRANSACTION_CANCELED": return `Transaction canceled: ${details.reasons.map((r) => r.type).join(", ")}`;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
var DinahError = class extends Error {
|
|
17
|
+
details;
|
|
18
|
+
constructor(details, options) {
|
|
19
|
+
super(dinahErrorMessage(details), options);
|
|
20
|
+
this.name = "DinahError";
|
|
21
|
+
this.details = details;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const isDinahError = (err) => err instanceof DinahError;
|
|
25
|
+
//#endregion
|
|
6
26
|
//#region src/expression-builder.ts
|
|
7
27
|
const attrTypes = [
|
|
8
28
|
"S",
|
|
@@ -225,8 +245,15 @@ var Repo = class {
|
|
|
225
245
|
get tableName() {
|
|
226
246
|
return `${this.db.config?.tableNamePrefix ?? ""}${this.table.def.name}`;
|
|
227
247
|
}
|
|
228
|
-
get
|
|
229
|
-
|
|
248
|
+
get resourceName() {
|
|
249
|
+
if (this.config.resourceName) return this.config.resourceName;
|
|
250
|
+
const clsName = this.constructor.name;
|
|
251
|
+
if (clsName && clsName !== "Repo") return clsName.replace(/Repo$/i, "") || clsName;
|
|
252
|
+
const t = this.table.def.name;
|
|
253
|
+
return t.charAt(0).toUpperCase() + t.slice(1);
|
|
254
|
+
}
|
|
255
|
+
get defaultCreateData() {
|
|
256
|
+
return this.config.defaultCreateData?.() ?? {};
|
|
230
257
|
}
|
|
231
258
|
get defaultUpdateData() {
|
|
232
259
|
return this.config.defaultUpdateData?.() ?? {};
|
|
@@ -234,9 +261,6 @@ var Repo = class {
|
|
|
234
261
|
transformOutput(item) {
|
|
235
262
|
return this.config.transformOutput?.(item) ?? item;
|
|
236
263
|
}
|
|
237
|
-
transformInput(item) {
|
|
238
|
-
return this.config.transformInput?.(item) ?? item;
|
|
239
|
-
}
|
|
240
264
|
extractKey(item) {
|
|
241
265
|
const { partitionKey, sortKey } = this.table.def;
|
|
242
266
|
if (sortKey) return {
|
|
@@ -246,40 +270,44 @@ var Repo = class {
|
|
|
246
270
|
return { [partitionKey]: item[partitionKey] };
|
|
247
271
|
}
|
|
248
272
|
async get(key, options) {
|
|
273
|
+
const { filter, ...restOptions } = options ?? {};
|
|
249
274
|
const item = await this.db.get({
|
|
250
275
|
table: this.tableName,
|
|
251
276
|
key: this.extractKey(key),
|
|
252
|
-
|
|
277
|
+
filter,
|
|
278
|
+
...restOptions
|
|
253
279
|
});
|
|
254
280
|
return item && this.applyTransformIfNeeded(item, options);
|
|
255
281
|
}
|
|
256
282
|
async getOrThrow(key, options) {
|
|
283
|
+
const { filter, ...restOptions } = options ?? {};
|
|
257
284
|
const item = await this.db.getOrThrow({
|
|
258
285
|
table: this.tableName,
|
|
259
286
|
key: this.extractKey(key),
|
|
260
|
-
|
|
287
|
+
resource: this.resourceName,
|
|
288
|
+
filter,
|
|
289
|
+
...restOptions
|
|
261
290
|
});
|
|
262
291
|
return this.applyTransformIfNeeded(item, options);
|
|
263
292
|
}
|
|
264
293
|
async put(item, options) {
|
|
265
|
-
const itemWithDefaults = this.applyPutTransforms(item);
|
|
266
294
|
const result = await this.db.put({
|
|
267
295
|
table: this.tableName,
|
|
268
|
-
item
|
|
296
|
+
item,
|
|
297
|
+
resource: this.resourceName,
|
|
269
298
|
...options
|
|
270
299
|
});
|
|
271
300
|
return this.applyTransformIfNeeded(result);
|
|
272
301
|
}
|
|
273
302
|
async update(key, update, options) {
|
|
274
|
-
const updateWithDefaults = this.applyNormalizersToExpression(
|
|
275
|
-
...this.defaultUpdateData,
|
|
276
|
-
...update
|
|
277
|
-
});
|
|
303
|
+
const updateWithDefaults = this.applyNormalizersToExpression(update);
|
|
278
304
|
const result = await this.db.update({
|
|
279
305
|
table: this.tableName,
|
|
280
306
|
key: this.extractKey(key),
|
|
307
|
+
resource: this.resourceName,
|
|
281
308
|
update: updateWithDefaults,
|
|
282
|
-
...options
|
|
309
|
+
...options,
|
|
310
|
+
condition: this.withDiscriminatorCondition(key, options?.condition)
|
|
283
311
|
});
|
|
284
312
|
return this.applyTransformIfNeeded(result);
|
|
285
313
|
}
|
|
@@ -287,15 +315,21 @@ var Repo = class {
|
|
|
287
315
|
const { condition: otherCondition, ...otherOptions } = options ?? {};
|
|
288
316
|
const condition = { $and: [{ [this.table.def.partitionKey]: { $exists: false } }] };
|
|
289
317
|
if (otherCondition) condition.$and.push(otherCondition);
|
|
290
|
-
|
|
318
|
+
const normalizedItem = this.applyCreateTransforms(item);
|
|
319
|
+
const result = await this.db.put({
|
|
320
|
+
table: this.tableName,
|
|
321
|
+
item: normalizedItem,
|
|
322
|
+
resource: this.resourceName,
|
|
291
323
|
condition,
|
|
292
324
|
...otherOptions
|
|
293
325
|
});
|
|
326
|
+
return this.applyTransformIfNeeded(result);
|
|
294
327
|
}
|
|
295
328
|
async delete(key, options) {
|
|
296
329
|
const item = await this.db.delete({
|
|
297
330
|
table: this.tableName,
|
|
298
331
|
key: this.extractKey(key),
|
|
332
|
+
resource: this.resourceName,
|
|
299
333
|
...options
|
|
300
334
|
});
|
|
301
335
|
return item && this.applyTransformIfNeeded(item);
|
|
@@ -304,6 +338,7 @@ var Repo = class {
|
|
|
304
338
|
const item = await this.db.deleteOrThrow({
|
|
305
339
|
table: this.tableName,
|
|
306
340
|
key: this.extractKey(key),
|
|
341
|
+
resource: this.resourceName,
|
|
307
342
|
...options
|
|
308
343
|
});
|
|
309
344
|
return this.applyTransformIfNeeded(item);
|
|
@@ -346,6 +381,35 @@ var Repo = class {
|
|
|
346
381
|
gsi
|
|
347
382
|
});
|
|
348
383
|
}
|
|
384
|
+
async getGsi(gsi, query, options) {
|
|
385
|
+
const { filter, ...restOptions } = options ?? {};
|
|
386
|
+
const items = await this.db.query({
|
|
387
|
+
table: this.tableName,
|
|
388
|
+
index: gsi,
|
|
389
|
+
query,
|
|
390
|
+
...restOptions
|
|
391
|
+
});
|
|
392
|
+
if (items.length > 1) throw new DinahError({
|
|
393
|
+
type: "DATA_INTEGRITY",
|
|
394
|
+
message: `getGsi on "${gsi}" returned ${items.length} items; expected at most 1.`
|
|
395
|
+
});
|
|
396
|
+
const item = items[0];
|
|
397
|
+
if (!item) return void 0;
|
|
398
|
+
if (filter && !require_util.matchesPartial(filter, item)) return void 0;
|
|
399
|
+
return this.applyTransformIfNeeded(item, {
|
|
400
|
+
...options,
|
|
401
|
+
gsi
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
async getGsiOrThrow(gsi, query, options) {
|
|
405
|
+
const item = await this.getGsi(gsi, query, options);
|
|
406
|
+
if (item === void 0) throw new DinahError({
|
|
407
|
+
type: "NOT_FOUND",
|
|
408
|
+
key: query,
|
|
409
|
+
resource: this.resourceName
|
|
410
|
+
});
|
|
411
|
+
return item;
|
|
412
|
+
}
|
|
349
413
|
async scan(options) {
|
|
350
414
|
const items = await this.db.scan({
|
|
351
415
|
table: this.tableName,
|
|
@@ -396,9 +460,11 @@ var Repo = class {
|
|
|
396
460
|
});
|
|
397
461
|
}
|
|
398
462
|
async batchGet(keys, options) {
|
|
463
|
+
const { filter, ...restOptions } = options ?? {};
|
|
399
464
|
const { items, unprocessed } = await this.db.batchGet({ [this.tableName]: {
|
|
400
465
|
keys: keys.map((key) => this.extractKey(key)),
|
|
401
|
-
|
|
466
|
+
filter,
|
|
467
|
+
...restOptions
|
|
402
468
|
} });
|
|
403
469
|
const tableItems = items[this.tableName];
|
|
404
470
|
return {
|
|
@@ -407,9 +473,12 @@ var Repo = class {
|
|
|
407
473
|
};
|
|
408
474
|
}
|
|
409
475
|
async batchGetOrThrow(keys, options) {
|
|
476
|
+
const { filter, ...restOptions } = options ?? {};
|
|
410
477
|
const result = await this.db.batchGetOrThrow({ [this.tableName]: {
|
|
411
478
|
keys: keys.map((key) => this.extractKey(key)),
|
|
412
|
-
|
|
479
|
+
resource: this.resourceName,
|
|
480
|
+
filter,
|
|
481
|
+
...restOptions
|
|
413
482
|
} });
|
|
414
483
|
return this.applyTransformsIfNeeded(result[this.tableName] ?? [], options);
|
|
415
484
|
}
|
|
@@ -421,7 +490,7 @@ var Repo = class {
|
|
|
421
490
|
};
|
|
422
491
|
else return {
|
|
423
492
|
type: "PUT",
|
|
424
|
-
item:
|
|
493
|
+
item: request.item
|
|
425
494
|
};
|
|
426
495
|
}) });
|
|
427
496
|
return {
|
|
@@ -430,27 +499,29 @@ var Repo = class {
|
|
|
430
499
|
};
|
|
431
500
|
}
|
|
432
501
|
async batchUpdate(keys, update) {
|
|
433
|
-
const updateWithDefaults = this.applyNormalizersToExpression(
|
|
434
|
-
...this.defaultUpdateData,
|
|
435
|
-
...update
|
|
436
|
-
});
|
|
502
|
+
const updateWithDefaults = this.applyNormalizersToExpression(update);
|
|
437
503
|
return { unprocessed: (await this.db.batchUpdate({ [this.tableName]: {
|
|
438
504
|
keys: keys.map((key) => this.extractKey(key)),
|
|
439
505
|
update: updateWithDefaults
|
|
440
506
|
} })).unprocessed?.[this.tableName]?.keys };
|
|
441
507
|
}
|
|
442
508
|
async trxGet(keys, options) {
|
|
509
|
+
const { filter, ...restOptions } = options ?? {};
|
|
443
510
|
return (await this.db.trxGet(...keys.map((key) => ({
|
|
444
511
|
table: this.tableName,
|
|
445
512
|
key: this.extractKey(key),
|
|
446
|
-
|
|
513
|
+
filter,
|
|
514
|
+
...restOptions
|
|
447
515
|
})))).map((item) => item && this.applyTransformIfNeeded(item, options));
|
|
448
516
|
}
|
|
449
517
|
async trxGetOrThrow(keys, options) {
|
|
518
|
+
const { filter, ...restOptions } = options ?? {};
|
|
450
519
|
const items = await this.db.trxGetOrThrow(...keys.map((key) => ({
|
|
451
520
|
table: this.tableName,
|
|
452
521
|
key: this.extractKey(key),
|
|
453
|
-
|
|
522
|
+
resource: this.resourceName,
|
|
523
|
+
filter,
|
|
524
|
+
...restOptions
|
|
454
525
|
})));
|
|
455
526
|
return this.applyTransformsIfNeeded(items, options);
|
|
456
527
|
}
|
|
@@ -458,8 +529,8 @@ var Repo = class {
|
|
|
458
529
|
await this.db.trxWrite(...requests.map((request) => {
|
|
459
530
|
switch (request.type) {
|
|
460
531
|
case "CONDITION": {
|
|
461
|
-
const { key, condition
|
|
462
|
-
return this.trxConditionRequest(key, condition
|
|
532
|
+
const { key, condition } = request;
|
|
533
|
+
return this.trxConditionRequest(key, condition);
|
|
463
534
|
}
|
|
464
535
|
case "DELETE": {
|
|
465
536
|
const { key, ...options } = request;
|
|
@@ -504,85 +575,125 @@ var Repo = class {
|
|
|
504
575
|
...options
|
|
505
576
|
};
|
|
506
577
|
}
|
|
507
|
-
trxConditionRequest(key, condition
|
|
578
|
+
trxConditionRequest(key, condition) {
|
|
508
579
|
return {
|
|
509
580
|
table: this.tableName,
|
|
510
581
|
type: "CONDITION",
|
|
511
582
|
key: this.extractKey(key),
|
|
512
|
-
condition
|
|
513
|
-
...options
|
|
583
|
+
condition
|
|
514
584
|
};
|
|
515
585
|
}
|
|
516
586
|
trxPutRequest(item, options) {
|
|
517
|
-
const itemWithDefaults = this.applyPutTransforms(item);
|
|
518
587
|
return {
|
|
519
588
|
table: this.tableName,
|
|
520
589
|
type: "PUT",
|
|
521
|
-
item
|
|
590
|
+
item,
|
|
522
591
|
...options
|
|
523
592
|
};
|
|
524
593
|
}
|
|
525
594
|
trxUpdateRequest(key, update, options) {
|
|
526
|
-
const updateWithDefaults = this.applyNormalizersToExpression(
|
|
527
|
-
...this.defaultUpdateData,
|
|
528
|
-
...update
|
|
529
|
-
});
|
|
595
|
+
const updateWithDefaults = this.applyNormalizersToExpression(update);
|
|
530
596
|
return {
|
|
531
597
|
table: this.tableName,
|
|
532
598
|
type: "UPDATE",
|
|
533
599
|
key: this.extractKey(key),
|
|
534
600
|
update: updateWithDefaults,
|
|
535
|
-
...options
|
|
601
|
+
...options,
|
|
602
|
+
condition: this.withDiscriminatorCondition(key, options?.condition)
|
|
536
603
|
};
|
|
537
604
|
}
|
|
538
605
|
trxCreateRequest(item, options) {
|
|
539
606
|
const { condition: otherCondition, ...otherOptions } = options ?? {};
|
|
540
607
|
const condition = { $and: [{ [this.table.def.partitionKey]: { $exists: false } }] };
|
|
541
608
|
if (otherCondition) condition.$and.push(otherCondition);
|
|
542
|
-
const
|
|
609
|
+
const normalizedItem = this.applyCreateTransforms(item);
|
|
543
610
|
return {
|
|
544
611
|
table: this.tableName,
|
|
545
612
|
type: "PUT",
|
|
546
|
-
item:
|
|
613
|
+
item: normalizedItem,
|
|
547
614
|
condition,
|
|
548
615
|
...otherOptions
|
|
549
616
|
};
|
|
550
617
|
}
|
|
551
|
-
|
|
552
|
-
const
|
|
553
|
-
|
|
618
|
+
applyCreateTransforms(item) {
|
|
619
|
+
const { transformAttributes, computedAttributes } = this.config;
|
|
620
|
+
if (computedAttributes) {
|
|
621
|
+
for (const key of Object.keys(computedAttributes)) if (key in item) throw new DinahError({
|
|
622
|
+
type: "VALIDATION",
|
|
623
|
+
message: `Field "${key}" is a computed attribute and cannot be set directly. Remove it from the create input.`
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
const merged = {
|
|
627
|
+
...this.defaultCreateData,
|
|
554
628
|
...item
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
629
|
+
};
|
|
630
|
+
if (transformAttributes) {
|
|
631
|
+
for (const [key, transform] of Object.entries(transformAttributes)) if (key in merged && merged[key] !== void 0) merged[key] = transform(merged[key]);
|
|
632
|
+
}
|
|
633
|
+
if (computedAttributes) for (const [key, def] of Object.entries(computedAttributes)) {
|
|
634
|
+
const { from, compute } = def;
|
|
635
|
+
const computed = compute(merged[from]);
|
|
636
|
+
if (computed !== void 0) merged[key] = computed;
|
|
637
|
+
else delete merged[key];
|
|
638
|
+
}
|
|
639
|
+
return merged;
|
|
640
|
+
}
|
|
641
|
+
applyNormalizersToExpression(userUpdate) {
|
|
642
|
+
const { transformAttributes, computedAttributes, immutableAttributes } = this.config;
|
|
643
|
+
if (computedAttributes) {
|
|
644
|
+
for (const key of Object.keys(computedAttributes)) if (key in userUpdate) throw new DinahError({
|
|
645
|
+
type: "VALIDATION",
|
|
646
|
+
message: `Field "${key}" is a computed attribute and cannot be set directly in an update. Update the source field instead.`
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
for (const key of immutableAttributes ?? []) if (key in userUpdate) throw new DinahError({
|
|
650
|
+
type: "VALIDATION",
|
|
651
|
+
message: `Field "${key}" is immutable and cannot be updated.`
|
|
652
|
+
});
|
|
653
|
+
const result = {
|
|
654
|
+
...this.defaultUpdateData,
|
|
655
|
+
...userUpdate
|
|
656
|
+
};
|
|
657
|
+
if (transformAttributes) for (const [key, transform] of Object.entries(transformAttributes)) {
|
|
658
|
+
if (!(key in result)) continue;
|
|
659
|
+
const val = result[key];
|
|
660
|
+
const fn = transform;
|
|
661
|
+
if (val === void 0 || isOperation(val) && val.$remove === true) {} else if (!isOperation(val)) result[key] = fn(val);
|
|
662
|
+
else if (val.$set !== void 0) result[key] = {
|
|
663
|
+
...val,
|
|
664
|
+
$set: fn(val.$set)
|
|
665
|
+
};
|
|
666
|
+
else if (val.$ifNotExists !== void 0) {
|
|
667
|
+
const ifne = val.$ifNotExists;
|
|
668
|
+
result[key] = {
|
|
669
|
+
...val,
|
|
670
|
+
$ifNotExists: Array.isArray(ifne) ? [ifne[0], fn(ifne[1])] : fn(ifne)
|
|
580
671
|
};
|
|
581
672
|
}
|
|
582
673
|
}
|
|
583
|
-
for (const
|
|
674
|
+
if (computedAttributes) for (const [computedKey, def] of Object.entries(computedAttributes)) {
|
|
675
|
+
const { from, compute } = def;
|
|
676
|
+
if (!(from in result)) continue;
|
|
677
|
+
const val = result[from];
|
|
678
|
+
if (val === void 0 || isOperation(val) && val.$remove === true) result[computedKey] = void 0;
|
|
679
|
+
else if (!isOperation(val)) result[computedKey] = compute(val);
|
|
680
|
+
else if (val.$set !== void 0) result[computedKey] = compute(val.$set);
|
|
681
|
+
else throw new DinahError({
|
|
682
|
+
type: "VALIDATION",
|
|
683
|
+
message: `Field "${from}" drives computed field "${computedKey}" and cannot use arithmetic or list operators in updates.`
|
|
684
|
+
});
|
|
685
|
+
}
|
|
584
686
|
return result;
|
|
585
687
|
}
|
|
688
|
+
withDiscriminatorCondition(key, condition) {
|
|
689
|
+
const discriminator = this.config.discriminator;
|
|
690
|
+
if (!discriminator) return condition;
|
|
691
|
+
const value = key[discriminator];
|
|
692
|
+
if (value === void 0) return condition;
|
|
693
|
+
const guard = { [discriminator]: value };
|
|
694
|
+
if (!condition) return guard;
|
|
695
|
+
return { $and: [guard, condition] };
|
|
696
|
+
}
|
|
586
697
|
applyTransformsIfNeeded(items, options) {
|
|
587
698
|
if (options?.projection?.length) return items;
|
|
588
699
|
if (options?.gsi) {
|
|
@@ -652,12 +763,16 @@ var Db = class {
|
|
|
652
763
|
ExpressionAttributeNames: exp.attributeNames
|
|
653
764
|
});
|
|
654
765
|
const output = await this.client.send(input);
|
|
655
|
-
if (output.Item && data.filter && !data.filter
|
|
766
|
+
if (output.Item && data.filter && !require_util.matchesPartial(data.filter, output.Item)) return;
|
|
656
767
|
return output.Item;
|
|
657
768
|
}
|
|
658
769
|
async getOrThrow(data) {
|
|
659
770
|
const item = await this.get(data);
|
|
660
|
-
if (!item) throw new
|
|
771
|
+
if (!item) throw new DinahError({
|
|
772
|
+
type: "NOT_FOUND",
|
|
773
|
+
key: data.key,
|
|
774
|
+
resource: data.resource
|
|
775
|
+
});
|
|
661
776
|
return item;
|
|
662
777
|
}
|
|
663
778
|
async put(data) {
|
|
@@ -672,8 +787,16 @@ var Db = class {
|
|
|
672
787
|
ExpressionAttributeNames: exp.attributeNames,
|
|
673
788
|
ExpressionAttributeValues: exp.attributeValues
|
|
674
789
|
});
|
|
675
|
-
|
|
676
|
-
|
|
790
|
+
try {
|
|
791
|
+
const output = await this.client.send(input);
|
|
792
|
+
return data.returnOld ? output.Attributes : item;
|
|
793
|
+
} catch (err) {
|
|
794
|
+
if (err instanceof _aws_sdk_client_dynamodb.ConditionalCheckFailedException) throw new DinahError({
|
|
795
|
+
type: "CONDITIONAL_CHECK_FAILED",
|
|
796
|
+
resource: data.resource
|
|
797
|
+
}, { cause: err });
|
|
798
|
+
throw err;
|
|
799
|
+
}
|
|
677
800
|
}
|
|
678
801
|
async update(data) {
|
|
679
802
|
const exp = new ExpressionBuilder();
|
|
@@ -689,7 +812,16 @@ var Db = class {
|
|
|
689
812
|
ExpressionAttributeNames: exp.attributeNames,
|
|
690
813
|
ExpressionAttributeValues: exp.attributeValues
|
|
691
814
|
});
|
|
692
|
-
|
|
815
|
+
try {
|
|
816
|
+
return (await this.client.send(input)).Attributes;
|
|
817
|
+
} catch (err) {
|
|
818
|
+
if (err instanceof _aws_sdk_client_dynamodb.ConditionalCheckFailedException) throw new DinahError({
|
|
819
|
+
type: "CONDITIONAL_CHECK_FAILED",
|
|
820
|
+
key: data.key,
|
|
821
|
+
resource: data.resource
|
|
822
|
+
}, { cause: err });
|
|
823
|
+
throw err;
|
|
824
|
+
}
|
|
693
825
|
}
|
|
694
826
|
async delete(data) {
|
|
695
827
|
const exp = new ExpressionBuilder();
|
|
@@ -702,11 +834,24 @@ var Db = class {
|
|
|
702
834
|
ExpressionAttributeNames: exp.attributeNames,
|
|
703
835
|
ExpressionAttributeValues: exp.attributeValues
|
|
704
836
|
});
|
|
705
|
-
|
|
837
|
+
try {
|
|
838
|
+
return (await this.client.send(input)).Attributes;
|
|
839
|
+
} catch (err) {
|
|
840
|
+
if (err instanceof _aws_sdk_client_dynamodb.ConditionalCheckFailedException) throw new DinahError({
|
|
841
|
+
type: "CONDITIONAL_CHECK_FAILED",
|
|
842
|
+
key: data.key,
|
|
843
|
+
resource: data.resource
|
|
844
|
+
}, { cause: err });
|
|
845
|
+
throw err;
|
|
846
|
+
}
|
|
706
847
|
}
|
|
707
848
|
async deleteOrThrow(data) {
|
|
708
849
|
const item = await this.delete(data);
|
|
709
|
-
if (!item) throw new
|
|
850
|
+
if (!item) throw new DinahError({
|
|
851
|
+
type: "NOT_FOUND",
|
|
852
|
+
key: data.key,
|
|
853
|
+
resource: data.resource
|
|
854
|
+
});
|
|
710
855
|
return item;
|
|
711
856
|
}
|
|
712
857
|
async *queryPaged(data) {
|
|
@@ -821,7 +966,7 @@ var Db = class {
|
|
|
821
966
|
const output = await this.client.send(input);
|
|
822
967
|
for (const [table, items] of Object.entries(output.Responses ?? {})) {
|
|
823
968
|
if (!result.items[table]) continue;
|
|
824
|
-
const filteredItems = tableData[table]?.filter ? items.filter(tableData[table].filter) : items;
|
|
969
|
+
const filteredItems = tableData[table]?.filter ? items.filter((item) => require_util.matchesPartial(tableData[table].filter, item)) : items;
|
|
825
970
|
result.items[table].push(...filteredItems);
|
|
826
971
|
}
|
|
827
972
|
let unprocessedKeyCount = 0;
|
|
@@ -863,7 +1008,11 @@ var Db = class {
|
|
|
863
1008
|
const { items, unprocessed } = await this.batchGet(data);
|
|
864
1009
|
for (const table of Object.keys(data)) {
|
|
865
1010
|
if (unprocessed?.[table]) throw new Error(`One or more batch get requests were not processed in "${table}" table.`);
|
|
866
|
-
if (items[table]?.length !== data[table]?.keys?.length) throw new
|
|
1011
|
+
if (items[table]?.length !== data[table]?.keys?.length) throw new DinahError({
|
|
1012
|
+
type: "NOT_FOUND",
|
|
1013
|
+
key: {},
|
|
1014
|
+
resource: data[table]?.resource
|
|
1015
|
+
});
|
|
867
1016
|
}
|
|
868
1017
|
return items;
|
|
869
1018
|
}
|
|
@@ -978,12 +1127,16 @@ var Db = class {
|
|
|
978
1127
|
return (await this.client.send(input)).Responses?.map((response, i) => {
|
|
979
1128
|
if (!response.Item) return;
|
|
980
1129
|
if (!requests[i]?.filter) return response.Item;
|
|
981
|
-
return requests[i].filter
|
|
1130
|
+
return require_util.matchesPartial(requests[i].filter, response.Item) ? response.Item : void 0;
|
|
982
1131
|
}) ?? [];
|
|
983
1132
|
}
|
|
984
1133
|
async trxGetOrThrow(...requests) {
|
|
985
1134
|
const items = await this.trxGet(...requests);
|
|
986
|
-
for (let i = 0; i < items.length; i++) if (!items[i]) throw new
|
|
1135
|
+
for (let i = 0; i < items.length; i++) if (!items[i]) throw new DinahError({
|
|
1136
|
+
type: "NOT_FOUND",
|
|
1137
|
+
key: requests[i]?.key ?? {},
|
|
1138
|
+
resource: requests[i]?.resource
|
|
1139
|
+
});
|
|
987
1140
|
return items;
|
|
988
1141
|
}
|
|
989
1142
|
async trxWrite(...requests) {
|
|
@@ -1013,7 +1166,18 @@ var Db = class {
|
|
|
1013
1166
|
} };
|
|
1014
1167
|
});
|
|
1015
1168
|
const input = new _aws_sdk_lib_dynamodb.TransactWriteCommand({ TransactItems: trxItems });
|
|
1016
|
-
|
|
1169
|
+
try {
|
|
1170
|
+
await this.client.send(input);
|
|
1171
|
+
} catch (err) {
|
|
1172
|
+
if (err instanceof _aws_sdk_client_dynamodb.TransactionCanceledException) throw new DinahError({
|
|
1173
|
+
type: "TRANSACTION_CANCELED",
|
|
1174
|
+
reasons: (err.CancellationReasons ?? []).map((r) => ({
|
|
1175
|
+
type: r.Code ?? "Unknown",
|
|
1176
|
+
message: r.Message
|
|
1177
|
+
}))
|
|
1178
|
+
}, { cause: err });
|
|
1179
|
+
throw err;
|
|
1180
|
+
}
|
|
1017
1181
|
}
|
|
1018
1182
|
};
|
|
1019
1183
|
//#endregion
|
|
@@ -1028,11 +1192,14 @@ var Table = class {
|
|
|
1028
1192
|
};
|
|
1029
1193
|
//#endregion
|
|
1030
1194
|
exports.Db = Db;
|
|
1195
|
+
exports.DinahError = DinahError;
|
|
1031
1196
|
exports.Repo = Repo;
|
|
1032
1197
|
exports.Table = Table;
|
|
1033
1198
|
exports.chunk = require_util.chunk;
|
|
1034
1199
|
exports.extractTableDesc = require_util.extractTableDesc;
|
|
1200
|
+
exports.isDinahError = isDinahError;
|
|
1035
1201
|
exports.makeRepo = makeRepo;
|
|
1202
|
+
exports.matchesPartial = require_util.matchesPartial;
|
|
1036
1203
|
exports.removeUndefined = require_util.removeUndefined;
|
|
1037
1204
|
exports.resolveAttrType = require_util.resolveAttrType;
|
|
1038
1205
|
|