@metaobjectsdev/codegen-ts 0.16.0 → 0.17.0-rc.1
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/dist/column-mapper.d.ts +10 -0
- package/dist/column-mapper.d.ts.map +1 -1
- package/dist/column-mapper.js +21 -2
- package/dist/column-mapper.js.map +1 -1
- package/dist/naming.d.ts +4 -0
- package/dist/naming.d.ts.map +1 -1
- package/dist/naming.js +6 -0
- package/dist/naming.js.map +1 -1
- package/dist/projection/build-projection-views.d.ts +5 -1
- package/dist/projection/build-projection-views.d.ts.map +1 -1
- package/dist/projection/build-projection-views.js +165 -47
- package/dist/projection/build-projection-views.js.map +1 -1
- package/dist/projection/extract-view-spec.d.ts +8 -1
- package/dist/projection/extract-view-spec.d.ts.map +1 -1
- package/dist/projection/extract-view-spec.js +430 -29
- package/dist/projection/extract-view-spec.js.map +1 -1
- package/dist/projection/view-ddl-emit.d.ts.map +1 -1
- package/dist/projection/view-ddl-emit.js +142 -25
- package/dist/projection/view-ddl-emit.js.map +1 -1
- package/dist/projection/view-spec.d.ts +101 -3
- package/dist/projection/view-spec.d.ts.map +1 -1
- package/dist/templates/drizzle-schema.d.ts.map +1 -1
- package/dist/templates/drizzle-schema.js +9 -0
- package/dist/templates/drizzle-schema.js.map +1 -1
- package/dist/templates/entity-file.d.ts.map +1 -1
- package/dist/templates/entity-file.js +39 -3
- package/dist/templates/entity-file.js.map +1 -1
- package/dist/templates/inferred-types.d.ts +1 -1
- package/dist/templates/inferred-types.d.ts.map +1 -1
- package/dist/templates/inferred-types.js +13 -1
- package/dist/templates/inferred-types.js.map +1 -1
- package/dist/templates/projection-decl.d.ts.map +1 -1
- package/dist/templates/projection-decl.js +9 -70
- package/dist/templates/projection-decl.js.map +1 -1
- package/dist/templates/queries-file.d.ts.map +1 -1
- package/dist/templates/queries-file.js +117 -43
- package/dist/templates/queries-file.js.map +1 -1
- package/dist/templates/queries.d.ts +21 -4
- package/dist/templates/queries.d.ts.map +1 -1
- package/dist/templates/queries.js +48 -12
- package/dist/templates/queries.js.map +1 -1
- package/dist/templates/view-decl.d.ts +28 -0
- package/dist/templates/view-decl.d.ts.map +1 -0
- package/dist/templates/view-decl.js +107 -0
- package/dist/templates/view-decl.js.map +1 -0
- package/dist/templates/zod-validators.d.ts +6 -0
- package/dist/templates/zod-validators.d.ts.map +1 -1
- package/dist/templates/zod-validators.js +53 -7
- package/dist/templates/zod-validators.js.map +1 -1
- package/package.json +6 -6
- package/src/column-mapper.ts +26 -1
- package/src/naming.ts +7 -0
- package/src/projection/build-projection-views.ts +211 -50
- package/src/projection/extract-view-spec.ts +468 -29
- package/src/projection/view-ddl-emit.ts +158 -24
- package/src/projection/view-spec.ts +104 -3
- package/src/reference/entity.ts +11 -1
- package/src/reference/queries.ts +4 -1
- package/src/templates/drizzle-schema.ts +7 -0
- package/src/templates/entity-file.ts +46 -3
- package/src/templates/inferred-types.ts +18 -1
- package/src/templates/projection-decl.ts +8 -74
- package/src/templates/queries-file.ts +133 -48
- package/src/templates/queries.ts +50 -11
- package/src/templates/view-decl.ts +128 -0
- package/src/templates/zod-validators.ts +54 -9
|
@@ -73,6 +73,19 @@ export function isTphSubtype(obj: MetaObject): boolean {
|
|
|
73
73
|
return tphDiscriminatorPin(obj) !== undefined;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
/** True when this object declares at least one @autoSet timestamp field
|
|
77
|
+
* (onCreate or onUpdate). Drives whether codegen emits the #203
|
|
78
|
+
* `<Entity>InsertPreservingSchema` + `insertPreserving<Entity>` escape hatch —
|
|
79
|
+
* a plain entity has nothing to preserve, so both are omitted. Resolving
|
|
80
|
+
* (ADR-0039): honors an @autoSet inherited via extends. */
|
|
81
|
+
export function hasAutoSetFields(obj: MetaObject): boolean {
|
|
82
|
+
for (const child of obj.fields()) {
|
|
83
|
+
const autoSet = child.attr(FIELD_ATTR_AUTO_SET);
|
|
84
|
+
if (autoSet === AUTO_SET_ON_CREATE || autoSet === AUTO_SET_ON_UPDATE) return true;
|
|
85
|
+
}
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
|
|
76
89
|
/**
|
|
77
90
|
* FR-017 Tier 2 — the per-subtype FULL read schema `<Sub>Schema`. Unlike the
|
|
78
91
|
* insert schema, this includes every effective field (PK included) so a raw DB
|
|
@@ -162,7 +175,9 @@ export function renderInsertSchemaOnly(obj: MetaObject, ctx?: RenderContext): Co
|
|
|
162
175
|
// FR-013: @readOnly fields are populated by DB / replication / external
|
|
163
176
|
// owner; the application has no path to write them. Exclude from the
|
|
164
177
|
// create-shape schema entirely.
|
|
165
|
-
|
|
178
|
+
// #213 — a derived (origin-bearing) field is read-only (FR-024 §7 / ADR-0028):
|
|
179
|
+
// excluded from the Insert/Update/preserving schemas, exactly like @readOnly.
|
|
180
|
+
if (child.attr(FIELD_ATTR_READ_ONLY) === true || child.isDerived()) continue;
|
|
166
181
|
|
|
167
182
|
// FR-017 Tier 1: TPH subtype pins its discriminator field to z.literal(...).
|
|
168
183
|
if (tphPin !== undefined && child.name === tphPin.fieldName) {
|
|
@@ -226,7 +241,9 @@ export function insertSchemaFields(obj: MetaObject): SchemaFieldShape[] {
|
|
|
226
241
|
const out: SchemaFieldShape[] = [];
|
|
227
242
|
for (const child of obj.fields()) {
|
|
228
243
|
if (autoGenPkFields.has(child.name)) continue;
|
|
229
|
-
|
|
244
|
+
// #213 — a derived (origin-bearing) field is read-only (FR-024 §7 / ADR-0028):
|
|
245
|
+
// excluded from the Insert/Update/preserving schemas, exactly like @readOnly.
|
|
246
|
+
if (child.attr(FIELD_ATTR_READ_ONLY) === true || child.isDerived()) continue;
|
|
230
247
|
if (tphPin !== undefined && child.name === tphPin.fieldName) {
|
|
231
248
|
out.push({ name: child.name, optional: false, pinnedLiteral: tphPin.value });
|
|
232
249
|
continue;
|
|
@@ -256,7 +273,9 @@ export function updateSchemaFields(obj: MetaObject): SchemaFieldShape[] {
|
|
|
256
273
|
const out: SchemaFieldShape[] = [];
|
|
257
274
|
for (const child of obj.fields()) {
|
|
258
275
|
if (autoGenPkFields.has(child.name)) continue;
|
|
259
|
-
|
|
276
|
+
// #213 — a derived (origin-bearing) field is read-only (FR-024 §7 / ADR-0028):
|
|
277
|
+
// excluded from the Insert/Update/preserving schemas, exactly like @readOnly.
|
|
278
|
+
if (child.attr(FIELD_ATTR_READ_ONLY) === true || child.isDerived()) continue;
|
|
260
279
|
// TPH subtype discriminator: omitted from the update schema entirely.
|
|
261
280
|
if (tphPin !== undefined && child.name === tphPin.fieldName) continue;
|
|
262
281
|
const autoSet = child.attr(FIELD_ATTR_AUTO_SET);
|
|
@@ -282,22 +301,29 @@ export function renderZodValidators(obj: MetaObject, ctx?: RenderContext): Code
|
|
|
282
301
|
|
|
283
302
|
const insertFieldLines: Code[] = [];
|
|
284
303
|
const updateFieldLines: Code[] = [];
|
|
304
|
+
// #203 — the `insertPreserving` escape hatch's schema: same shape as the insert
|
|
305
|
+
// schema, but @autoSet columns are written VERBATIM (no create-time now()
|
|
306
|
+
// transform). Only emitted when the entity declares @autoSet fields.
|
|
307
|
+
const preservingFieldLines: Code[] = [];
|
|
308
|
+
const emitPreserving = hasAutoSetFields(obj);
|
|
285
309
|
for (const child of obj.fields()) {
|
|
286
310
|
if (autoGenPkFields.has(child.name)) continue;
|
|
287
311
|
// FR-013: @readOnly fields appear in neither InsertSchema nor UpdateSchema.
|
|
288
312
|
// The DB / trigger / replication owns the write path; the app must not
|
|
289
313
|
// pass these values in POST/PATCH bodies (routesFile enforces the same
|
|
290
314
|
// contract at the boundary with a 400 response).
|
|
291
|
-
|
|
315
|
+
// #213 — a derived (origin-bearing) field is read-only (FR-024 §7 / ADR-0028):
|
|
316
|
+
// excluded from the Insert/Update/preserving schemas, exactly like @readOnly.
|
|
317
|
+
if (child.attr(FIELD_ATTR_READ_ONLY) === true || child.isDerived()) continue;
|
|
292
318
|
|
|
293
319
|
// FR-017 Tier 1: TPH subtype pins its discriminator field to z.literal(...).
|
|
294
320
|
// The discriminator is implicit on subtype rows (controlled by URL / insert
|
|
295
321
|
// path) — the app never writes it via the body and never updates it.
|
|
296
322
|
// Insert: pinned literal. Update: omitted entirely (clients can't change subtype).
|
|
297
323
|
if (tphPin !== undefined && child.name === tphPin.fieldName) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
);
|
|
324
|
+
const litLine = code` ${child.name}: z.literal(${JSON.stringify(tphPin.value)})`;
|
|
325
|
+
insertFieldLines.push(litLine);
|
|
326
|
+
preservingFieldLines.push(litLine);
|
|
301
327
|
continue;
|
|
302
328
|
}
|
|
303
329
|
|
|
@@ -308,8 +334,13 @@ export function renderZodValidators(obj: MetaObject, ctx?: RenderContext): Code
|
|
|
308
334
|
insertFieldLines.push(
|
|
309
335
|
code` ${child.name}: z.string().optional().transform(() => new Date().toISOString())`,
|
|
310
336
|
);
|
|
337
|
+
// Preserving schema: the @autoSet column is validated verbatim (its natural
|
|
338
|
+
// field expr) so an import/restore keeps the caller's original timestamp.
|
|
339
|
+
preservingFieldLines.push(code` ${child.name}: ${zodFieldExpr(child, obj, ctx)}`);
|
|
311
340
|
} else {
|
|
312
|
-
|
|
341
|
+
const fieldLine = code` ${child.name}: ${zodFieldExpr(child, obj, ctx)}`;
|
|
342
|
+
insertFieldLines.push(fieldLine);
|
|
343
|
+
preservingFieldLines.push(fieldLine);
|
|
313
344
|
}
|
|
314
345
|
|
|
315
346
|
// Update schema: @autoSet onCreate → omit entirely; onUpdate → transform
|
|
@@ -339,10 +370,24 @@ export function renderZodValidators(obj: MetaObject, ctx?: RenderContext): Code
|
|
|
339
370
|
|
|
340
371
|
const insertSchemaName = `${obj.name}InsertSchema`;
|
|
341
372
|
const updateSchemaName = `${obj.name}UpdateSchema`;
|
|
373
|
+
const preservingSchemaName = `${obj.name}InsertPreservingSchema`;
|
|
342
374
|
|
|
343
375
|
const docs = renderDocsFor(obj);
|
|
344
376
|
const docsPrefix = docs ? `${docs}\n` : "";
|
|
345
377
|
|
|
378
|
+
// #203 — emit the preserving insert-shape only for @autoSet entities (nothing to
|
|
379
|
+
// preserve otherwise). Backs `insertPreserving<Entity>` (import/restore/replication).
|
|
380
|
+
const preservingBlock = emitPreserving
|
|
381
|
+
? code`
|
|
382
|
+
|
|
383
|
+
/** Insert-shape for import / restore / replication of ${obj.name}: identical to
|
|
384
|
+
* ${insertSchemaName}, but the @autoSet timestamp columns are written VERBATIM
|
|
385
|
+
* (no create-time now() stamp) so the caller's original values are preserved. */
|
|
386
|
+
export const ${preservingSchemaName} = ${z}.object({
|
|
387
|
+
${joinCode(preservingFieldLines, { on: ",\n" })}
|
|
388
|
+
});`
|
|
389
|
+
: code``;
|
|
390
|
+
|
|
346
391
|
return code`
|
|
347
392
|
${docsPrefix}export const ${insertSchemaName} = ${z}.object({
|
|
348
393
|
${joinCode(insertFieldLines, { on: ",\n" })}
|
|
@@ -354,7 +399,7 @@ ${joinCode(updateFieldLines, { on: ",\n" })}
|
|
|
354
399
|
|
|
355
400
|
/** Typed patch shape for ${obj.name}: every settable field, optional (FR-035 PATCH). A
|
|
356
401
|
* renamed/dropped field is a compile error at every \`update${obj.name}\` call site. */
|
|
357
|
-
export type ${obj.name}Patch = ${z}.input<typeof ${updateSchemaName}
|
|
402
|
+
export type ${obj.name}Patch = ${z}.input<typeof ${updateSchemaName}>;${preservingBlock}
|
|
358
403
|
`;
|
|
359
404
|
}
|
|
360
405
|
|