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.
- package/README.md +368 -186
- package/dist/batch-builder-DNsz6zvh.d.cts +398 -0
- package/dist/batch-builder-Dz1yPGrJ.d.ts +398 -0
- package/dist/builders/condition-check-builder.cjs +0 -13
- package/dist/builders/condition-check-builder.cjs.map +1 -1
- package/dist/builders/condition-check-builder.d.cts +0 -13
- package/dist/builders/condition-check-builder.d.ts +0 -13
- package/dist/builders/condition-check-builder.js +0 -13
- package/dist/builders/condition-check-builder.js.map +1 -1
- package/dist/builders/delete-builder.cjs +38 -0
- package/dist/builders/delete-builder.cjs.map +1 -1
- package/dist/builders/delete-builder.d.cts +36 -0
- package/dist/builders/delete-builder.d.ts +36 -0
- package/dist/builders/delete-builder.js +38 -0
- package/dist/builders/delete-builder.js.map +1 -1
- package/dist/builders/paginator.cjs +0 -24
- package/dist/builders/paginator.cjs.map +1 -1
- package/dist/builders/paginator.d.cts +0 -24
- package/dist/builders/paginator.d.ts +0 -24
- package/dist/builders/paginator.js +0 -24
- package/dist/builders/paginator.js.map +1 -1
- package/dist/builders/put-builder.cjs +39 -8
- package/dist/builders/put-builder.cjs.map +1 -1
- package/dist/builders/put-builder.d.cts +37 -8
- package/dist/builders/put-builder.d.ts +37 -8
- package/dist/builders/put-builder.js +39 -8
- package/dist/builders/put-builder.js.map +1 -1
- package/dist/builders/query-builder.cjs +0 -53
- package/dist/builders/query-builder.cjs.map +1 -1
- package/dist/builders/query-builder.d.cts +1 -1
- package/dist/builders/query-builder.d.ts +1 -1
- package/dist/builders/query-builder.js +0 -53
- package/dist/builders/query-builder.js.map +1 -1
- package/dist/builders/transaction-builder.cjs +0 -47
- package/dist/builders/transaction-builder.cjs.map +1 -1
- package/dist/builders/transaction-builder.d.cts +0 -47
- package/dist/builders/transaction-builder.d.ts +0 -47
- package/dist/builders/transaction-builder.js +0 -47
- package/dist/builders/transaction-builder.js.map +1 -1
- package/dist/builders/update-builder.cjs +2 -2
- package/dist/builders/update-builder.cjs.map +1 -1
- package/dist/builders/update-builder.d.cts +2 -2
- package/dist/builders/update-builder.d.ts +2 -2
- package/dist/builders/update-builder.js +2 -2
- package/dist/builders/update-builder.js.map +1 -1
- package/dist/conditions.cjs.map +1 -1
- package/dist/conditions.js.map +1 -1
- package/dist/entity.cjs +162 -86
- package/dist/entity.cjs.map +1 -1
- package/dist/entity.d.cts +39 -15
- package/dist/entity.d.ts +39 -15
- package/dist/entity.js +162 -86
- package/dist/entity.js.map +1 -1
- package/dist/index.cjs +623 -231
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +622 -232
- package/dist/index.js.map +1 -1
- package/dist/{query-builder-CbHvimBk.d.cts → query-builder-BDuHHrb-.d.cts} +0 -34
- package/dist/{query-builder-BhrR31oO.d.ts → query-builder-C6XjVEFH.d.ts} +0 -34
- package/dist/{table-Des8C2od.d.ts → table-BWa4tx63.d.ts} +39 -151
- package/dist/{table-CY9byPEg.d.cts → table-DAKlzQsK.d.cts} +39 -151
- package/dist/table.cjs +459 -145
- package/dist/table.cjs.map +1 -1
- package/dist/table.d.cts +3 -2
- package/dist/table.d.ts +3 -2
- package/dist/table.js +459 -145
- package/dist/table.js.map +1 -1
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.js.map +1 -1
- 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
|
|
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 =
|
|
62
|
-
|
|
63
|
-
|
|
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
|
-
...
|
|
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(
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
132
|
-
|
|
133
|
-
|
|
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
|
|
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]:
|
|
138
|
-
...table.sortKey ? { [table.sortKey]:
|
|
139
|
-
...
|
|
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
|
|
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]:
|
|
157
|
-
...table.sortKey ? { [table.sortKey]:
|
|
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
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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
|
-
|
|
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
|
}
|