dyno-table 1.5.0 → 1.7.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.
Files changed (72) hide show
  1. package/README.md +368 -186
  2. package/dist/batch-builder-DNsz6zvh.d.cts +398 -0
  3. package/dist/batch-builder-Dz1yPGrJ.d.ts +398 -0
  4. package/dist/builders/condition-check-builder.cjs +0 -13
  5. package/dist/builders/condition-check-builder.cjs.map +1 -1
  6. package/dist/builders/condition-check-builder.d.cts +0 -13
  7. package/dist/builders/condition-check-builder.d.ts +0 -13
  8. package/dist/builders/condition-check-builder.js +0 -13
  9. package/dist/builders/condition-check-builder.js.map +1 -1
  10. package/dist/builders/delete-builder.cjs +38 -0
  11. package/dist/builders/delete-builder.cjs.map +1 -1
  12. package/dist/builders/delete-builder.d.cts +36 -0
  13. package/dist/builders/delete-builder.d.ts +36 -0
  14. package/dist/builders/delete-builder.js +38 -0
  15. package/dist/builders/delete-builder.js.map +1 -1
  16. package/dist/builders/paginator.cjs +0 -24
  17. package/dist/builders/paginator.cjs.map +1 -1
  18. package/dist/builders/paginator.d.cts +0 -24
  19. package/dist/builders/paginator.d.ts +0 -24
  20. package/dist/builders/paginator.js +0 -24
  21. package/dist/builders/paginator.js.map +1 -1
  22. package/dist/builders/put-builder.cjs +39 -8
  23. package/dist/builders/put-builder.cjs.map +1 -1
  24. package/dist/builders/put-builder.d.cts +37 -8
  25. package/dist/builders/put-builder.d.ts +37 -8
  26. package/dist/builders/put-builder.js +39 -8
  27. package/dist/builders/put-builder.js.map +1 -1
  28. package/dist/builders/query-builder.cjs +0 -53
  29. package/dist/builders/query-builder.cjs.map +1 -1
  30. package/dist/builders/query-builder.d.cts +1 -1
  31. package/dist/builders/query-builder.d.ts +1 -1
  32. package/dist/builders/query-builder.js +0 -53
  33. package/dist/builders/query-builder.js.map +1 -1
  34. package/dist/builders/transaction-builder.cjs +0 -47
  35. package/dist/builders/transaction-builder.cjs.map +1 -1
  36. package/dist/builders/transaction-builder.d.cts +0 -47
  37. package/dist/builders/transaction-builder.d.ts +0 -47
  38. package/dist/builders/transaction-builder.js +0 -47
  39. package/dist/builders/transaction-builder.js.map +1 -1
  40. package/dist/builders/update-builder.cjs +2 -2
  41. package/dist/builders/update-builder.cjs.map +1 -1
  42. package/dist/builders/update-builder.d.cts +2 -2
  43. package/dist/builders/update-builder.d.ts +2 -2
  44. package/dist/builders/update-builder.js +2 -2
  45. package/dist/builders/update-builder.js.map +1 -1
  46. package/dist/conditions.cjs.map +1 -1
  47. package/dist/conditions.js.map +1 -1
  48. package/dist/entity.cjs +162 -86
  49. package/dist/entity.cjs.map +1 -1
  50. package/dist/entity.d.cts +39 -15
  51. package/dist/entity.d.ts +39 -15
  52. package/dist/entity.js +162 -86
  53. package/dist/entity.js.map +1 -1
  54. package/dist/index.cjs +623 -231
  55. package/dist/index.cjs.map +1 -1
  56. package/dist/index.d.cts +3 -2
  57. package/dist/index.d.ts +3 -2
  58. package/dist/index.js +622 -232
  59. package/dist/index.js.map +1 -1
  60. package/dist/{query-builder-CbHvimBk.d.cts → query-builder-BDuHHrb-.d.cts} +0 -34
  61. package/dist/{query-builder-BhrR31oO.d.ts → query-builder-C6XjVEFH.d.ts} +0 -34
  62. package/dist/{table-Des8C2od.d.ts → table-BWa4tx63.d.ts} +39 -151
  63. package/dist/{table-CY9byPEg.d.cts → table-DAKlzQsK.d.cts} +39 -151
  64. package/dist/table.cjs +459 -145
  65. package/dist/table.cjs.map +1 -1
  66. package/dist/table.d.cts +3 -2
  67. package/dist/table.d.ts +3 -2
  68. package/dist/table.js +459 -145
  69. package/dist/table.js.map +1 -1
  70. package/dist/utils.cjs.map +1 -1
  71. package/dist/utils.js.map +1 -1
  72. package/package.json +1 -1
