@metaobjectsdev/codegen-ts 0.6.0 → 0.7.0-rc.2
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 +161 -4
- package/dist/column-mapper.d.ts +16 -0
- package/dist/column-mapper.d.ts.map +1 -1
- package/dist/column-mapper.js +73 -2
- package/dist/column-mapper.js.map +1 -1
- package/dist/generators/entity-file.d.ts +15 -0
- package/dist/generators/entity-file.d.ts.map +1 -1
- package/dist/generators/entity-file.js +2 -1
- package/dist/generators/entity-file.js.map +1 -1
- package/dist/generators/index.d.ts +2 -0
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +2 -0
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/output-parser-file.d.ts +9 -0
- package/dist/generators/output-parser-file.d.ts.map +1 -0
- package/dist/generators/output-parser-file.js +37 -0
- package/dist/generators/output-parser-file.js.map +1 -0
- package/dist/generators/prompt-render-file.d.ts +9 -0
- package/dist/generators/prompt-render-file.d.ts.map +1 -0
- package/dist/generators/prompt-render-file.js +70 -0
- package/dist/generators/prompt-render-file.js.map +1 -0
- package/dist/generators/queries-file.d.ts +1 -1
- package/dist/generators/queries-file.d.ts.map +1 -1
- package/dist/generators/queries-file.js +11 -3
- package/dist/generators/queries-file.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/metaobjects-config.d.ts +3 -1
- package/dist/metaobjects-config.d.ts.map +1 -1
- package/dist/metaobjects-config.js +2 -1
- package/dist/metaobjects-config.js.map +1 -1
- package/dist/naming.d.ts +3 -12
- package/dist/naming.d.ts.map +1 -1
- package/dist/naming.js +14 -44
- package/dist/naming.js.map +1 -1
- package/dist/payload-codegen.d.ts +8 -0
- package/dist/payload-codegen.d.ts.map +1 -1
- package/dist/payload-codegen.js +33 -3
- package/dist/payload-codegen.js.map +1 -1
- package/dist/projection/extract-view-spec.d.ts +1 -1
- package/dist/projection/extract-view-spec.js +1 -1
- package/dist/source-detect.d.ts +10 -0
- package/dist/source-detect.d.ts.map +1 -0
- package/dist/source-detect.js +30 -0
- package/dist/source-detect.js.map +1 -0
- package/dist/templates/drizzle-schema.js +27 -3
- package/dist/templates/drizzle-schema.js.map +1 -1
- package/dist/templates/entity-file.d.ts +15 -1
- package/dist/templates/entity-file.d.ts.map +1 -1
- package/dist/templates/entity-file.js +15 -5
- package/dist/templates/entity-file.js.map +1 -1
- package/dist/templates/inferred-types.d.ts +9 -0
- package/dist/templates/inferred-types.d.ts.map +1 -1
- package/dist/templates/inferred-types.js +88 -2
- package/dist/templates/inferred-types.js.map +1 -1
- package/dist/templates/output-parser.d.ts +8 -0
- package/dist/templates/output-parser.d.ts.map +1 -0
- package/dist/templates/output-parser.js +129 -0
- package/dist/templates/output-parser.js.map +1 -0
- package/dist/templates/projection-decl.d.ts +1 -1
- package/dist/templates/projection-decl.js +1 -1
- package/dist/templates/queries-file.d.ts.map +1 -1
- package/dist/templates/queries-file.js +15 -4
- package/dist/templates/queries-file.js.map +1 -1
- package/dist/templates/queries.d.ts.map +1 -1
- package/dist/templates/queries.js +11 -30
- package/dist/templates/queries.js.map +1 -1
- package/dist/templates/value-object-file.d.ts +3 -0
- package/dist/templates/value-object-file.d.ts.map +1 -0
- package/dist/templates/value-object-file.js +27 -0
- package/dist/templates/value-object-file.js.map +1 -0
- package/dist/templates/zod-validators.d.ts +10 -0
- package/dist/templates/zod-validators.d.ts.map +1 -1
- package/dist/templates/zod-validators.js +108 -30
- package/dist/templates/zod-validators.js.map +1 -1
- package/package.json +4 -4
- package/src/column-mapper.ts +86 -1
- package/src/generators/entity-file.ts +17 -1
- package/src/generators/index.ts +2 -0
- package/src/generators/output-parser-file.ts +50 -0
- package/src/generators/prompt-render-file.ts +95 -0
- package/src/generators/queries-file.ts +13 -4
- package/src/index.ts +1 -1
- package/src/metaobjects-config.ts +4 -2
- package/src/naming.ts +22 -46
- package/src/payload-codegen.ts +34 -2
- package/src/projection/extract-view-spec.ts +1 -1
- package/src/source-detect.ts +28 -0
- package/src/templates/drizzle-schema.ts +27 -3
- package/src/templates/entity-file.ts +36 -5
- package/src/templates/inferred-types.ts +117 -3
- package/src/templates/output-parser.ts +143 -0
- package/src/templates/projection-decl.ts +1 -1
- package/src/templates/queries-file.ts +18 -4
- package/src/templates/queries.ts +11 -33
- package/src/templates/value-object-file.ts +30 -0
- package/src/templates/zod-validators.ts +121 -35
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-file.js","sourceRoot":"","sources":["../../src/templates/entity-file.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,0EAA0E;AAC1E,EAAE;AACF,YAAY;AACZ,
|
|
1
|
+
{"version":3,"file":"entity-file.js","sourceRoot":"","sources":["../../src/templates/entity-file.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,0EAA0E;AAC1E,EAAE;AACF,YAAY;AACZ,oHAAoH;AACpH,mHAAmH;AACnH,4DAA4D;AAE5D,OAAO,EAAE,QAAQ,EAAa,MAAM,SAAS,CAAC;AAG9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAiB/D,MAAM,UAAU,gBAAgB,CAC9B,MAAkB,EAClB,GAAkB,EAClB,IAA2B;IAE3B,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,IAAI,CAAC;IAE5C,+EAA+E;IAC/E,4EAA4E;IAC5E,wEAAwE;IACxE,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,OAAO,oBAAoB,CAAC,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE;YAClD,oBAAoB,EAAE,GAAG,CAAC,oBAAoB;YAC9C,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC,CAAC;IACL,CAAC;IAED,8EAA8E;IAC9E,4EAA4E;IAC5E,uEAAuE;IACvE,0DAA0D;IAC1D,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,8CAA8C;IAC9C,MAAM,WAAW,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAW;QACvB,mBAAmB,CAAC,MAAM,EAAE,GAAG,CAAC;QAChC,mBAAmB,CAAC,MAAM,CAAC;QAC3B,GAAG,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C,mBAAmB,CAAC,MAAM,CAAC;QAC3B,qBAAqB,CAAC,MAAM,EAAE,GAAG,CAAC,SAAS,CAAC;QAC5C,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACnF,gBAAgB,CAAC,MAAM,CAAC;KACzB,CAAC;IAEF,+EAA+E;IAC/E,4EAA4E;IAC5E,0EAA0E;IAC1E,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACzD,MAAM,MAAM,GACV,MAAM,gBAAgB,mBAAmB;QACzC,uBAAuB,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK;QACxD,oBAAoB,MAAM,CAAC,IAAI,gCAAgC,CAAC;IAClE,OAAO,MAAM,GAAG,IAAI,CAAC;AACvB,CAAC"}
|
|
@@ -8,4 +8,13 @@ export declare function renderInferredTypes(entity: MetaObject): Code;
|
|
|
8
8
|
* Returns null if the entity has no enum fields.
|
|
9
9
|
*/
|
|
10
10
|
export declare function renderEnumTypeAliases(entity: MetaObject): Code | null;
|
|
11
|
+
/**
|
|
12
|
+
* Emit a structural `interface <Name> { ... }` for a value-only object.
|
|
13
|
+
*
|
|
14
|
+
* Optional fields use `name?: T` (matching the Zod `.optional()` inference
|
|
15
|
+
* `T | undefined`) instead of `name?: T | null`. Value objects never round-
|
|
16
|
+
* trip through Drizzle nullable columns, so the null-bridge is unnecessary
|
|
17
|
+
* here — and forces consumers into a residual cast at the call site.
|
|
18
|
+
*/
|
|
19
|
+
export declare function renderValueObjectInterface(entity: MetaObject): Code;
|
|
11
20
|
//# sourceMappingURL=inferred-types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inferred-types.d.ts","sourceRoot":"","sources":["../../src/templates/inferred-types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"inferred-types.d.ts","sourceRoot":"","sources":["../../src/templates/inferred-types.ts"],"names":[],"mappings":"AASA,OAAO,EAAuB,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,0BAA0B,CAAC;AAyBtE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAW5D;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAyBrE;AA+DD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAkBnE"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
// Inferred types template — emits Drizzle's InferSelectModel / InferInsertModel type aliases,
|
|
2
2
|
// plus named union types for field.enum fields.
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
//
|
|
4
|
+
// Also emits the structural TS interface for value-only objects (metaobjects
|
|
5
|
+
// with no writable source.rdb). That path side-steps Drizzle entirely: the
|
|
6
|
+
// interface is computed directly from the field tree, with `name?: T` for
|
|
7
|
+
// optional fields (matching Zod's `.optional()` inference — `T | undefined` —
|
|
8
|
+
// without the superfluous `| null` that Drizzle nullable columns introduce).
|
|
9
|
+
import { code, imp, joinCode } from "ts-poet";
|
|
10
|
+
import { FIELD_SUBTYPE_ENUM, FIELD_SUBTYPE_OBJECT, FIELD_SUBTYPE_STRING, FIELD_SUBTYPE_INT, FIELD_SUBTYPE_SHORT, FIELD_SUBTYPE_BYTE, FIELD_SUBTYPE_LONG, FIELD_SUBTYPE_DOUBLE, FIELD_SUBTYPE_FLOAT, FIELD_SUBTYPE_DECIMAL, FIELD_SUBTYPE_CURRENCY, FIELD_SUBTYPE_BOOLEAN, FIELD_SUBTYPE_DATE, FIELD_SUBTYPE_TIME, FIELD_SUBTYPE_TIMESTAMP, FIELD_SUBTYPE_CLASS, FIELD_ATTR_REQUIRED, FIELD_ATTR_OBJECT_REF, } from "@metaobjectsdev/metadata";
|
|
5
11
|
import { variableNameFromEntity, toPascalCase } from "../naming.js";
|
|
6
12
|
import { enumValues } from "../enum-meta.js";
|
|
7
13
|
import { renderDocsFor } from "./jsdoc.js";
|
|
@@ -46,4 +52,84 @@ export function renderEnumTypeAliases(entity) {
|
|
|
46
52
|
}
|
|
47
53
|
return lines.length > 0 ? code `${lines.join("\n")}` : null;
|
|
48
54
|
}
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Value-object interface emitter
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
const SCALAR_TS_BY_SUBTYPE = {
|
|
59
|
+
[FIELD_SUBTYPE_STRING]: "string",
|
|
60
|
+
[FIELD_SUBTYPE_CLASS]: "string",
|
|
61
|
+
[FIELD_SUBTYPE_INT]: "number",
|
|
62
|
+
[FIELD_SUBTYPE_SHORT]: "number",
|
|
63
|
+
[FIELD_SUBTYPE_BYTE]: "number",
|
|
64
|
+
[FIELD_SUBTYPE_LONG]: "number",
|
|
65
|
+
[FIELD_SUBTYPE_DOUBLE]: "number",
|
|
66
|
+
[FIELD_SUBTYPE_FLOAT]: "number",
|
|
67
|
+
[FIELD_SUBTYPE_DECIMAL]: "number",
|
|
68
|
+
[FIELD_SUBTYPE_CURRENCY]: "number",
|
|
69
|
+
[FIELD_SUBTYPE_BOOLEAN]: "boolean",
|
|
70
|
+
[FIELD_SUBTYPE_DATE]: "string",
|
|
71
|
+
[FIELD_SUBTYPE_TIME]: "string",
|
|
72
|
+
[FIELD_SUBTYPE_TIMESTAMP]: "string",
|
|
73
|
+
};
|
|
74
|
+
/** Type-alias name for a field.enum, mirroring renderEnumTypeAliases. */
|
|
75
|
+
function enumTypeAliasName(entity, field) {
|
|
76
|
+
const superField = field.resolveSuper();
|
|
77
|
+
return superField !== undefined
|
|
78
|
+
? toPascalCase(superField.name)
|
|
79
|
+
: `${entity.name}${toPascalCase(field.name)}`;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* One-line TS type expression for a field on a value-only object.
|
|
83
|
+
* Returns a `Code` so cross-module `field.object` refs can be hoisted via
|
|
84
|
+
* ts-poet `imp(...)` — matching how the Zod emitter hoists `<Ref>InsertSchema`.
|
|
85
|
+
*/
|
|
86
|
+
function valueObjectFieldType(entity, field) {
|
|
87
|
+
// field.object: import the referenced TS interface from its sibling module
|
|
88
|
+
// so ts-poet hoists the import. Mirrors zod-validators.ts's `<Ref>InsertSchema`
|
|
89
|
+
// import strategy, just for the type alias instead of the schema constant.
|
|
90
|
+
if (field.subType === FIELD_SUBTYPE_OBJECT) {
|
|
91
|
+
const ref = field.ownAttr(FIELD_ATTR_OBJECT_REF);
|
|
92
|
+
if (typeof ref === "string" && ref.length > 0) {
|
|
93
|
+
const refImp = imp(`${ref}@./${ref}.js`);
|
|
94
|
+
return field.isArray ? code `${refImp}[]` : code `${refImp}`;
|
|
95
|
+
}
|
|
96
|
+
return field.isArray ? code `unknown[]` : code `unknown`;
|
|
97
|
+
}
|
|
98
|
+
// field.enum: use the same type-alias name as renderEnumTypeAliases emits.
|
|
99
|
+
if (field.subType === FIELD_SUBTYPE_ENUM) {
|
|
100
|
+
const values = enumValues(field);
|
|
101
|
+
if (values !== undefined) {
|
|
102
|
+
const alias = enumTypeAliasName(entity, field);
|
|
103
|
+
return field.isArray ? code `${alias}[]` : code `${alias}`;
|
|
104
|
+
}
|
|
105
|
+
return field.isArray ? code `string[]` : code `string`;
|
|
106
|
+
}
|
|
107
|
+
const scalar = SCALAR_TS_BY_SUBTYPE[field.subType] ?? "unknown";
|
|
108
|
+
return field.isArray ? code `${scalar}[]` : code `${scalar}`;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Emit a structural `interface <Name> { ... }` for a value-only object.
|
|
112
|
+
*
|
|
113
|
+
* Optional fields use `name?: T` (matching the Zod `.optional()` inference
|
|
114
|
+
* `T | undefined`) instead of `name?: T | null`. Value objects never round-
|
|
115
|
+
* trip through Drizzle nullable columns, so the null-bridge is unnecessary
|
|
116
|
+
* here — and forces consumers into a residual cast at the call site.
|
|
117
|
+
*/
|
|
118
|
+
export function renderValueObjectInterface(entity) {
|
|
119
|
+
const docs = renderDocsFor(entity);
|
|
120
|
+
const docsPrefix = docs ? `${docs}\n` : "";
|
|
121
|
+
const lines = [];
|
|
122
|
+
for (const field of entity.fields()) {
|
|
123
|
+
const required = field.ownAttr(FIELD_ATTR_REQUIRED) === true;
|
|
124
|
+
const optional = required ? "" : "?";
|
|
125
|
+
const tsType = valueObjectFieldType(entity, field);
|
|
126
|
+
lines.push(code ` ${field.name}${optional}: ${tsType};`);
|
|
127
|
+
}
|
|
128
|
+
// joinCode with "\n" interpolates each Code segment on its own line and
|
|
129
|
+
// keeps the imp() registrations intact so ts-poet hoists the imports.
|
|
130
|
+
return code `${docsPrefix}export interface ${entity.name} {
|
|
131
|
+
${joinCode(lines, { on: "\n" })}
|
|
132
|
+
}
|
|
133
|
+
`;
|
|
134
|
+
}
|
|
49
135
|
//# sourceMappingURL=inferred-types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inferred-types.js","sourceRoot":"","sources":["../../src/templates/inferred-types.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,gDAAgD;
|
|
1
|
+
{"version":3,"file":"inferred-types.js","sourceRoot":"","sources":["../../src/templates/inferred-types.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,gDAAgD;AAChD,EAAE;AACF,6EAA6E;AAC7E,2EAA2E;AAC3E,0EAA0E;AAC1E,8EAA8E;AAC9E,6EAA6E;AAE7E,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAa,MAAM,SAAS,CAAC;AAEzD,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,sBAAsB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,MAAM,UAAU,mBAAmB,CAAC,MAAkB;IACpD,MAAM,OAAO,GAAG,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,GAAG,CAAC,8BAA8B,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,GAAG,CAAC,8BAA8B,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3C,OAAO,IAAI,CAAA;EACX,UAAU,eAAe,MAAM,CAAC,IAAI,MAAM,SAAS,WAAW,OAAO;cACzD,MAAM,CAAC,IAAI,YAAY,SAAS,WAAW,OAAO;cAClD,MAAM,CAAC,IAAI,oBAAoB,MAAM,CAAC,IAAI;CACvD,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAkB;IACtD,uFAAuF;IACvF,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QACpC,IAAI,KAAK,CAAC,OAAO,KAAK,kBAAkB;YAAE,SAAS;QAEnD,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,SAAS;YAAE,SAAS;QAEnC,8BAA8B;QAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,UAAU,KAAK,SAAS;YACvC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC;YAC/B,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAEhD,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS;QACjC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEnB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/D,KAAK,CAAC,IAAI,CAAC,eAAe,QAAQ,MAAM,KAAK,GAAG,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7D,CAAC;AAED,8EAA8E;AAC9E,iCAAiC;AACjC,8EAA8E;AAE9E,MAAM,oBAAoB,GAA2B;IACnD,CAAC,oBAAoB,CAAC,EAAE,QAAQ;IAChC,CAAC,mBAAmB,CAAC,EAAE,QAAQ;IAC/B,CAAC,iBAAiB,CAAC,EAAE,QAAQ;IAC7B,CAAC,mBAAmB,CAAC,EAAE,QAAQ;IAC/B,CAAC,kBAAkB,CAAC,EAAE,QAAQ;IAC9B,CAAC,kBAAkB,CAAC,EAAE,QAAQ;IAC9B,CAAC,oBAAoB,CAAC,EAAE,QAAQ;IAChC,CAAC,mBAAmB,CAAC,EAAE,QAAQ;IAC/B,CAAC,qBAAqB,CAAC,EAAE,QAAQ;IACjC,CAAC,sBAAsB,CAAC,EAAE,QAAQ;IAClC,CAAC,qBAAqB,CAAC,EAAE,SAAS;IAClC,CAAC,kBAAkB,CAAC,EAAE,QAAQ;IAC9B,CAAC,kBAAkB,CAAC,EAAE,QAAQ;IAC9B,CAAC,uBAAuB,CAAC,EAAE,QAAQ;CACpC,CAAC;AAEF,yEAAyE;AACzE,SAAS,iBAAiB,CAAC,MAAkB,EAAE,KAAgB;IAC7D,MAAM,UAAU,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;IACxC,OAAO,UAAU,KAAK,SAAS;QAC7B,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC;QAC/B,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,SAAS,oBAAoB,CAAC,MAAkB,EAAE,KAAgB;IAChE,2EAA2E;IAC3E,gFAAgF;IAChF,2EAA2E;IAC3E,IAAI,KAAK,CAAC,OAAO,KAAK,oBAAoB,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;QACjD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,MAAM,GAAG,KAAK,CAAC,CAAC;YACzC,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,GAAG,MAAM,EAAE,CAAC;QAC7D,CAAC;QACD,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,WAAW,CAAC,CAAC,CAAC,IAAI,CAAA,SAAS,CAAC;IACzD,CAAC;IAED,2EAA2E;IAC3E,IAAI,KAAK,CAAC,OAAO,KAAK,kBAAkB,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC/C,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,GAAG,KAAK,EAAE,CAAC;QAC3D,CAAC;QACD,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,UAAU,CAAC,CAAC,CAAC,IAAI,CAAA,QAAQ,CAAC;IACvD,CAAC;IAED,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC;IAChE,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAA,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA,GAAG,MAAM,EAAE,CAAC;AAC7D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,0BAA0B,CAAC,MAAkB;IAC3D,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAE3C,MAAM,KAAK,GAAW,EAAE,CAAC;IACzB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC,KAAK,IAAI,CAAC;QAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QACrC,MAAM,MAAM,GAAG,oBAAoB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAA,KAAK,KAAK,CAAC,IAAI,GAAG,QAAQ,KAAK,MAAM,GAAG,CAAC,CAAC;IAC3D,CAAC;IAED,wEAAwE;IACxE,sEAAsE;IACtE,OAAO,IAAI,CAAA,GAAG,UAAU,oBAAoB,MAAM,CAAC,IAAI;EACvD,QAAQ,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;;CAE9B,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type MetaData } from "@metaobjectsdev/metadata";
|
|
2
|
+
/**
|
|
3
|
+
* Render the full output-parser file for one `template.output` node.
|
|
4
|
+
* Throws if the template isn't found, isn't a template.output, or its
|
|
5
|
+
* @payloadRef doesn't resolve to an object.value.
|
|
6
|
+
*/
|
|
7
|
+
export declare function renderOutputParser(root: MetaData, templateName: string): string;
|
|
8
|
+
//# sourceMappingURL=output-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-parser.d.ts","sourceRoot":"","sources":["../../src/templates/output-parser.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,KAAK,QAAQ,EAQd,MAAM,0BAA0B,CAAC;AAyDlC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CA6D/E"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// server/typescript/packages/codegen-ts/src/templates/output-parser.ts
|
|
2
|
+
//
|
|
3
|
+
// Per-template renderer for template.output codegen. Walks the @payloadRef's
|
|
4
|
+
// value-object into a Zod schema and emits a dual-API parser (parse + safeParse)
|
|
5
|
+
// alongside the schema. The emitted file is self-contained: it derives a
|
|
6
|
+
// local data type via `z.infer<typeof Schema>` and exports it as
|
|
7
|
+
// `<TemplateName>Data`. Consumers wiring `promptRender()` get a structurally
|
|
8
|
+
// identical payload-VO interface in `prompts.ts`; either type can be used
|
|
9
|
+
// interchangeably with parse results.
|
|
10
|
+
import { TYPE_OBJECT, TYPE_FIELD, TYPE_TEMPLATE, TEMPLATE_SUBTYPE_OUTPUT, FIELD_SUBTYPE_OBJECT, FIELD_ATTR_OBJECT_REF, TEMPLATE_ATTR_PAYLOAD_REF, } from "@metaobjectsdev/metadata";
|
|
11
|
+
const SCALAR_ZOD = {
|
|
12
|
+
string: "z.string()",
|
|
13
|
+
class: "z.string()",
|
|
14
|
+
int: "z.number().int()",
|
|
15
|
+
short: "z.number().int()",
|
|
16
|
+
byte: "z.number().int()",
|
|
17
|
+
long: "z.number().int()",
|
|
18
|
+
double: "z.number()",
|
|
19
|
+
float: "z.number()",
|
|
20
|
+
boolean: "z.boolean()",
|
|
21
|
+
};
|
|
22
|
+
function findObject(root, name) {
|
|
23
|
+
return root.ownChildren().find((c) => c.type === TYPE_OBJECT && c.name === name);
|
|
24
|
+
}
|
|
25
|
+
function findTemplate(root, name) {
|
|
26
|
+
return root.ownChildren().find((c) => c.type === TYPE_TEMPLATE && c.name === name);
|
|
27
|
+
}
|
|
28
|
+
/** Render the Zod expression for a single field; recurses on @objectRef. */
|
|
29
|
+
function fieldZod(field, root, seen, depth) {
|
|
30
|
+
// isArray is a native (reserved) property on MetaData, not an attr.
|
|
31
|
+
const isArray = field.isArray === true;
|
|
32
|
+
let base;
|
|
33
|
+
if (field.subType === FIELD_SUBTYPE_OBJECT) {
|
|
34
|
+
const refName = field.ownAttr(FIELD_ATTR_OBJECT_REF);
|
|
35
|
+
if (typeof refName !== "string") {
|
|
36
|
+
base = "z.unknown()";
|
|
37
|
+
}
|
|
38
|
+
else if (seen.has(refName)) {
|
|
39
|
+
// Cycle guard — emit unknown for self-references (rare; lazy schemas not in scope for v1).
|
|
40
|
+
base = "z.unknown()";
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const inner = findObject(root, refName);
|
|
44
|
+
base = inner ? renderObjectSchema(inner, root, new Set(seen).add(refName), depth + 1) : "z.unknown()";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
base = SCALAR_ZOD[field.subType] ?? "z.unknown()";
|
|
49
|
+
}
|
|
50
|
+
return isArray ? `z.array(${base})` : base;
|
|
51
|
+
}
|
|
52
|
+
/** Render a `z.object({ ... })` for an object.value node.
|
|
53
|
+
* At depth 0 the schema starts at column 0 (consumer's `const Foo = z.object({`),
|
|
54
|
+
* so fields sit at 2 spaces and the closing `})` at 0 spaces — matching the
|
|
55
|
+
* surrounding `const NameSchema = ...` statement's indent. Nested schemas
|
|
56
|
+
* step in two spaces per depth level. */
|
|
57
|
+
function renderObjectSchema(vo, root, seen, depth) {
|
|
58
|
+
const fields = vo.children().filter((c) => c.type === TYPE_FIELD);
|
|
59
|
+
const fieldIndent = " ".repeat(depth + 1);
|
|
60
|
+
const closeIndent = " ".repeat(depth);
|
|
61
|
+
const lines = fields.map((f) => `${fieldIndent}${f.name}: ${fieldZod(f, root, seen, depth)},`);
|
|
62
|
+
return `z.object({\n${lines.join("\n")}\n${closeIndent}})`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Render the full output-parser file for one `template.output` node.
|
|
66
|
+
* Throws if the template isn't found, isn't a template.output, or its
|
|
67
|
+
* @payloadRef doesn't resolve to an object.value.
|
|
68
|
+
*/
|
|
69
|
+
export function renderOutputParser(root, templateName) {
|
|
70
|
+
const tmpl = findTemplate(root, templateName);
|
|
71
|
+
if (!tmpl) {
|
|
72
|
+
throw new Error(`template "${templateName}" not found in metadata root`);
|
|
73
|
+
}
|
|
74
|
+
if (tmpl.subType !== TEMPLATE_SUBTYPE_OUTPUT) {
|
|
75
|
+
throw new Error(`template "${templateName}" is not a template.output (got subtype "${tmpl.subType}")`);
|
|
76
|
+
}
|
|
77
|
+
const payloadRef = tmpl.ownAttr(TEMPLATE_ATTR_PAYLOAD_REF);
|
|
78
|
+
if (typeof payloadRef !== "string") {
|
|
79
|
+
throw new Error(`template "${templateName}" missing @payloadRef`);
|
|
80
|
+
}
|
|
81
|
+
const vo = findObject(root, payloadRef);
|
|
82
|
+
if (!vo) {
|
|
83
|
+
throw new Error(`template "${templateName}" @payloadRef "${payloadRef}" not found in metadata root`);
|
|
84
|
+
}
|
|
85
|
+
const schema = renderObjectSchema(vo, root, new Set([payloadRef]), 0);
|
|
86
|
+
const schemaName = `${templateName}Schema`;
|
|
87
|
+
const dataName = `${templateName}Data`;
|
|
88
|
+
const errorName = `${templateName}ValidationError`;
|
|
89
|
+
const parseName = `parse${templateName}`;
|
|
90
|
+
const safeParseName = `safeParse${templateName}`;
|
|
91
|
+
return `import { z } from "zod";
|
|
92
|
+
|
|
93
|
+
const ${schemaName} = ${schema};
|
|
94
|
+
|
|
95
|
+
export type ${dataName} = z.infer<typeof ${schemaName}>;
|
|
96
|
+
export type ${errorName} = z.ZodError;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Parse an LLM response into a typed ${dataName}.
|
|
100
|
+
* @throws ZodError on validation failure.
|
|
101
|
+
*/
|
|
102
|
+
export function ${parseName}(text: string): ${dataName} {
|
|
103
|
+
return ${schemaName}.parse(JSON.parse(text));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Parse an LLM response with explicit error handling (Result-style).
|
|
108
|
+
* Does not throw on validation failure.
|
|
109
|
+
*/
|
|
110
|
+
export function ${safeParseName}(
|
|
111
|
+
text: string,
|
|
112
|
+
): { success: true; data: ${dataName} } | { success: false; error: ${errorName} } {
|
|
113
|
+
let parsed: unknown;
|
|
114
|
+
try {
|
|
115
|
+
parsed = JSON.parse(text);
|
|
116
|
+
} catch (err) {
|
|
117
|
+
return {
|
|
118
|
+
success: false,
|
|
119
|
+
error: new z.ZodError([{ code: "custom", path: [], message: \`invalid JSON: \${(err as Error).message}\` }]),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
const result = ${schemaName}.safeParse(parsed);
|
|
123
|
+
return result.success
|
|
124
|
+
? { success: true, data: result.data }
|
|
125
|
+
: { success: false, error: result.error };
|
|
126
|
+
}
|
|
127
|
+
`;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=output-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-parser.js","sourceRoot":"","sources":["../../src/templates/output-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@ export interface ProjectionDeclOpts {
|
|
|
14
14
|
*
|
|
15
15
|
* @param projection The projection entity (has a source[dbView] child).
|
|
16
16
|
* @param root The loader's root (all top-level objects as direct children,
|
|
17
|
-
* from `MetaDataLoader.load()`
|
|
17
|
+
* from `MetaDataLoader.load()` or `MetaDataLoader.fromDirectory()` as `result.root`).
|
|
18
18
|
* @param opts Column naming strategy + dialect.
|
|
19
19
|
*/
|
|
20
20
|
export declare function renderProjectionDecl(projection: MetaObject, root: MetaRoot, opts: ProjectionDeclOpts): string;
|
|
@@ -40,7 +40,7 @@ function pathFromProjectionName(name) {
|
|
|
40
40
|
*
|
|
41
41
|
* @param projection The projection entity (has a source[dbView] child).
|
|
42
42
|
* @param root The loader's root (all top-level objects as direct children,
|
|
43
|
-
* from `MetaDataLoader.load()`
|
|
43
|
+
* from `MetaDataLoader.load()` or `MetaDataLoader.fromDirectory()` as `result.root`).
|
|
44
44
|
* @param opts Column naming strategy + dialect.
|
|
45
45
|
*/
|
|
46
46
|
export function renderProjectionDecl(projection, root, opts) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries-file.d.ts","sourceRoot":"","sources":["../../src/templates/queries-file.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAY1D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"queries-file.d.ts","sourceRoot":"","sources":["../../src/templates/queries-file.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAY1D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,MAAM,CAoD7E"}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { code, joinCode } from "ts-poet";
|
|
4
4
|
import { MetaObject } from "@metaobjectsdev/metadata";
|
|
5
5
|
import {} from "../render-context.js";
|
|
6
|
-
import { entityModuleSpecifier
|
|
6
|
+
import { entityModuleSpecifier } from "../import-path.js";
|
|
7
7
|
import { renderFindByIdFn, renderListFn, renderCreateFn, renderUpdateFn, renderDeleteByIdFn, } from "./queries.js";
|
|
8
8
|
import { variableNameFromEntity } from "../naming.js";
|
|
9
9
|
import { GENERATED_HEADER } from "../constants.js";
|
|
@@ -12,12 +12,23 @@ export function renderQueriesFile(obj, ctx) {
|
|
|
12
12
|
// Import the entity's own file. Same target → relative "./Entity"; cross
|
|
13
13
|
// target → importBase-qualified package path.
|
|
14
14
|
const entityFileName = entityModuleSpecifier(ctx.selfTarget, ctx.entityModuleTarget, obj.package, entityName, ctx.extStyle);
|
|
15
|
-
const dbImportSpec = relativeModuleSpecifier(ctx.outputLayout, obj.package, ctx.dbImport);
|
|
16
15
|
const varName = variableNameFromEntity(entityName);
|
|
17
|
-
//
|
|
16
|
+
// The persistence-context `db` is parameter-passed into every generated CRUD
|
|
17
|
+
// helper (ADR-0008). Emit the dialect-correct Drizzle type alias so the
|
|
18
|
+
// signatures `findXxx(db: Db, ...)` typecheck without the consumer importing
|
|
19
|
+
// anything to construct one. Consumers pass any compatible Drizzle instance.
|
|
20
|
+
const dbTypeImport = ctx.dialect === "postgres"
|
|
21
|
+
? `import type { NodePgDatabase } from "drizzle-orm/node-postgres";`
|
|
22
|
+
: `import type { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core";`;
|
|
23
|
+
const dbTypeAlias = ctx.dialect === "postgres"
|
|
24
|
+
? `type Db = NodePgDatabase<Record<string, never>>;`
|
|
25
|
+
: `type Db = BaseSQLiteDatabase<"async", Record<string, never>>;`;
|
|
26
|
+
// Literal imports (Db type + entity types) live in a code block so they sort
|
|
18
27
|
// alongside ts-poet's hoisted imp() imports at the top of the body.
|
|
19
28
|
const literalImports = code `
|
|
20
|
-
|
|
29
|
+
${dbTypeImport}
|
|
30
|
+
${dbTypeAlias}
|
|
31
|
+
|
|
21
32
|
import { ${varName}, type ${entityName}, ${entityName}InsertSchema } from ${JSON.stringify(entityFileName)};
|
|
22
33
|
`;
|
|
23
34
|
const sections = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries-file.js","sourceRoot":"","sources":["../../src/templates/queries-file.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,kFAAkF;AAElF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAa,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAsB,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"queries-file.js","sourceRoot":"","sources":["../../src/templates/queries-file.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,kFAAkF;AAElF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAa,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAsB,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,cAAc,EACd,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,UAAU,iBAAiB,CAAC,GAAe,EAAE,GAAkB;IACnE,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC;IAC5B,yEAAyE;IACzE,8CAA8C;IAC9C,MAAM,cAAc,GAAG,qBAAqB,CAC1C,GAAG,CAAC,UAAU,EACd,GAAG,CAAC,kBAAkB,EACtB,GAAG,CAAC,OAAO,EACX,UAAU,EACV,GAAG,CAAC,QAAQ,CACb,CAAC;IACF,MAAM,OAAO,GAAG,sBAAsB,CAAC,UAAU,CAAC,CAAC;IAEnD,6EAA6E;IAC7E,wEAAwE;IACxE,6EAA6E;IAC7E,6EAA6E;IAC7E,MAAM,YAAY,GAChB,GAAG,CAAC,OAAO,KAAK,UAAU;QACxB,CAAC,CAAC,kEAAkE;QACpE,CAAC,CAAC,oEAAoE,CAAC;IAC3E,MAAM,WAAW,GACf,GAAG,CAAC,OAAO,KAAK,UAAU;QACxB,CAAC,CAAC,kDAAkD;QACpD,CAAC,CAAC,+DAA+D,CAAC;IAEtE,6EAA6E;IAC7E,oEAAoE;IACpE,MAAM,cAAc,GAAG,IAAI,CAAA;EAC3B,YAAY;EACZ,WAAW;;WAEF,OAAO,UAAU,UAAU,KAAK,UAAU,uBAAuB,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC;CACzG,CAAC;IAEA,MAAM,QAAQ,GAAW;QACvB,cAAc;QACd,gBAAgB,CAAC,GAAG,EAAE,GAAG,CAAC;QAC1B,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC;QACtB,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC;QACxB,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC;QACxB,kBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC;KAC7B,CAAC;IAEF,4EAA4E;IAC5E,kCAAkC;IAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACzD,MAAM,MAAM,GACV,MAAM,gBAAgB,mBAAmB;QACzC,uBAAuB,UAAU,KAAK,GAAG,CAAC,GAAG,EAAE,KAAK;QACpD,oBAAoB,UAAU,mEAAmE,CAAC;IACpG,OAAO,MAAM,GAAG,IAAI,CAAC;AACvB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/templates/queries.ts"],"names":[],"mappings":"AAGA,OAAO,EAAa,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/templates/queries.ts"],"names":[],"mappings":"AAGA,OAAO,EAAa,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAqB1D,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,IAAI,CAc7E;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAe1E;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,aAAa,GAAG,IAAI,CAc5E;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,IAAI,CAgB3E;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,IAAI,CAe/E"}
|
|
@@ -2,11 +2,7 @@
|
|
|
2
2
|
// Each returns a ts-poet Code block; composed into a file by queries-file.ts.
|
|
3
3
|
import { code, imp } from "ts-poet";
|
|
4
4
|
import { IDENTITY_ATTR_FIELDS } from "@metaobjectsdev/metadata";
|
|
5
|
-
import { variableNameFromEntity,
|
|
6
|
-
/** Derive a stable prepared statement name. Deterministic from entity + field names. */
|
|
7
|
-
function prepareName(prefix, entitySnakeName, fieldDbName) {
|
|
8
|
-
return `${prefix}_${entitySnakeName}_by_${fieldDbName}`;
|
|
9
|
-
}
|
|
5
|
+
import { variableNameFromEntity, pluralize } from "../naming.js";
|
|
10
6
|
/** Get the PK field name and its TS type for a given entity. */
|
|
11
7
|
function getPkInfo(entity, ctx) {
|
|
12
8
|
// Use primaryIdentity() to find the primary identity (may be inherited from extends:/super:).
|
|
@@ -27,28 +23,12 @@ export function renderFindByIdFn(entity, ctx) {
|
|
|
27
23
|
const varName = variableNameFromEntity(entity.name);
|
|
28
24
|
const entityName = entity.name;
|
|
29
25
|
const singularVar = entityName.charAt(0).toLowerCase() + entityName.slice(1);
|
|
30
|
-
const entitySnakeName = toSnakeCase(entityName);
|
|
31
26
|
const { fieldName: pkField, tsType: pkType } = getPkInfo(entity, ctx);
|
|
32
|
-
const pkSnakeName = toSnakeCase(pkField);
|
|
33
|
-
const prepName = prepareName("find", entitySnakeName, pkSnakeName);
|
|
34
27
|
const fnName = `find${entityName}ById`;
|
|
35
|
-
const prepVarName = `${fnName}Prepared`;
|
|
36
28
|
const eqSym = imp("eq@drizzle-orm");
|
|
37
|
-
const sqlSym = imp("sql@drizzle-orm");
|
|
38
|
-
const baseVarName = `${fnName}Base`;
|
|
39
|
-
// Drizzle's `.prepare()` signature differs by dialect:
|
|
40
|
-
// - Postgres: prepare(name) — the name is used by the pg driver to cache the plan
|
|
41
|
-
// - SQLite: prepare() — no name; the name arg was removed in drizzle-orm 0.41+
|
|
42
|
-
const prepArg = ctx.dialect === "postgres" ? `"${prepName}"` : "";
|
|
43
29
|
return code `
|
|
44
|
-
|
|
45
|
-
.select()
|
|
46
|
-
.from(${varName})
|
|
47
|
-
.where(${eqSym}(${varName}.${pkField}, ${sqlSym}.placeholder(${JSON.stringify(pkField)})));
|
|
48
|
-
const ${prepVarName} = ${baseVarName}.prepare(${prepArg});
|
|
49
|
-
|
|
50
|
-
export async function ${fnName}(${pkField}: ${pkType}): Promise<${entityName} | null> {
|
|
51
|
-
const [${singularVar}] = await ${prepVarName}.execute({ ${pkField} });
|
|
30
|
+
export async function ${fnName}(db: Db, ${pkField}: ${pkType}): Promise<${entityName} | null> {
|
|
31
|
+
const [${singularVar}] = await db.select().from(${varName}).where(${eqSym}(${varName}.${pkField}, ${pkField})).limit(1);
|
|
52
32
|
return ${singularVar} ?? null;
|
|
53
33
|
}
|
|
54
34
|
`;
|
|
@@ -60,7 +40,7 @@ export function renderListFn(entity, _ctx) {
|
|
|
60
40
|
// (e.g., "Category" -> "Categories", not "Categorys").
|
|
61
41
|
const fnName = `list${pluralize(entityName)}`;
|
|
62
42
|
return code `
|
|
63
|
-
export async function ${fnName}(opts?: { limit?: number; offset?: number }): Promise<${entityName}[]> {
|
|
43
|
+
export async function ${fnName}(db: Db, opts?: { limit?: number; offset?: number }): Promise<${entityName}[]> {
|
|
64
44
|
let q = db.select().from(${varName}).$dynamic();
|
|
65
45
|
if (opts?.limit !== undefined) q = q.limit(opts.limit);
|
|
66
46
|
if (opts?.offset !== undefined) q = q.offset(opts.offset);
|
|
@@ -75,7 +55,7 @@ export function renderCreateFn(entity, _ctx) {
|
|
|
75
55
|
const fnName = `create${entityName}`;
|
|
76
56
|
const schemaName = `${entityName}InsertSchema`;
|
|
77
57
|
return code `
|
|
78
|
-
export async function ${fnName}(data: unknown): Promise<${entityName}> {
|
|
58
|
+
export async function ${fnName}(db: Db, data: unknown): Promise<${entityName}> {
|
|
79
59
|
const validated = ${schemaName}.parse(data);
|
|
80
60
|
const [${singularVar}] = await db.insert(${varName}).values(validated).returning();
|
|
81
61
|
return ${singularVar}!;
|
|
@@ -91,7 +71,7 @@ export function renderUpdateFn(entity, ctx) {
|
|
|
91
71
|
const schemaName = `${entityName}InsertSchema`;
|
|
92
72
|
const eqSym = imp("eq@drizzle-orm");
|
|
93
73
|
return code `
|
|
94
|
-
export async function ${fnName}(${pkField}: ${pkType}, data: unknown): Promise<${entityName} | null> {
|
|
74
|
+
export async function ${fnName}(db: Db, ${pkField}: ${pkType}, data: unknown): Promise<${entityName} | null> {
|
|
95
75
|
const validated = ${schemaName}.partial().parse(data);
|
|
96
76
|
const [${singularVar}] = await db.update(${varName}).set(validated).where(${eqSym}(${varName}.${pkField}, ${pkField})).returning();
|
|
97
77
|
return ${singularVar} ?? null;
|
|
@@ -105,10 +85,11 @@ export function renderDeleteByIdFn(entity, ctx) {
|
|
|
105
85
|
const fnName = `delete${entityName}ById`;
|
|
106
86
|
const eqSym = imp("eq@drizzle-orm");
|
|
107
87
|
return code `
|
|
108
|
-
export async function ${fnName}(${pkField}: ${pkType}): Promise<boolean> {
|
|
109
|
-
|
|
110
|
-
//
|
|
111
|
-
|
|
88
|
+
export async function ${fnName}(db: Db, ${pkField}: ${pkType}): Promise<boolean> {
|
|
89
|
+
// Use .returning() unconditionally — supported on SQLite ≥3.35 (covers D1, libsql/Turso)
|
|
90
|
+
// and Postgres. Result is an array of deleted rows; presence implies success.
|
|
91
|
+
const deleted = await db.delete(${varName}).where(${eqSym}(${varName}.${pkField}, ${pkField})).returning();
|
|
92
|
+
return deleted.length > 0;
|
|
112
93
|
}
|
|
113
94
|
`;
|
|
114
95
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/templates/queries.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,8EAA8E;AAE9E,OAAO,EAAE,IAAI,EAAE,GAAG,EAAa,MAAM,SAAS,CAAC;AAE/C,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAEhE,OAAO,EAAE,sBAAsB,EAAE,
|
|
1
|
+
{"version":3,"file":"queries.js","sourceRoot":"","sources":["../../src/templates/queries.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"value-object-file.d.ts","sourceRoot":"","sources":["../../src/templates/value-object-file.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAK3D,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAa7D"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Value-object file composer — emits a streamlined "value-only" module for
|
|
2
|
+
// metaobjects with no writable source.rdb child. Output is just the TS
|
|
3
|
+
// interface + the Zod schema (and enum type aliases when applicable); no
|
|
4
|
+
// Drizzle table, no Infer*Model aliases, no filter allowlists, no constants
|
|
5
|
+
// object.
|
|
6
|
+
//
|
|
7
|
+
// Dispatch: entity-file.ts routes here when hasWritableRdbSource(entity) is
|
|
8
|
+
// false. The entity may still have read-only source.* children (those are
|
|
9
|
+
// handled by the projection path before this one is reached).
|
|
10
|
+
import { joinCode } from "ts-poet";
|
|
11
|
+
import { renderValueObjectInterface, renderEnumTypeAliases } from "./inferred-types.js";
|
|
12
|
+
import { renderInsertSchemaOnly } from "./zod-validators.js";
|
|
13
|
+
import { GENERATED_HEADER } from "../constants.js";
|
|
14
|
+
export function renderValueObjectFile(obj) {
|
|
15
|
+
const enumAliases = renderEnumTypeAliases(obj);
|
|
16
|
+
const sections = [
|
|
17
|
+
renderValueObjectInterface(obj),
|
|
18
|
+
...(enumAliases !== null ? [enumAliases] : []),
|
|
19
|
+
renderInsertSchemaOnly(obj),
|
|
20
|
+
];
|
|
21
|
+
const body = joinCode(sections, { on: "\n" }).toString();
|
|
22
|
+
const header = `// ${GENERATED_HEADER} — DO NOT EDIT.\n` +
|
|
23
|
+
`// Source metadata: ${obj.name} (${obj.fqn()})\n` +
|
|
24
|
+
`// Customize via ${obj.name}.extra.ts in this directory.\n`;
|
|
25
|
+
return header + body;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=value-object-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"value-object-file.js","sourceRoot":"","sources":["../../src/templates/value-object-file.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,uEAAuE;AACvE,yEAAyE;AACzE,4EAA4E;AAC5E,UAAU;AACV,EAAE;AACF,4EAA4E;AAC5E,0EAA0E;AAC1E,8DAA8D;AAE9D,OAAO,EAAE,QAAQ,EAAa,MAAM,SAAS,CAAC;AAE9C,OAAO,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,UAAU,qBAAqB,CAAC,GAAe;IACnD,MAAM,WAAW,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAW;QACvB,0BAA0B,CAAC,GAAG,CAAC;QAC/B,GAAG,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C,sBAAsB,CAAC,GAAG,CAAC;KAC5B,CAAC;IACF,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACzD,MAAM,MAAM,GACV,MAAM,gBAAgB,mBAAmB;QACzC,uBAAuB,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,GAAG,EAAE,KAAK;QAClD,oBAAoB,GAAG,CAAC,IAAI,gCAAgC,CAAC;IAC/D,OAAO,MAAM,GAAG,IAAI,CAAC;AACvB,CAAC"}
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { type Code } from "ts-poet";
|
|
2
2
|
import { MetaObject } from "@metaobjectsdev/metadata";
|
|
3
|
+
/**
|
|
4
|
+
* Emit ONLY the `<Name>InsertSchema`. Used by the value-object file emitter
|
|
5
|
+
* for metaobjects with no writable source.rdb — those have no PATCH/update
|
|
6
|
+
* semantics, so emitting an UpdateSchema would be misleading.
|
|
7
|
+
*
|
|
8
|
+
* The schema name is kept as `<Name>InsertSchema` even for pure value objects
|
|
9
|
+
* so consumer imports don't churn. A future polish PR could add a `<Name>Schema`
|
|
10
|
+
* alias for clarity.
|
|
11
|
+
*/
|
|
12
|
+
export declare function renderInsertSchemaOnly(obj: MetaObject): Code;
|
|
3
13
|
export declare function renderZodValidators(obj: MetaObject): Code;
|
|
4
14
|
//# sourceMappingURL=zod-validators.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zod-validators.d.ts","sourceRoot":"","sources":["../../src/templates/zod-validators.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"zod-validators.d.ts","sourceRoot":"","sources":["../../src/templates/zod-validators.ts"],"names":[],"mappings":"AAWA,OAAO,EAAuB,KAAK,IAAI,EAAE,MAAM,SAAS,CAAC;AACzD,OAAO,EAAE,UAAU,EAAa,MAAM,0BAA0B,CAAC;AA+BjE;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CA4B5D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAqDzD"}
|