@ftschopp/dynatable-core 1.0.0 → 1.2.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/CHANGELOG.md +19 -0
- package/README.md +528 -2
- package/dist/builders/delete/types.d.ts +6 -1
- package/dist/builders/delete/types.d.ts.map +1 -1
- package/dist/builders/get/types.d.ts +6 -1
- package/dist/builders/get/types.d.ts.map +1 -1
- package/dist/builders/put/types.d.ts +6 -1
- package/dist/builders/put/types.d.ts.map +1 -1
- package/dist/builders/query/create-query-builder.d.ts +1 -1
- package/dist/builders/query/create-query-builder.d.ts.map +1 -1
- package/dist/builders/query/types.d.ts +9 -10
- package/dist/builders/query/types.d.ts.map +1 -1
- package/dist/builders/transact-write/create-transact-write-builder.d.ts.map +1 -1
- package/dist/builders/transact-write/create-transact-write-builder.js +1 -1
- package/dist/builders/transact-write/types.d.ts +33 -6
- package/dist/builders/transact-write/types.d.ts.map +1 -1
- package/dist/builders/update/create-update-builder.d.ts.map +1 -1
- package/dist/builders/update/create-update-builder.js +30 -9
- package/dist/builders/update/types.d.ts +8 -2
- package/dist/builders/update/types.d.ts.map +1 -1
- package/dist/core/types.d.ts +96 -11
- package/dist/core/types.d.ts.map +1 -1
- package/dist/entity/create-entity-api.d.ts +15 -0
- package/dist/entity/create-entity-api.d.ts.map +1 -0
- package/dist/entity/create-entity-api.js +124 -0
- package/dist/entity/index.d.ts +12 -0
- package/dist/entity/index.d.ts.map +1 -0
- package/dist/entity/index.js +18 -0
- package/dist/entity/middleware/factories.d.ts +6 -0
- package/dist/entity/middleware/factories.d.ts.map +1 -0
- package/dist/entity/middleware/factories.js +15 -0
- package/dist/entity/middleware/types.d.ts +8 -0
- package/dist/entity/middleware/types.d.ts.map +1 -0
- package/dist/entity/middleware/types.js +2 -0
- package/dist/entity/middleware/with-middleware.d.ts +8 -0
- package/dist/entity/middleware/with-middleware.d.ts.map +1 -0
- package/dist/entity/middleware/with-middleware.js +29 -0
- package/dist/{entity.d.ts → entity/types.d.ts} +6 -17
- package/dist/entity/types.d.ts.map +1 -0
- package/dist/entity/types.js +2 -0
- package/dist/entity/validation/key-validation.d.ts +7 -0
- package/dist/entity/validation/key-validation.d.ts.map +1 -0
- package/dist/entity/validation/key-validation.js +25 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/table.d.ts +8 -1
- package/dist/table.d.ts.map +1 -1
- package/dist/table.js +1 -0
- package/dist/utils/model-utils.d.ts +7 -1
- package/dist/utils/model-utils.d.ts.map +1 -1
- package/dist/utils/model-utils.js +32 -3
- package/dist/utils/zod-utils.d.ts +3 -2
- package/dist/utils/zod-utils.d.ts.map +1 -1
- package/dist/utils/zod-utils.js +33 -11
- package/package.json +3 -2
- package/src/builders/README.md +68 -1
- package/src/builders/delete/types.ts +7 -1
- package/src/builders/get/types.ts +7 -1
- package/src/builders/put/types.ts +7 -1
- package/src/builders/query/create-query-builder.ts +4 -6
- package/src/builders/query/types.ts +9 -12
- package/src/builders/transact-write/README.md +37 -1
- package/src/builders/transact-write/create-transact-write-builder.ts +20 -14
- package/src/builders/transact-write/types.ts +44 -6
- package/src/builders/update/create-update-builder.test.ts +43 -0
- package/src/builders/update/create-update-builder.ts +47 -9
- package/src/builders/update/types.ts +9 -2
- package/src/core/types.test.ts +137 -0
- package/src/core/types.ts +97 -20
- package/src/entity/create-entity-api.ts +212 -0
- package/src/entity/index.ts +19 -0
- package/src/entity/middleware/factories.ts +15 -0
- package/src/entity/middleware/types.ts +7 -0
- package/src/entity/middleware/with-middleware.ts +37 -0
- package/src/entity/types.ts +79 -0
- package/src/entity/validation/key-validation.ts +34 -0
- package/src/index.ts +1 -0
- package/src/table.ts +10 -3
- package/src/utils/model-utils.test.ts +131 -1
- package/src/utils/model-utils.ts +35 -2
- package/src/utils/zod-utils.test.ts +97 -2
- package/src/utils/zod-utils.ts +31 -12
- package/dist/entity.d.ts.map +0 -1
- package/dist/entity.js +0 -161
- package/src/entity.ts +0 -337
package/src/entity.ts
DELETED
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
2
|
-
import { InferInput, InferKeyInput, InferModel, ModelDefinition } from './core/types';
|
|
3
|
-
import { applyPostDefaults, resolveKeys, extractTemplateVars } from './utils/model-utils';
|
|
4
|
-
import { modelToZod } from './utils/zod-utils';
|
|
5
|
-
import {
|
|
6
|
-
createGetBuilder,
|
|
7
|
-
createPutBuilder,
|
|
8
|
-
createQueryBuilder,
|
|
9
|
-
createUpdateBuilder,
|
|
10
|
-
createDeleteBuilder,
|
|
11
|
-
createScanBuilder,
|
|
12
|
-
createBatchGetBuilder,
|
|
13
|
-
createBatchWriteBuilder,
|
|
14
|
-
GetBuilder,
|
|
15
|
-
PutBuilder,
|
|
16
|
-
QueryBuilder,
|
|
17
|
-
UpdateBuilder,
|
|
18
|
-
DeleteBuilder,
|
|
19
|
-
ScanBuilder,
|
|
20
|
-
BatchGetBuilder,
|
|
21
|
-
BatchWriteBuilder,
|
|
22
|
-
WriteRequest,
|
|
23
|
-
} from './builders';
|
|
24
|
-
import { DynamoDBLogger } from './utils/dynamodb-logger';
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Options for creating the Entity API
|
|
28
|
-
*/
|
|
29
|
-
export type EntityAPIOptions = {
|
|
30
|
-
logger?: DynamoDBLogger;
|
|
31
|
-
timestamps?: boolean;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Entity API interface for a model
|
|
36
|
-
*/
|
|
37
|
-
export type EntityAPI<Model, Input, KeyInput, ModelDef extends ModelDefinition = any> = {
|
|
38
|
-
/**
|
|
39
|
-
* Retrieves an item by its key.
|
|
40
|
-
* @param key - Partial or full key object to identify the item
|
|
41
|
-
* @returns GetBuilder configured for the item
|
|
42
|
-
*/
|
|
43
|
-
get: (key: KeyInput) => GetBuilder<KeyInput, Model>;
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Puts an item into the table after validation and applying defaults.
|
|
47
|
-
* @param item - The input data to put
|
|
48
|
-
* @returns PutBuilder configured for the item
|
|
49
|
-
*/
|
|
50
|
-
put: (item: Input) => PutBuilder<Model>;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Queries items using key conditions.
|
|
54
|
-
* @returns QueryBuilder for building and executing the query
|
|
55
|
-
*/
|
|
56
|
-
query: () => QueryBuilder<Model, ModelDef>;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Scans the entire table or index without key conditions.
|
|
60
|
-
* @returns ScanBuilder for building and executing the scan
|
|
61
|
-
*/
|
|
62
|
-
scan: () => ScanBuilder<Model>;
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Updates an item by its key.
|
|
66
|
-
* @param key - Partial or full key object to identify the item
|
|
67
|
-
* @returns UpdateBuilder configured for the item
|
|
68
|
-
*/
|
|
69
|
-
update: (key: KeyInput) => UpdateBuilder<Model>;
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Deletes an item by its key.
|
|
73
|
-
* @param key - Partial or full key object to identify the item
|
|
74
|
-
* @returns DeleteBuilder configured for the item
|
|
75
|
-
*/
|
|
76
|
-
delete: (key: KeyInput) => DeleteBuilder<Model>;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Retrieves multiple items by their keys in a single batch operation.
|
|
80
|
-
* @param keys - Array of key objects to retrieve
|
|
81
|
-
* @returns BatchGetBuilder configured for the items
|
|
82
|
-
*/
|
|
83
|
-
batchGet: (keys: KeyInput[]) => BatchGetBuilder<Model>;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Writes multiple items in a single batch operation (puts or deletes).
|
|
87
|
-
* @param items - Array of items to put
|
|
88
|
-
* @returns BatchWriteBuilder configured for the items
|
|
89
|
-
*/
|
|
90
|
-
batchWrite: (items: Input[]) => BatchWriteBuilder;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Creates an entity API instance with validation, key resolution, and builder creation.
|
|
95
|
-
*
|
|
96
|
-
* @param modelName - The name of the model/entity
|
|
97
|
-
* @param model - The model definition
|
|
98
|
-
* @param client - DynamoDB client instance
|
|
99
|
-
* @param options - Optional configuration (logger, timestamps)
|
|
100
|
-
* @returns EntityAPI with get and put methods
|
|
101
|
-
*/
|
|
102
|
-
export const createEntityAPI = <Model extends ModelDefinition>(
|
|
103
|
-
tableName: string,
|
|
104
|
-
modelName: string,
|
|
105
|
-
model: Model,
|
|
106
|
-
client: DynamoDBClient,
|
|
107
|
-
options: EntityAPIOptions = {}
|
|
108
|
-
): EntityAPI<InferModel<Model>, InferInput<Model>, InferKeyInput<Model>, Model> => {
|
|
109
|
-
const { logger, timestamps = false } = options;
|
|
110
|
-
|
|
111
|
-
// Build a Zod schema from the model
|
|
112
|
-
const zodSchema = modelToZod(model);
|
|
113
|
-
|
|
114
|
-
return {
|
|
115
|
-
get(key) {
|
|
116
|
-
// Extract required fields from key templates
|
|
117
|
-
const requiredFields = new Set<string>();
|
|
118
|
-
if (model.key) {
|
|
119
|
-
for (const keyDef of Object.values(model.key)) {
|
|
120
|
-
extractTemplateVars(keyDef.value).forEach((field) => requiredFields.add(field));
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Check if all required fields are present
|
|
125
|
-
const keyRecord = key as Record<string, unknown>;
|
|
126
|
-
const missingFields = Array.from(requiredFields).filter(
|
|
127
|
-
(field) => keyRecord[field] === undefined
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
if (missingFields.length > 0) {
|
|
131
|
-
throw new Error(
|
|
132
|
-
`[${modelName}] Missing required key field(s) for get(): ${missingFields.join(', ')}. ` +
|
|
133
|
-
`Required fields: ${Array.from(requiredFields).join(', ')}`
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Resolve any key defaults or computed keys
|
|
138
|
-
const fullKey = resolveKeys(model, key);
|
|
139
|
-
|
|
140
|
-
return createGetBuilder<InferKeyInput<Model>, InferModel<Model>>(
|
|
141
|
-
tableName,
|
|
142
|
-
fullKey,
|
|
143
|
-
client,
|
|
144
|
-
undefined,
|
|
145
|
-
logger
|
|
146
|
-
);
|
|
147
|
-
},
|
|
148
|
-
|
|
149
|
-
put(item) {
|
|
150
|
-
// Validate full input data
|
|
151
|
-
const parsed = zodSchema.parse(item);
|
|
152
|
-
|
|
153
|
-
// Apply post-processing defaults from the model (including timestamps for new items)
|
|
154
|
-
const withDefaults = applyPostDefaults(model, parsed, {
|
|
155
|
-
isUpdate: false,
|
|
156
|
-
timestamps,
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
// Resolve keys again with defaults
|
|
160
|
-
const fullKey = resolveKeys(model, withDefaults);
|
|
161
|
-
|
|
162
|
-
// Combine keys and data into full item, adding _type field
|
|
163
|
-
const fullItem = {
|
|
164
|
-
...withDefaults,
|
|
165
|
-
...fullKey,
|
|
166
|
-
_type: modelName, // Add entity type identifier
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
return createPutBuilder(tableName, fullItem, client, [], false, 'NONE', false, logger);
|
|
170
|
-
},
|
|
171
|
-
|
|
172
|
-
query() {
|
|
173
|
-
return createQueryBuilder<InferModel<Model>, Model>(tableName, client, model, logger);
|
|
174
|
-
},
|
|
175
|
-
|
|
176
|
-
scan() {
|
|
177
|
-
return createScanBuilder<InferModel<Model>>(
|
|
178
|
-
tableName,
|
|
179
|
-
client,
|
|
180
|
-
[],
|
|
181
|
-
[],
|
|
182
|
-
undefined,
|
|
183
|
-
false,
|
|
184
|
-
undefined,
|
|
185
|
-
undefined,
|
|
186
|
-
undefined,
|
|
187
|
-
logger
|
|
188
|
-
);
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
update(key) {
|
|
192
|
-
// Extract required fields from key templates
|
|
193
|
-
const requiredFields = new Set<string>();
|
|
194
|
-
if (model.key) {
|
|
195
|
-
for (const keyDef of Object.values(model.key)) {
|
|
196
|
-
extractTemplateVars(keyDef.value).forEach((field) => requiredFields.add(field));
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Check if all required fields are present
|
|
201
|
-
const keyRecord = key as Record<string, unknown>;
|
|
202
|
-
const missingFields = Array.from(requiredFields).filter(
|
|
203
|
-
(field) => keyRecord[field] === undefined
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
if (missingFields.length > 0) {
|
|
207
|
-
throw new Error(
|
|
208
|
-
`[${modelName}] Missing required key field(s) for update(): ${missingFields.join(', ')}. ` +
|
|
209
|
-
`Required fields: ${Array.from(requiredFields).join(', ')}`
|
|
210
|
-
);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Resolve any key defaults or computed keys
|
|
214
|
-
const fullKey = resolveKeys(model, key);
|
|
215
|
-
|
|
216
|
-
return createUpdateBuilder<InferModel<Model>>(
|
|
217
|
-
tableName,
|
|
218
|
-
fullKey as Partial<InferModel<Model>>,
|
|
219
|
-
client,
|
|
220
|
-
[],
|
|
221
|
-
{ set: [], remove: [], add: [], delete: [] },
|
|
222
|
-
'NONE',
|
|
223
|
-
0,
|
|
224
|
-
timestamps,
|
|
225
|
-
logger
|
|
226
|
-
);
|
|
227
|
-
},
|
|
228
|
-
|
|
229
|
-
delete(key) {
|
|
230
|
-
// Extract required fields from key templates
|
|
231
|
-
const requiredFields = new Set<string>();
|
|
232
|
-
if (model.key) {
|
|
233
|
-
for (const keyDef of Object.values(model.key)) {
|
|
234
|
-
extractTemplateVars(keyDef.value).forEach((field) => requiredFields.add(field));
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// Check if all required fields are present
|
|
239
|
-
const keyRecord = key as Record<string, unknown>;
|
|
240
|
-
const missingFields = Array.from(requiredFields).filter(
|
|
241
|
-
(field) => keyRecord[field] === undefined
|
|
242
|
-
);
|
|
243
|
-
|
|
244
|
-
if (missingFields.length > 0) {
|
|
245
|
-
throw new Error(
|
|
246
|
-
`[${modelName}] Missing required key field(s) for delete(): ${missingFields.join(', ')}. ` +
|
|
247
|
-
`Required fields: ${Array.from(requiredFields).join(', ')}`
|
|
248
|
-
);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// Resolve any key defaults or computed keys
|
|
252
|
-
const fullKey = resolveKeys(model, key);
|
|
253
|
-
|
|
254
|
-
return createDeleteBuilder<InferModel<Model>>(
|
|
255
|
-
tableName,
|
|
256
|
-
fullKey as Partial<InferModel<Model>>,
|
|
257
|
-
client,
|
|
258
|
-
[],
|
|
259
|
-
'NONE',
|
|
260
|
-
logger
|
|
261
|
-
);
|
|
262
|
-
},
|
|
263
|
-
|
|
264
|
-
batchGet(keys) {
|
|
265
|
-
// Extract required fields from key templates
|
|
266
|
-
const requiredFields = new Set<string>();
|
|
267
|
-
if (model.key) {
|
|
268
|
-
for (const keyDef of Object.values(model.key)) {
|
|
269
|
-
extractTemplateVars(keyDef.value).forEach((field) => requiredFields.add(field));
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Process all keys and validate them
|
|
274
|
-
const resolvedKeys = keys.map((key) => {
|
|
275
|
-
// Check if all required fields are present
|
|
276
|
-
const keyRecord = key as Record<string, unknown>;
|
|
277
|
-
const missingFields = Array.from(requiredFields).filter(
|
|
278
|
-
(field) => keyRecord[field] === undefined
|
|
279
|
-
);
|
|
280
|
-
|
|
281
|
-
if (missingFields.length > 0) {
|
|
282
|
-
throw new Error(
|
|
283
|
-
`[${modelName}] Missing required key field(s) for batchGet(): ${missingFields.join(', ')}. ` +
|
|
284
|
-
`Required fields: ${Array.from(requiredFields).join(', ')}`
|
|
285
|
-
);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Resolve any key defaults or computed keys
|
|
289
|
-
return resolveKeys(model, key);
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
// Create the request items in the format expected by BatchGetItem
|
|
293
|
-
const requestItems = {
|
|
294
|
-
[tableName]: {
|
|
295
|
-
Keys: resolvedKeys,
|
|
296
|
-
},
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
return createBatchGetBuilder<InferModel<Model>>(requestItems, client, undefined, logger);
|
|
300
|
-
},
|
|
301
|
-
|
|
302
|
-
batchWrite(items) {
|
|
303
|
-
// Validate and process all items
|
|
304
|
-
const processedItems = items.map((item) => {
|
|
305
|
-
// Validate full input data
|
|
306
|
-
const parsed = zodSchema.parse(item);
|
|
307
|
-
|
|
308
|
-
// Apply post-processing defaults from the model (including timestamps for new items)
|
|
309
|
-
const withDefaults = applyPostDefaults(model, parsed, {
|
|
310
|
-
isUpdate: false,
|
|
311
|
-
timestamps,
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
// Resolve keys again with defaults
|
|
315
|
-
const fullKey = resolveKeys(model, withDefaults);
|
|
316
|
-
|
|
317
|
-
// Combine keys and data into full item, adding _type field
|
|
318
|
-
return {
|
|
319
|
-
...withDefaults,
|
|
320
|
-
...fullKey,
|
|
321
|
-
_type: modelName, // Add entity type identifier
|
|
322
|
-
};
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
// Create the request items in the format expected by BatchWriteItem
|
|
326
|
-
const requestItems: Record<string, WriteRequest[]> = {
|
|
327
|
-
[tableName]: processedItems.map((item) => ({
|
|
328
|
-
PutRequest: {
|
|
329
|
-
Item: item,
|
|
330
|
-
},
|
|
331
|
-
})),
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
return createBatchWriteBuilder(requestItems, client, logger);
|
|
335
|
-
},
|
|
336
|
-
};
|
|
337
|
-
};
|