dinah 0.11.1 → 0.12.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 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. For a plain repo with no configuration, use `db.createRepo`:
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
- For repos with defaults, transforms, or attribute rules, use `makeRepo` to define a class (see [Repository Configuration](#repository-configuration)):
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/index.cjs CHANGED
@@ -3,6 +3,25 @@ const require_util = require("./util-D88GS6Gt.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 "TRANSACTION_CANCELED": return `Transaction canceled: ${details.reasons.map((r) => r.type).join(", ")}`;
13
+ }
14
+ }
15
+ var DinahError = class extends Error {
16
+ details;
17
+ constructor(details, options) {
18
+ super(dinahErrorMessage(details), options);
19
+ this.name = "DinahError";
20
+ this.details = details;
21
+ }
22
+ };
23
+ const isDinahError = (err) => err instanceof DinahError;
24
+ //#endregion
6
25
  //#region src/expression-builder.ts
7
26
  const attrTypes = [
8
27
  "S",
@@ -225,6 +244,13 @@ var Repo = class {
225
244
  get tableName() {
226
245
  return `${this.db.config?.tableNamePrefix ?? ""}${this.table.def.name}`;
227
246
  }
247
+ get resourceName() {
248
+ if (this.config.resourceName) return this.config.resourceName;
249
+ const clsName = this.constructor.name;
250
+ if (clsName && clsName !== "Repo") return clsName.replace(/Repo$/i, "") || clsName;
251
+ const t = this.table.def.name;
252
+ return t.charAt(0).toUpperCase() + t.slice(1);
253
+ }
228
254
  get defaultPutData() {
229
255
  return this.config.defaultPutData?.() ?? {};
230
256
  }
@@ -257,6 +283,7 @@ var Repo = class {
257
283
  const item = await this.db.getOrThrow({
258
284
  table: this.tableName,
259
285
  key: this.extractKey(key),
286
+ resource: this.resourceName,
260
287
  ...options
261
288
  });
262
289
  return this.applyTransformIfNeeded(item, options);
@@ -266,6 +293,7 @@ var Repo = class {
266
293
  const result = await this.db.put({
267
294
  table: this.tableName,
268
295
  item: itemWithDefaults,
296
+ resource: this.resourceName,
269
297
  ...options
270
298
  });
271
299
  return this.applyTransformIfNeeded(result);
@@ -278,6 +306,7 @@ var Repo = class {
278
306
  const result = await this.db.update({
279
307
  table: this.tableName,
280
308
  key: this.extractKey(key),
309
+ resource: this.resourceName,
281
310
  update: updateWithDefaults,
282
311
  ...options
283
312
  });
@@ -296,6 +325,7 @@ var Repo = class {
296
325
  const item = await this.db.delete({
297
326
  table: this.tableName,
298
327
  key: this.extractKey(key),
328
+ resource: this.resourceName,
299
329
  ...options
300
330
  });
301
331
  return item && this.applyTransformIfNeeded(item);
@@ -304,6 +334,7 @@ var Repo = class {
304
334
  const item = await this.db.deleteOrThrow({
305
335
  table: this.tableName,
306
336
  key: this.extractKey(key),
337
+ resource: this.resourceName,
307
338
  ...options
308
339
  });
309
340
  return this.applyTransformIfNeeded(item);
@@ -409,6 +440,7 @@ var Repo = class {
409
440
  async batchGetOrThrow(keys, options) {
410
441
  const result = await this.db.batchGetOrThrow({ [this.tableName]: {
411
442
  keys: keys.map((key) => this.extractKey(key)),
443
+ resource: this.resourceName,
412
444
  ...options
413
445
  } });
414
446
  return this.applyTransformsIfNeeded(result[this.tableName] ?? [], options);
@@ -450,6 +482,7 @@ var Repo = class {
450
482
  const items = await this.db.trxGetOrThrow(...keys.map((key) => ({
451
483
  table: this.tableName,
452
484
  key: this.extractKey(key),
485
+ resource: this.resourceName,
453
486
  ...options
454
487
  })));
455
488
  return this.applyTransformsIfNeeded(items, options);
@@ -657,7 +690,11 @@ var Db = class {
657
690
  }
658
691
  async getOrThrow(data) {
659
692
  const item = await this.get(data);
660
- if (!item) throw new Error(`Item not found in "${data.table}" table.`);
693
+ if (!item) throw new DinahError({
694
+ type: "NOT_FOUND",
695
+ key: data.key,
696
+ resource: data.resource
697
+ });
661
698
  return item;
662
699
  }
663
700
  async put(data) {
@@ -672,8 +709,16 @@ var Db = class {
672
709
  ExpressionAttributeNames: exp.attributeNames,
673
710
  ExpressionAttributeValues: exp.attributeValues
674
711
  });
675
- const output = await this.client.send(input);
676
- return data.returnOld ? output.Attributes : item;
712
+ try {
713
+ const output = await this.client.send(input);
714
+ return data.returnOld ? output.Attributes : item;
715
+ } catch (err) {
716
+ if (err instanceof _aws_sdk_client_dynamodb.ConditionalCheckFailedException) throw new DinahError({
717
+ type: "CONDITIONAL_CHECK_FAILED",
718
+ resource: data.resource
719
+ }, { cause: err });
720
+ throw err;
721
+ }
677
722
  }
678
723
  async update(data) {
679
724
  const exp = new ExpressionBuilder();
@@ -689,7 +734,16 @@ var Db = class {
689
734
  ExpressionAttributeNames: exp.attributeNames,
690
735
  ExpressionAttributeValues: exp.attributeValues
691
736
  });
692
- return (await this.client.send(input)).Attributes;
737
+ try {
738
+ return (await this.client.send(input)).Attributes;
739
+ } catch (err) {
740
+ if (err instanceof _aws_sdk_client_dynamodb.ConditionalCheckFailedException) throw new DinahError({
741
+ type: "CONDITIONAL_CHECK_FAILED",
742
+ key: data.key,
743
+ resource: data.resource
744
+ }, { cause: err });
745
+ throw err;
746
+ }
693
747
  }
694
748
  async delete(data) {
695
749
  const exp = new ExpressionBuilder();
@@ -702,11 +756,24 @@ var Db = class {
702
756
  ExpressionAttributeNames: exp.attributeNames,
703
757
  ExpressionAttributeValues: exp.attributeValues
704
758
  });
705
- return (await this.client.send(input)).Attributes;
759
+ try {
760
+ return (await this.client.send(input)).Attributes;
761
+ } catch (err) {
762
+ if (err instanceof _aws_sdk_client_dynamodb.ConditionalCheckFailedException) throw new DinahError({
763
+ type: "CONDITIONAL_CHECK_FAILED",
764
+ key: data.key,
765
+ resource: data.resource
766
+ }, { cause: err });
767
+ throw err;
768
+ }
706
769
  }
707
770
  async deleteOrThrow(data) {
708
771
  const item = await this.delete(data);
709
- if (!item) throw new Error(`Item not found in "${data.table}" table.`);
772
+ if (!item) throw new DinahError({
773
+ type: "NOT_FOUND",
774
+ key: data.key,
775
+ resource: data.resource
776
+ });
710
777
  return item;
711
778
  }
712
779
  async *queryPaged(data) {
@@ -863,7 +930,11 @@ var Db = class {
863
930
  const { items, unprocessed } = await this.batchGet(data);
864
931
  for (const table of Object.keys(data)) {
865
932
  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 Error(`One or more items were not found in "${table}" table.`);
933
+ if (items[table]?.length !== data[table]?.keys?.length) throw new DinahError({
934
+ type: "NOT_FOUND",
935
+ key: {},
936
+ resource: data[table]?.resource
937
+ });
867
938
  }
868
939
  return items;
869
940
  }
@@ -983,7 +1054,11 @@ var Db = class {
983
1054
  }
984
1055
  async trxGetOrThrow(...requests) {
985
1056
  const items = await this.trxGet(...requests);
986
- 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.`);
1057
+ for (let i = 0; i < items.length; i++) if (!items[i]) throw new DinahError({
1058
+ type: "NOT_FOUND",
1059
+ key: requests[i]?.key ?? {},
1060
+ resource: requests[i]?.resource
1061
+ });
987
1062
  return items;
988
1063
  }
989
1064
  async trxWrite(...requests) {
@@ -1013,7 +1088,18 @@ var Db = class {
1013
1088
  } };
1014
1089
  });
1015
1090
  const input = new _aws_sdk_lib_dynamodb.TransactWriteCommand({ TransactItems: trxItems });
1016
- await this.client.send(input);
1091
+ try {
1092
+ await this.client.send(input);
1093
+ } catch (err) {
1094
+ if (err instanceof _aws_sdk_client_dynamodb.TransactionCanceledException) throw new DinahError({
1095
+ type: "TRANSACTION_CANCELED",
1096
+ reasons: (err.CancellationReasons ?? []).map((r) => ({
1097
+ type: r.Code ?? "Unknown",
1098
+ message: r.Message
1099
+ }))
1100
+ }, { cause: err });
1101
+ throw err;
1102
+ }
1017
1103
  }
1018
1104
  };
1019
1105
  //#endregion
@@ -1028,10 +1114,12 @@ var Table = class {
1028
1114
  };
1029
1115
  //#endregion
1030
1116
  exports.Db = Db;
1117
+ exports.DinahError = DinahError;
1031
1118
  exports.Repo = Repo;
1032
1119
  exports.Table = Table;
1033
1120
  exports.chunk = require_util.chunk;
1034
1121
  exports.extractTableDesc = require_util.extractTableDesc;
1122
+ exports.isDinahError = isDinahError;
1035
1123
  exports.makeRepo = makeRepo;
1036
1124
  exports.removeUndefined = require_util.removeUndefined;
1037
1125
  exports.resolveAttrType = require_util.resolveAttrType;