package/dist/entity.js CHANGED
@@ -6,9 +6,55 @@ var createComparisonCondition = (type) => (attr, value) => ({
6
6
  });
7
7
  var eq = createComparisonCondition("eq");
8
8
 
9
+ // src/builders/entity-aware-builders.ts
10
+ function createEntityAwareBuilder(builder, entityName) {
11
+ return new Proxy(builder, {
12
+ get(target, prop, receiver) {
13
+ if (prop === "entityName") {
14
+ return entityName;
15
+ }
16
+ if (prop === "withBatch" && typeof target[prop] === "function") {
17
+ return (batch, entityType) => {
18
+ const typeToUse = entityType ?? entityName;
19
+ const fn = target[prop];
20
+ return fn.call(target, batch, typeToUse);
21
+ };
22
+ }
23
+ return Reflect.get(target, prop, receiver);
24
+ }
25
+ });
26
+ }
27
+ function createEntityAwarePutBuilder(builder, entityName) {
28
+ return createEntityAwareBuilder(builder, entityName);
29
+ }
30
+ function createEntityAwareGetBuilder(builder, entityName) {
31
+ return createEntityAwareBuilder(builder, entityName);
32
+ }
33
+ function createEntityAwareDeleteBuilder(builder, entityName) {
34
+ return createEntityAwareBuilder(builder, entityName);
35
+ }
36
+
9
37
  // src/entity.ts
