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