@ftschopp/dynatable-core 1.4.2 → 1.4.4
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 +14 -0
- package/dist/builders/query/create-query-builder.d.ts.map +1 -1
- package/dist/builders/query/create-query-builder.js +19 -2
- package/dist/builders/update/create-update-builder.d.ts.map +1 -1
- package/dist/builders/update/create-update-builder.js +25 -0
- package/dist/core/types.d.ts +5 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/utils/model-utils.d.ts +9 -3
- package/dist/utils/model-utils.d.ts.map +1 -1
- package/dist/utils/model-utils.js +15 -7
- package/package.json +19 -2
- package/eslint.config.mjs +0 -4
- package/jest.config.js +0 -11
- package/src/builders/README.md +0 -339
- package/src/builders/batch-get/README.md +0 -43
- package/src/builders/batch-get/create-batch-get-builder.test.ts +0 -193
- package/src/builders/batch-get/create-batch-get-builder.ts +0 -108
- package/src/builders/batch-get/index.ts +0 -2
- package/src/builders/batch-get/types.ts +0 -28
- package/src/builders/batch-write/README.md +0 -204
- package/src/builders/batch-write/create-batch-write-builder.test.ts +0 -173
- package/src/builders/batch-write/create-batch-write-builder.ts +0 -49
- package/src/builders/batch-write/index.ts +0 -2
- package/src/builders/batch-write/types.ts +0 -33
- package/src/builders/delete/create-delete-builder.test.ts +0 -294
- package/src/builders/delete/create-delete-builder.ts +0 -100
- package/src/builders/delete/index.ts +0 -2
- package/src/builders/delete/types.ts +0 -17
- package/src/builders/get/create-get-builder.test.ts +0 -272
- package/src/builders/get/create-get-builder.ts +0 -117
- package/src/builders/get/index.ts +0 -2
- package/src/builders/get/types.ts +0 -39
- package/src/builders/index.ts +0 -14
- package/src/builders/put/create-put-builder.test.ts +0 -213
- package/src/builders/put/create-put-builder.ts +0 -160
- package/src/builders/put/index.ts +0 -2
- package/src/builders/put/types.ts +0 -24
- package/src/builders/query/create-query-builder.test.ts +0 -770
- package/src/builders/query/create-query-builder.ts +0 -455
- package/src/builders/query/index.ts +0 -2
- package/src/builders/query/types.ts +0 -109
- package/src/builders/scan/create-scan-builder.test.ts +0 -416
- package/src/builders/scan/create-scan-builder.ts +0 -265
- package/src/builders/scan/index.ts +0 -2
- package/src/builders/scan/types.ts +0 -88
- package/src/builders/shared/conditions.ts +0 -58
- package/src/builders/shared/index.ts +0 -4
- package/src/builders/shared/operators.test.ts +0 -270
- package/src/builders/shared/operators.ts +0 -208
- package/src/builders/shared/projection.ts +0 -28
- package/src/builders/shared/types.ts +0 -101
- package/src/builders/transact-get/README.md +0 -167
- package/src/builders/transact-get/create-transact-get-builder.test.ts +0 -239
- package/src/builders/transact-get/create-transact-get-builder.ts +0 -67
- package/src/builders/transact-get/index.ts +0 -2
- package/src/builders/transact-get/types.ts +0 -31
- package/src/builders/transact-write/README.md +0 -202
- package/src/builders/transact-write/create-transact-write-builder.test.ts +0 -288
- package/src/builders/transact-write/create-transact-write-builder.ts +0 -124
- package/src/builders/transact-write/index.ts +0 -2
- package/src/builders/transact-write/types.ts +0 -71
- package/src/builders/update/create-update-builder.test.ts +0 -573
- package/src/builders/update/create-update-builder.ts +0 -375
- package/src/builders/update/index.ts +0 -2
- package/src/builders/update/types.ts +0 -63
- package/src/core/types.test.ts +0 -641
- package/src/core/types.ts +0 -366
- package/src/entity/create-entity-api.ts +0 -224
- package/src/entity/index.ts +0 -19
- package/src/entity/middleware/factories.ts +0 -15
- package/src/entity/middleware/types.ts +0 -7
- package/src/entity/middleware/with-middleware.ts +0 -37
- package/src/entity/types.ts +0 -79
- package/src/entity/validation/key-validation.ts +0 -34
- package/src/index.ts +0 -23
- package/src/table.ts +0 -116
- package/src/utils/dynamodb-logger.test.ts +0 -246
- package/src/utils/dynamodb-logger.ts +0 -175
- package/src/utils/model-utils.test.ts +0 -452
- package/src/utils/model-utils.ts +0 -188
- package/src/utils/zod-utils.test.ts +0 -363
- package/src/utils/zod-utils.ts +0 -56
- package/tests/integration/instagram-clone.integration.test.ts +0 -1019
- package/tests/integration/pagination-timestamps.integration.test.ts +0 -374
- package/tests/integration/transactions.integration.test.ts +0 -528
- package/tsconfig.json +0 -12
|
@@ -1,363 +0,0 @@
|
|
|
1
|
-
import { modelToZod, typeToZod } from './zod-utils';
|
|
2
|
-
import type { AttributeDefinition, ModelDefinition } from '../core/types';
|
|
3
|
-
|
|
4
|
-
describe('zod-utils', () => {
|
|
5
|
-
describe('typeToZod', () => {
|
|
6
|
-
it('should convert String type to z.string()', () => {
|
|
7
|
-
const attr: AttributeDefinition = {
|
|
8
|
-
type: String,
|
|
9
|
-
required: true,
|
|
10
|
-
};
|
|
11
|
-
const zodType = typeToZod(attr);
|
|
12
|
-
|
|
13
|
-
expect(() => zodType.parse('hello')).not.toThrow();
|
|
14
|
-
expect(() => zodType.parse(123)).toThrow();
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('should convert Number type to z.number()', () => {
|
|
18
|
-
const attr: AttributeDefinition = {
|
|
19
|
-
type: Number,
|
|
20
|
-
required: true,
|
|
21
|
-
};
|
|
22
|
-
const zodType = typeToZod(attr);
|
|
23
|
-
|
|
24
|
-
expect(() => zodType.parse(42)).not.toThrow();
|
|
25
|
-
expect(() => zodType.parse('42')).toThrow();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('should convert Boolean type to z.boolean()', () => {
|
|
29
|
-
const attr: AttributeDefinition = {
|
|
30
|
-
type: Boolean,
|
|
31
|
-
required: true,
|
|
32
|
-
};
|
|
33
|
-
const zodType = typeToZod(attr);
|
|
34
|
-
|
|
35
|
-
expect(() => zodType.parse(true)).not.toThrow();
|
|
36
|
-
expect(() => zodType.parse(false)).not.toThrow();
|
|
37
|
-
expect(() => zodType.parse('true')).toThrow();
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('should convert Date type to z.date()', () => {
|
|
41
|
-
const attr: AttributeDefinition = {
|
|
42
|
-
type: Date,
|
|
43
|
-
required: true,
|
|
44
|
-
};
|
|
45
|
-
const zodType = typeToZod(attr);
|
|
46
|
-
|
|
47
|
-
const now = new Date();
|
|
48
|
-
expect(() => zodType.parse(now)).not.toThrow();
|
|
49
|
-
expect(() => zodType.parse('2024-01-01')).toThrow();
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('should make optional fields when required is false', () => {
|
|
53
|
-
const attr: AttributeDefinition = {
|
|
54
|
-
type: String,
|
|
55
|
-
required: false,
|
|
56
|
-
};
|
|
57
|
-
const zodType = typeToZod(attr);
|
|
58
|
-
|
|
59
|
-
expect(() => zodType.parse('hello')).not.toThrow();
|
|
60
|
-
expect(() => zodType.parse(undefined)).not.toThrow();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('should make required fields when required is true', () => {
|
|
64
|
-
const attr: AttributeDefinition = {
|
|
65
|
-
type: String,
|
|
66
|
-
required: true,
|
|
67
|
-
};
|
|
68
|
-
const zodType = typeToZod(attr);
|
|
69
|
-
|
|
70
|
-
expect(() => zodType.parse('hello')).not.toThrow();
|
|
71
|
-
expect(() => zodType.parse(undefined)).toThrow();
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('should return z.unknown() for unrecognized types', () => {
|
|
75
|
-
const attr: AttributeDefinition = {
|
|
76
|
-
type: Map as any,
|
|
77
|
-
required: true,
|
|
78
|
-
};
|
|
79
|
-
const zodType = typeToZod(attr);
|
|
80
|
-
|
|
81
|
-
// z.unknown() accepts any value
|
|
82
|
-
expect(() => zodType.parse('anything')).not.toThrow();
|
|
83
|
-
expect(() => zodType.parse(123)).not.toThrow();
|
|
84
|
-
expect(() => zodType.parse([])).not.toThrow();
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('should convert Object type with schema to z.looseObject()', () => {
|
|
88
|
-
const attr: AttributeDefinition = {
|
|
89
|
-
type: Object,
|
|
90
|
-
schema: {
|
|
91
|
-
city: { type: String, required: true },
|
|
92
|
-
zip: { type: String },
|
|
93
|
-
},
|
|
94
|
-
required: true,
|
|
95
|
-
};
|
|
96
|
-
const zodType = typeToZod(attr);
|
|
97
|
-
|
|
98
|
-
expect(() => zodType.parse({ city: 'BA' })).not.toThrow();
|
|
99
|
-
expect(() => zodType.parse({ city: 'BA', zip: '1000' })).not.toThrow();
|
|
100
|
-
expect(() => zodType.parse({ zip: '1000' })).toThrow(); // city required
|
|
101
|
-
expect(() => zodType.parse({})).toThrow();
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('should convert Object type without schema to z.record()', () => {
|
|
105
|
-
const attr: AttributeDefinition = {
|
|
106
|
-
type: Object,
|
|
107
|
-
schema: {},
|
|
108
|
-
};
|
|
109
|
-
const zodType = typeToZod(attr);
|
|
110
|
-
expect(() => zodType.parse({})).not.toThrow();
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('should convert Array type with scalar items', () => {
|
|
114
|
-
const attr: AttributeDefinition = {
|
|
115
|
-
type: Array,
|
|
116
|
-
items: { type: String },
|
|
117
|
-
required: true,
|
|
118
|
-
};
|
|
119
|
-
const zodType = typeToZod(attr);
|
|
120
|
-
|
|
121
|
-
expect(() => zodType.parse(['a', 'b'])).not.toThrow();
|
|
122
|
-
expect(() => zodType.parse([])).not.toThrow();
|
|
123
|
-
expect(() => zodType.parse([1, 2])).toThrow(); // numbers, not strings
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it('should convert Array type with object items (like history)', () => {
|
|
127
|
-
const attr: AttributeDefinition = {
|
|
128
|
-
type: Array,
|
|
129
|
-
items: {
|
|
130
|
-
type: Object,
|
|
131
|
-
schema: {
|
|
132
|
-
date: { type: String },
|
|
133
|
-
status: { type: String, required: true },
|
|
134
|
-
},
|
|
135
|
-
},
|
|
136
|
-
required: true,
|
|
137
|
-
};
|
|
138
|
-
const zodType = typeToZod(attr);
|
|
139
|
-
|
|
140
|
-
expect(() => zodType.parse([{ status: 'PENDING' }])).not.toThrow();
|
|
141
|
-
expect(() => zodType.parse([{ date: '2024-01-01', status: 'DONE' }])).not.toThrow();
|
|
142
|
-
expect(() => zodType.parse([{ date: '2024-01-01' }])).toThrow(); // missing status
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it('should handle optional Object attribute', () => {
|
|
146
|
-
const attr: AttributeDefinition = {
|
|
147
|
-
type: Object,
|
|
148
|
-
schema: { name: { type: String, required: true } },
|
|
149
|
-
};
|
|
150
|
-
const zodType = typeToZod(attr);
|
|
151
|
-
|
|
152
|
-
expect(() => zodType.parse(undefined)).not.toThrow();
|
|
153
|
-
expect(() => zodType.parse({ name: 'test' })).not.toThrow();
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('should handle deeply nested objects', () => {
|
|
157
|
-
const attr: AttributeDefinition = {
|
|
158
|
-
type: Object,
|
|
159
|
-
required: true,
|
|
160
|
-
schema: {
|
|
161
|
-
value: { type: Number, required: true },
|
|
162
|
-
breakdown: {
|
|
163
|
-
type: Object,
|
|
164
|
-
schema: {
|
|
165
|
-
base: { type: Number, required: true },
|
|
166
|
-
fees: { type: Number, required: true },
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
};
|
|
171
|
-
const zodType = typeToZod(attr);
|
|
172
|
-
|
|
173
|
-
expect(() => zodType.parse({ value: 100, breakdown: { base: 90, fees: 10 } })).not.toThrow();
|
|
174
|
-
expect(() => zodType.parse({ value: 100 })).not.toThrow(); // breakdown optional
|
|
175
|
-
expect(() => zodType.parse({})).toThrow(); // value required
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
describe('modelToZod', () => {
|
|
180
|
-
it('should convert a simple model to Zod schema', () => {
|
|
181
|
-
const model: ModelDefinition = {
|
|
182
|
-
key: {
|
|
183
|
-
PK: { type: String, value: 'USER#${id}' },
|
|
184
|
-
SK: { type: String, value: 'PROFILE' },
|
|
185
|
-
},
|
|
186
|
-
attributes: {
|
|
187
|
-
id: { type: String, required: true },
|
|
188
|
-
name: { type: String, required: true },
|
|
189
|
-
age: { type: Number, required: false },
|
|
190
|
-
},
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
const zodSchema = modelToZod(model);
|
|
194
|
-
|
|
195
|
-
const validData = {
|
|
196
|
-
id: 'user-123',
|
|
197
|
-
name: 'John Doe',
|
|
198
|
-
age: 30,
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
expect(() => zodSchema.parse(validData)).not.toThrow();
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
it('should allow optional fields to be missing', () => {
|
|
205
|
-
const model: ModelDefinition = {
|
|
206
|
-
key: {
|
|
207
|
-
PK: { type: String, value: 'USER#${id}' },
|
|
208
|
-
SK: { type: String, value: 'PROFILE' },
|
|
209
|
-
},
|
|
210
|
-
attributes: {
|
|
211
|
-
id: { type: String, required: true },
|
|
212
|
-
email: { type: String, required: false },
|
|
213
|
-
},
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
const zodSchema = modelToZod(model);
|
|
217
|
-
|
|
218
|
-
const dataWithoutOptional = {
|
|
219
|
-
id: 'user-123',
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
expect(() => zodSchema.parse(dataWithoutOptional)).not.toThrow();
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
it('should reject missing required fields', () => {
|
|
226
|
-
const model: ModelDefinition = {
|
|
227
|
-
key: {
|
|
228
|
-
PK: { type: String, value: 'USER#${id}' },
|
|
229
|
-
SK: { type: String, value: 'PROFILE' },
|
|
230
|
-
},
|
|
231
|
-
attributes: {
|
|
232
|
-
id: { type: String, required: true },
|
|
233
|
-
name: { type: String, required: true },
|
|
234
|
-
},
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
const zodSchema = modelToZod(model);
|
|
238
|
-
|
|
239
|
-
const invalidData = {
|
|
240
|
-
id: 'user-123',
|
|
241
|
-
// name is missing
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
expect(() => zodSchema.parse(invalidData)).toThrow();
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('should use passthrough to allow additional fields', () => {
|
|
248
|
-
const model: ModelDefinition = {
|
|
249
|
-
key: {
|
|
250
|
-
PK: { type: String, value: 'USER#${id}' },
|
|
251
|
-
SK: { type: String, value: 'PROFILE' },
|
|
252
|
-
},
|
|
253
|
-
attributes: {
|
|
254
|
-
id: { type: String, required: true },
|
|
255
|
-
},
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
const zodSchema = modelToZod(model);
|
|
259
|
-
|
|
260
|
-
const dataWithExtraFields = {
|
|
261
|
-
id: 'user-123',
|
|
262
|
-
createdAt: new Date(),
|
|
263
|
-
updatedAt: new Date(),
|
|
264
|
-
someOtherField: 'value',
|
|
265
|
-
};
|
|
266
|
-
|
|
267
|
-
// Should not throw because of passthrough mode
|
|
268
|
-
expect(() => zodSchema.parse(dataWithExtraFields)).not.toThrow();
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it('should handle complex models with multiple types', () => {
|
|
272
|
-
const model: ModelDefinition = {
|
|
273
|
-
key: {
|
|
274
|
-
PK: { type: String, value: 'PRODUCT#${id}' },
|
|
275
|
-
SK: { type: String, value: 'DETAILS' },
|
|
276
|
-
},
|
|
277
|
-
attributes: {
|
|
278
|
-
id: { type: String, required: true },
|
|
279
|
-
name: { type: String, required: true },
|
|
280
|
-
price: { type: Number, required: true },
|
|
281
|
-
available: { type: Boolean, required: false },
|
|
282
|
-
releaseDate: { type: Date, required: false },
|
|
283
|
-
},
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
const zodSchema = modelToZod(model);
|
|
287
|
-
|
|
288
|
-
const validProduct = {
|
|
289
|
-
id: 'prod-123',
|
|
290
|
-
name: 'Laptop',
|
|
291
|
-
price: 999.99,
|
|
292
|
-
available: true,
|
|
293
|
-
releaseDate: new Date('2024-01-01'),
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
expect(() => zodSchema.parse(validProduct)).not.toThrow();
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
it('should reject wrong types', () => {
|
|
300
|
-
const model: ModelDefinition = {
|
|
301
|
-
key: {
|
|
302
|
-
PK: { type: String, value: 'USER#${id}' },
|
|
303
|
-
SK: { type: String, value: 'PROFILE' },
|
|
304
|
-
},
|
|
305
|
-
attributes: {
|
|
306
|
-
id: { type: String, required: true },
|
|
307
|
-
age: { type: Number, required: true },
|
|
308
|
-
},
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
const zodSchema = modelToZod(model);
|
|
312
|
-
|
|
313
|
-
const invalidData = {
|
|
314
|
-
id: 'user-123',
|
|
315
|
-
age: '30', // Wrong type: string instead of number
|
|
316
|
-
};
|
|
317
|
-
|
|
318
|
-
expect(() => zodSchema.parse(invalidData)).toThrow();
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
it('should handle empty models', () => {
|
|
322
|
-
const model: ModelDefinition = {
|
|
323
|
-
key: {
|
|
324
|
-
PK: { type: String, value: 'EMPTY#${id}' },
|
|
325
|
-
SK: { type: String, value: 'ITEM' },
|
|
326
|
-
},
|
|
327
|
-
attributes: {},
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
const zodSchema = modelToZod(model);
|
|
331
|
-
|
|
332
|
-
expect(() => zodSchema.parse({})).not.toThrow();
|
|
333
|
-
// Passthrough allows any fields
|
|
334
|
-
expect(() => zodSchema.parse({ anyField: 'value' })).not.toThrow();
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
it('should validate parsed data correctly', () => {
|
|
338
|
-
const model: ModelDefinition = {
|
|
339
|
-
key: {
|
|
340
|
-
PK: { type: String, value: 'USER#${id}' },
|
|
341
|
-
SK: { type: String, value: 'PROFILE' },
|
|
342
|
-
},
|
|
343
|
-
attributes: {
|
|
344
|
-
id: { type: String, required: true },
|
|
345
|
-
count: { type: Number, required: true },
|
|
346
|
-
},
|
|
347
|
-
};
|
|
348
|
-
|
|
349
|
-
const zodSchema = modelToZod(model);
|
|
350
|
-
|
|
351
|
-
const data = {
|
|
352
|
-
id: 'user-123',
|
|
353
|
-
count: 42,
|
|
354
|
-
extra: 'allowed',
|
|
355
|
-
};
|
|
356
|
-
|
|
357
|
-
const parsed = zodSchema.parse(data);
|
|
358
|
-
expect(parsed.id).toBe('user-123');
|
|
359
|
-
expect(parsed.count).toBe(42);
|
|
360
|
-
expect(parsed.extra).toBe('allowed');
|
|
361
|
-
});
|
|
362
|
-
});
|
|
363
|
-
});
|
package/src/utils/zod-utils.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
// -------------------- Zod Conversion --------------------
|
|
3
|
-
|
|
4
|
-
import { AttributeDefinition, ModelDefinition } from '@/core/types';
|
|
5
|
-
import { z, ZodObject, ZodType } from 'zod';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Converts an attribute definition to a Zod schema type.
|
|
9
|
-
* Supports scalars, nested objects (with schema), and arrays (with items).
|
|
10
|
-
*/
|
|
11
|
-
export const typeToZod = (attr: AttributeDefinition): ZodType => {
|
|
12
|
-
let zodType: ZodType;
|
|
13
|
-
|
|
14
|
-
if (attr.type === Object) {
|
|
15
|
-
const schema = (attr as { schema?: Record<string, AttributeDefinition> }).schema;
|
|
16
|
-
if (schema) {
|
|
17
|
-
const shape: Record<string, ZodType> = {};
|
|
18
|
-
for (const [key, nestedAttr] of Object.entries(schema)) {
|
|
19
|
-
shape[key] = typeToZod(nestedAttr);
|
|
20
|
-
}
|
|
21
|
-
zodType = z.looseObject(shape);
|
|
22
|
-
} else {
|
|
23
|
-
zodType = z.record(z.string(), z.unknown());
|
|
24
|
-
}
|
|
25
|
-
} else if (attr.type === Array) {
|
|
26
|
-
const items = (attr as { items?: AttributeDefinition }).items;
|
|
27
|
-
zodType = items ? z.array(typeToZod(items)) : z.array(z.unknown());
|
|
28
|
-
} else {
|
|
29
|
-
zodType =
|
|
30
|
-
attr.type === String
|
|
31
|
-
? z.string()
|
|
32
|
-
: attr.type === Number
|
|
33
|
-
? z.number()
|
|
34
|
-
: attr.type === Boolean
|
|
35
|
-
? z.boolean()
|
|
36
|
-
: attr.type === Date
|
|
37
|
-
? z.date()
|
|
38
|
-
: z.unknown();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
const isGenerated = 'generate' in attr;
|
|
42
|
-
return attr.required && !isGenerated ? zodType : zodType.optional();
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Converts a model definition to a Zod object schema
|
|
47
|
-
* Uses passthrough mode to allow additional fields like createdAt/updatedAt
|
|
48
|
-
* that are added by applyPostDefaults when timestamps are enabled
|
|
49
|
-
*/
|
|
50
|
-
export const modelToZod = (model: ModelDefinition): ZodObject<any> => {
|
|
51
|
-
const shape: Record<string, ZodType> = {};
|
|
52
|
-
for (const [key, attr] of Object.entries(model.attributes)) {
|
|
53
|
-
shape[key] = typeToZod(attr);
|
|
54
|
-
}
|
|
55
|
-
return z.looseObject(shape);
|
|
56
|
-
};
|