10
38
  function defineEntity(config) {
11
39
  const entityTypeAttributeName = config.settings?.entityTypeAttributeName ?? "entityType";
40
+ const wrapMethodWithPreparation = (originalMethod, prepareFn, context) => {
41
+ const wrappedMethod = (...args) => {
42
+ prepareFn();
43
+ return originalMethod.call(context, ...args);
44
+ };
45
+ Object.setPrototypeOf(wrappedMethod, originalMethod);
46
+ const propertyNames = Object.getOwnPropertyNames(originalMethod);
47
+ for (let i = 0; i < propertyNames.length; i++) {
48
+ const prop = propertyNames[i];
49
+ if (prop !== "length" && prop !== "name" && prop !== "prototype") {
50
+ const descriptor = Object.getOwnPropertyDescriptor(originalMethod, prop);
51
+ if (descriptor && descriptor.writable !== false && !descriptor.get) {
52
+ wrappedMethod[prop] = originalMethod[prop];
53
+ }
54
+ }
55
+ }
56
+ return wrappedMethod;
57
+ };
12
58
  const generateTimestamps = (timestampTypes) => {
13
59
  if (!config.settings?.timestamps) return {};
14
60
  const timestamps = {};
@@ -31,39 +77,33 @@ function defineEntity(config) {
31
77
  createRepository: (table) => {
32
78
  const repository = {
33
79
  create: (data) => {
34
- const primaryKey = config.primaryKey.generateKey(data);
35
- const indexes = Object.entries(config.indexes ?? {}).reduce(
36
- (acc, [indexName, index]) => {
37
- const key = index.generateKey(data);
38
- const gsiConfig = table.gsis[indexName];
39
- if (!gsiConfig) {
40
- throw new Error(`GSI configuration not found for index: ${indexName}`);
41
- }
42
- if (key.pk) {
43
- acc[gsiConfig.partitionKey] = key.pk;
44
- }
45
- if (key.sk && gsiConfig.sortKey) {
46
- acc[gsiConfig.sortKey] = key.sk;
47
- }
48
- return acc;
49
- },
50
- {}
51
- );
52
- const builder = table.create({
53
- ...data,
54
- [entityTypeAttributeName]: config.name,
55
- [table.partitionKey]: primaryKey.pk,
56
- ...table.sortKey ? { [table.sortKey]: primaryKey.sk } : {},
57
- ...indexes,
58
- ...generateTimestamps(["createdAt", "updatedAt"])
59
- });
80
+ const builder = table.create({});
60
81
  const prepareValidatedItemAsync = async () => {
61
- const validationResult = await config.schema["~standard"].validate(data);
62
- if ("issues" in validationResult && validationResult.issues) {
63
- throw new Error(`Validation failed: ${validationResult.issues.map((i) => i.message).join(", ")}`);
82
+ const validationResult = config.schema["~standard"].validate(data);
83
+ const validatedData = validationResult instanceof Promise ? await validationResult : validationResult;
84
+ if ("issues" in validatedData && validatedData.issues) {
85
+ throw new Error(`Validation failed: ${validatedData.issues.map((i) => i.message).join(", ")}`);
64
86
  }
87
+ const primaryKey = config.primaryKey.generateKey(validatedData.value);
88
+ const indexes = Object.entries(config.indexes ?? {}).reduce(
89
+ (acc, [indexName, index]) => {
90
+ const key = index.generateKey(validatedData.value);
91
+ const gsiConfig = table.gsis[indexName];
92
+ if (!gsiConfig) {
93
+ throw new Error(`GSI configuration not found for index: ${indexName}`);
94
+ }
95
+ if (key.pk) {
96
+ acc[gsiConfig.partitionKey] = key.pk;
97
+ }
98
+ if (key.sk && gsiConfig.sortKey) {
99
+ acc[gsiConfig.sortKey] = key.sk;
100
+ }
101
+ return acc;
102
+ },
103
+ {}
104
+ );
65
105
  const validatedItem = {
66
- ...validationResult.value,
106
+ ...validatedData.value,
67
107
  [entityTypeAttributeName]: config.name,
68
108
  [table.partitionKey]: primaryKey.pk,
69
109
  ...table.sortKey ? { [table.sortKey]: primaryKey.sk } : {},
@@ -76,11 +116,31 @@ function defineEntity(config) {
76
116
  const prepareValidatedItemSync = () => {
77
117
  const validationResult = config.schema["~standard"].validate(data);
78
118
  if (validationResult instanceof Promise) {
79
- throw new Error("Async validation is not supported in withTransaction. Use execute() instead.");
119
+ throw new Error(
120
+ "Async validation is not supported in create method. The schema must support synchronous validation for transaction compatibility."
121
+ );
80
122
  }
81
123
  if ("issues" in validationResult && validationResult.issues) {
82
124
  throw new Error(`Validation failed: ${validationResult.issues.map((i) => i.message).join(", ")}`);
83
125
  }
126
+ const primaryKey = config.primaryKey.generateKey(validationResult.value);
127
+ const indexes = Object.entries(config.indexes ?? {}).reduce(
128
+ (acc, [indexName, index]) => {
129
+ const key = index.generateKey(validationResult.value);
130
+ const gsiConfig = table.gsis[indexName];
131
+ if (!gsiConfig) {
132
+ throw new Error(`GSI configuration not found for index: ${indexName}`);
133
+ }
134
+ if (key.pk) {
135
+ acc[gsiConfig.partitionKey] = key.pk;
136
+ }
137
+ if (key.sk && gsiConfig.sortKey) {
138
+ acc[gsiConfig.sortKey] = key.sk;
139
+ }
140
+ return acc;
141
+ },
142
+ {}
143
+ );
84
144
  const validatedItem = {
85
145
  ...validationResult.value,
86
146
  [entityTypeAttributeName]: config.name,
@@ -99,45 +159,50 @@ function defineEntity(config) {
99
159
  };
100
160
  const originalWithTransaction = builder.withTransaction;
101
161
  if (originalWithTransaction) {
102
- const wrappedWithTransaction = (transaction) => {
103
- prepareValidatedItemSync();
104
- return originalWithTransaction.call(builder, transaction);
105
- };
106
- Object.setPrototypeOf(wrappedWithTransaction, originalWithTransaction);
107
- const propertyNames = Object.getOwnPropertyNames(originalWithTransaction);
108
- for (let i = 0; i < propertyNames.length; i++) {
109
- const prop = propertyNames[i];
110
- if (prop !== "length" && prop !== "name" && prop !== "prototype") {
111
- try {
112
- wrappedWithTransaction[prop] = originalWithTransaction[prop];
113
- } catch (e) {
114
- }
115
- }
116
- }
117
- builder.withTransaction = wrappedWithTransaction;
162
+ builder.withTransaction = wrapMethodWithPreparation(
163
+ originalWithTransaction,
164
+ prepareValidatedItemSync,
165
+ builder
166
+ );
118
167
  }
119
- return builder;
168
+ const originalWithBatch = builder.withBatch;
169
+ if (originalWithBatch) {
170
+ builder.withBatch = wrapMethodWithPreparation(originalWithBatch, prepareValidatedItemSync, builder);
171
+ }
172
+ return createEntityAwarePutBuilder(builder, config.name);
120
173
  },
121
174
  upsert: (data) => {
122
- const primaryKey = config.primaryKey.generateKey(data);
123
- const builder = table.put({
124
- [table.partitionKey]: primaryKey.pk,
125
- ...table.sortKey ? { [table.sortKey]: primaryKey.sk } : {},
126
- ...data,
127
- [entityTypeAttributeName]: config.name,
128
- ...generateTimestamps(["createdAt", "updatedAt"])
129
- });
175
+ const builder = table.put({});
130
176
  const prepareValidatedItemAsync = async () => {
131
- const validationResult = await config.schema["~standard"].validate(data);
132
- if ("issues" in validationResult && validationResult.issues) {
133
- throw new Error(`Validation failed: ${validationResult.issues.map((i) => i.message).join(", ")}`);
177
+ const validationResult = config.schema["~standard"].validate(data);
178
+ const validatedData = validationResult instanceof Promise ? await validationResult : validationResult;
179
+ if ("issues" in validatedData && validatedData.issues) {
180
+ throw new Error(`Validation failed: ${validatedData.issues.map((i) => i.message).join(", ")}`);
134
181
  }
135
- const primaryKey2 = config.primaryKey.generateKey(validationResult.value);
182
+ const primaryKey = config.primaryKey.generateKey(validatedData.value);
183
+ const indexes = Object.entries(config.indexes ?? {}).reduce(
184
+ (acc, [indexName, index]) => {
185
+ const key = index.generateKey(validatedData.value);
186
+ const gsiConfig = table.gsis[indexName];
187
+ if (!gsiConfig) {
188
+ throw new Error(`GSI configuration not found for index: ${indexName}`);
189
+ }
190
+ if (key.pk) {
191
+ acc[gsiConfig.partitionKey] = key.pk;
192
+ }
193
+ if (key.sk && gsiConfig.sortKey) {
194
+ acc[gsiConfig.sortKey] = key.sk;
195
+ }
196
+ return acc;
197
+ },
198
+ {}
199
+ );
136
200
  const validatedItem = {
137
- [table.partitionKey]: primaryKey2.pk,
138
- ...table.sortKey ? { [table.sortKey]: primaryKey2.sk } : {},
139
- ...validationResult.value,
201
+ [table.partitionKey]: primaryKey.pk,
202
+ ...table.sortKey ? { [table.sortKey]: primaryKey.sk } : {},
203
+ ...validatedData.value,
140
204
  [entityTypeAttributeName]: config.name,
205
+ ...indexes,
141
206
  ...generateTimestamps(["createdAt", "updatedAt"])
142
207
  };
143
208
  Object.assign(builder, { item: validatedItem });
@@ -151,12 +216,30 @@ function defineEntity(config) {
151
216
  if ("issues" in validationResult && validationResult.issues) {
152
217
  throw new Error(`Validation failed: ${validationResult.issues.map((i) => i.message).join(", ")}`);
153
218
  }
154
- const primaryKey2 = config.primaryKey.generateKey(validationResult.value);
219
+ const primaryKey = config.primaryKey.generateKey(validationResult.value);
220
+ const indexes = Object.entries(config.indexes ?? {}).reduce(
221
+ (acc, [indexName, index]) => {
222
+ const key = index.generateKey(validationResult.value);
223
+ const gsiConfig = table.gsis[indexName];
224
+ if (!gsiConfig) {
225
+ throw new Error(`GSI configuration not found for index: ${indexName}`);
226
+ }
227
+ if (key.pk) {
228
+ acc[gsiConfig.partitionKey] = key.pk;
229
+ }
230
+ if (key.sk && gsiConfig.sortKey) {
231
+ acc[gsiConfig.sortKey] = key.sk;
232
+ }
233
+ return acc;
234
+ },
235
+ {}
236
+ );
155
237
  const validatedItem = {
156
- [table.partitionKey]: primaryKey2.pk,
157
- ...table.sortKey ? { [table.sortKey]: primaryKey2.sk } : {},
238
+ [table.partitionKey]: primaryKey.pk,
239
+ ...table.sortKey ? { [table.sortKey]: primaryKey.sk } : {},
158
240
  ...validationResult.value,
159
241
  [entityTypeAttributeName]: config.name,
242
+ ...indexes,
160
243
  ...generateTimestamps(["createdAt", "updatedAt"])
161
244
  };
162
245
  Object.assign(builder, { item: validatedItem });
@@ -173,26 +256,19 @@ function defineEntity(config) {
173
256
  };
174
257
  const originalWithTransaction = builder.withTransaction;
175
258
  if (originalWithTransaction) {
176
- const wrappedWithTransaction = (transaction) => {
177
- prepareValidatedItemSync();
178
- return originalWithTransaction.call(builder, transaction);
179
- };
180
- Object.setPrototypeOf(wrappedWithTransaction, originalWithTransaction);
181
- const propertyNames = Object.getOwnPropertyNames(originalWithTransaction);
182
- for (let i = 0; i < propertyNames.length; i++) {
183
- const prop = propertyNames[i];
184
- if (prop !== "length" && prop !== "name" && prop !== "prototype") {
185
- try {
186
- wrappedWithTransaction[prop] = originalWithTransaction[prop];
187
- } catch (e) {
188
- }
189
- }
190
- }
191
- builder.withTransaction = wrappedWithTransaction;
259
+ builder.withTransaction = wrapMethodWithPreparation(
260
+ originalWithTransaction,
261
+ prepareValidatedItemSync,
262
+ builder
263
+ );
192
264
  }
193
- return builder;
265
+ const originalWithBatch = builder.withBatch;
266
+ if (originalWithBatch) {
267
+ builder.withBatch = wrapMethodWithPreparation(originalWithBatch, prepareValidatedItemSync, builder);
268
+ }
269
+ return createEntityAwarePutBuilder(builder, config.name);
194
270
  },
195
- get: (key) => table.get(config.primaryKey.generateKey(key)),
271
+ get: (key) => createEntityAwareGetBuilder(table.get(config.primaryKey.generateKey(key)), config.name),
196
272
  update: (key, data) => {
197
273
  const primaryKeyObj = config.primaryKey.generateKey(key);
198
274
  const builder = table.update(primaryKeyObj);
@@ -204,13 +280,13 @@ function defineEntity(config) {
204
280
  delete: (key) => {
205
281
  const builder = table.delete(config.primaryKey.generateKey(key));
206
282
  builder.condition(eq(entityTypeAttributeName, config.name));
207
- return builder;
283
+ return createEntityAwareDeleteBuilder(builder, config.name);
208
284
  },
209
285
  query: Object.entries(config.queries || {}).reduce((acc, [key, inputCallback]) => {
210
286
  acc[key] = (input) => {
211
287
  const queryEntity = {
212
288
  scan: repository.scan,
213
- get: (key2) => table.get(key2),
289
+ get: (key2) => createEntityAwareGetBuilder(table.get(key2), config.name),
214
290
  query: (keyCondition) => {
215
291
  return table.query(keyCondition);
216
292
  }