@metaobjectsdev/codegen-ts 0.8.1 → 0.9.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.map +1 -1
- package/dist/column-mapper.js +123 -46
- package/dist/column-mapper.js.map +1 -1
- package/dist/generators/callable-file.d.ts +8 -0
- package/dist/generators/callable-file.d.ts.map +1 -0
- package/dist/generators/callable-file.js +32 -0
- package/dist/generators/callable-file.js.map +1 -0
- package/dist/generators/docs-data-builder.d.ts.map +1 -1
- package/dist/generators/docs-data-builder.js +5 -2
- package/dist/generators/docs-data-builder.js.map +1 -1
- package/dist/generators/extractor-file.d.ts +9 -0
- package/dist/generators/extractor-file.d.ts.map +1 -0
- package/dist/generators/extractor-file.js +45 -0
- package/dist/generators/extractor-file.js.map +1 -0
- package/dist/generators/index.d.ts +3 -0
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +3 -0
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/render-helper-file.d.ts +9 -0
- package/dist/generators/render-helper-file.d.ts.map +1 -0
- package/dist/generators/render-helper-file.js +58 -0
- package/dist/generators/render-helper-file.js.map +1 -0
- package/dist/payload-codegen.d.ts.map +1 -1
- package/dist/payload-codegen.js +42 -8
- package/dist/payload-codegen.js.map +1 -1
- package/dist/projection/extract-view-spec.d.ts.map +1 -1
- package/dist/projection/extract-view-spec.js +11 -3
- package/dist/projection/extract-view-spec.js.map +1 -1
- package/dist/render-engine/framework-provider.d.ts +6 -5
- package/dist/render-engine/framework-provider.d.ts.map +1 -1
- package/dist/render-engine/framework-provider.js +53 -11
- package/dist/render-engine/framework-provider.js.map +1 -1
- package/dist/templates/callable-file.d.ts +8 -0
- package/dist/templates/callable-file.d.ts.map +1 -0
- package/dist/templates/callable-file.js +98 -0
- package/dist/templates/callable-file.js.map +1 -0
- package/dist/templates/extract-delegate-emitter.d.ts +42 -0
- package/dist/templates/extract-delegate-emitter.d.ts.map +1 -0
- package/dist/templates/extract-delegate-emitter.js +339 -0
- package/dist/templates/extract-delegate-emitter.js.map +1 -0
- package/dist/templates/{recover-schema-emitter.d.ts → extract-schema-emitter.d.ts} +2 -2
- package/dist/templates/extract-schema-emitter.d.ts.map +1 -0
- package/dist/templates/{recover-schema-emitter.js → extract-schema-emitter.js} +37 -20
- package/dist/templates/extract-schema-emitter.js.map +1 -0
- package/dist/templates/extractor.d.ts +9 -0
- package/dist/templates/extractor.d.ts.map +1 -0
- package/dist/templates/extractor.js +296 -0
- package/dist/templates/extractor.js.map +1 -0
- package/dist/templates/field-meta.d.ts.map +1 -1
- package/dist/templates/field-meta.js +2 -1
- package/dist/templates/field-meta.js.map +1 -1
- package/dist/templates/filter-type.d.ts.map +1 -1
- package/dist/templates/filter-type.js +8 -5
- package/dist/templates/filter-type.js.map +1 -1
- package/dist/templates/fr010-field-mapping.d.ts +22 -6
- package/dist/templates/fr010-field-mapping.d.ts.map +1 -1
- package/dist/templates/fr010-field-mapping.js +66 -21
- package/dist/templates/fr010-field-mapping.js.map +1 -1
- package/dist/templates/inferred-types.d.ts +15 -1
- package/dist/templates/inferred-types.d.ts.map +1 -1
- package/dist/templates/inferred-types.js +30 -17
- package/dist/templates/inferred-types.js.map +1 -1
- package/dist/templates/output-parser.d.ts.map +1 -1
- package/dist/templates/output-parser.js +98 -34
- package/dist/templates/output-parser.js.map +1 -1
- package/dist/templates/output-prompt.js +2 -2
- package/dist/templates/render-helper.d.ts +14 -0
- package/dist/templates/render-helper.d.ts.map +1 -0
- package/dist/templates/render-helper.js +180 -0
- package/dist/templates/render-helper.js.map +1 -0
- package/dist/templates/zod-validators.d.ts.map +1 -1
- package/dist/templates/zod-validators.js +59 -3
- package/dist/templates/zod-validators.js.map +1 -1
- package/package.json +10 -4
- package/src/column-mapper.ts +128 -45
- package/src/generators/callable-file.ts +44 -0
- package/src/generators/docs-data-builder.ts +5 -1
- package/src/generators/extractor-file.ts +57 -0
- package/src/generators/index.ts +3 -0
- package/src/generators/render-helper-file.ts +74 -0
- package/src/payload-codegen.ts +52 -7
- package/src/projection/extract-view-spec.ts +11 -3
- package/src/render-engine/framework-provider.ts +53 -16
- package/src/templates/callable-file.ts +122 -0
- package/src/templates/extract-delegate-emitter.ts +370 -0
- package/src/templates/{recover-schema-emitter.ts → extract-schema-emitter.ts} +39 -19
- package/src/templates/extractor.ts +333 -0
- package/src/templates/field-meta.ts +2 -0
- package/src/templates/filter-type.ts +7 -5
- package/src/templates/fr010-field-mapping.ts +71 -18
- package/src/templates/inferred-types.ts +32 -18
- package/src/templates/output-parser.ts +108 -35
- package/src/templates/output-prompt.ts +2 -2
- package/src/templates/render-helper.ts +244 -0
- package/src/templates/zod-validators.ts +51 -4
- package/dist/templates/recover-schema-emitter.d.ts.map +0 -1
- package/dist/templates/recover-schema-emitter.js.map +0 -1
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { type Code } from "ts-poet";
|
|
2
|
-
import type { MetaObject } from "@metaobjectsdev/metadata";
|
|
2
|
+
import type { MetaObject, MetaField } from "@metaobjectsdev/metadata";
|
|
3
3
|
export declare function renderInferredTypes(entity: MetaObject): Code;
|
|
4
|
+
/**
|
|
5
|
+
* The string-literal-union type-alias name for a `field.enum` field — the SINGLE
|
|
6
|
+
* source of truth for enum-union naming (reused by the entity inferred-types
|
|
7
|
+
* emitter AND the payload-VO emitter so both agree byte-for-byte).
|
|
8
|
+
*
|
|
9
|
+
* - If the field extends an abstract field.enum (super), use the super field's
|
|
10
|
+
* PascalCase name (so multiple fields sharing one abstract enum collapse to a
|
|
11
|
+
* single alias).
|
|
12
|
+
* - Otherwise use `<Owner><FieldPascal>` for inline enums, where `<Owner>` is the
|
|
13
|
+
* owning object's name (entity OR payload value-object).
|
|
14
|
+
*/
|
|
15
|
+
export declare function enumUnionAliasName(ownerName: string, field: MetaField): string;
|
|
16
|
+
/** The `"A" | "B"` union string for a set of enum member values. */
|
|
17
|
+
export declare function enumUnionString(values: string[]): string;
|
|
4
18
|
/**
|
|
5
19
|
* Emit one `export type <Name> = "A" | "B";` line per field.enum field on the entity.
|
|
6
20
|
* - If the field extends an abstract field.enum (super), use the super field's PascalCase name.
|
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AA0BtE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAW5D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAK9E;AAED,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAmBrE;AA2DD;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAkBnE"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// optional fields (matching Zod's `.optional()` inference — `T | undefined` —
|
|
8
8
|
// without the superfluous `| null` that Drizzle nullable columns introduce).
|
|
9
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";
|
|
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_SUBTYPE_UUID, FIELD_ATTR_REQUIRED, FIELD_ATTR_OBJECT_REF, } from "@metaobjectsdev/metadata";
|
|
11
11
|
import { variableNameFromEntity, toPascalCase } from "../naming.js";
|
|
12
12
|
import { enumValues } from "../enum-meta.js";
|
|
13
13
|
import { renderDocsFor } from "./jsdoc.js";
|
|
@@ -23,6 +23,27 @@ export type ${entity.name}Insert = ${insertSym}<typeof ${varName}>;
|
|
|
23
23
|
export type ${entity.name}Update = Partial<${entity.name}Insert>;
|
|
24
24
|
`;
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* The string-literal-union type-alias name for a `field.enum` field — the SINGLE
|
|
28
|
+
* source of truth for enum-union naming (reused by the entity inferred-types
|
|
29
|
+
* emitter AND the payload-VO emitter so both agree byte-for-byte).
|
|
30
|
+
*
|
|
31
|
+
* - If the field extends an abstract field.enum (super), use the super field's
|
|
32
|
+
* PascalCase name (so multiple fields sharing one abstract enum collapse to a
|
|
33
|
+
* single alias).
|
|
34
|
+
* - Otherwise use `<Owner><FieldPascal>` for inline enums, where `<Owner>` is the
|
|
35
|
+
* owning object's name (entity OR payload value-object).
|
|
36
|
+
*/
|
|
37
|
+
export function enumUnionAliasName(ownerName, field) {
|
|
38
|
+
const superField = field.resolveSuper();
|
|
39
|
+
return superField !== undefined
|
|
40
|
+
? toPascalCase(superField.name)
|
|
41
|
+
: `${ownerName}${toPascalCase(field.name)}`;
|
|
42
|
+
}
|
|
43
|
+
/** The `"A" | "B"` union string for a set of enum member values. */
|
|
44
|
+
export function enumUnionString(values) {
|
|
45
|
+
return values.map((v) => JSON.stringify(v)).join(" | ");
|
|
46
|
+
}
|
|
26
47
|
/**
|
|
27
48
|
* Emit one `export type <Name> = "A" | "B";` line per field.enum field on the entity.
|
|
28
49
|
* - If the field extends an abstract field.enum (super), use the super field's PascalCase name.
|
|
@@ -39,16 +60,11 @@ export function renderEnumTypeAliases(entity) {
|
|
|
39
60
|
const values = enumValues(field);
|
|
40
61
|
if (values === undefined)
|
|
41
62
|
continue;
|
|
42
|
-
|
|
43
|
-
const superField = field.resolveSuper();
|
|
44
|
-
const typeName = superField !== undefined
|
|
45
|
-
? toPascalCase(superField.name)
|
|
46
|
-
: `${entity.name}${toPascalCase(field.name)}`;
|
|
63
|
+
const typeName = enumUnionAliasName(entity.name, field);
|
|
47
64
|
if (seen.has(typeName))
|
|
48
65
|
continue;
|
|
49
66
|
seen.add(typeName);
|
|
50
|
-
|
|
51
|
-
lines.push(`export type ${typeName} = ${union};`);
|
|
67
|
+
lines.push(`export type ${typeName} = ${enumUnionString(values)};`);
|
|
52
68
|
}
|
|
53
69
|
return lines.length > 0 ? code `${lines.join("\n")}` : null;
|
|
54
70
|
}
|
|
@@ -58,26 +74,23 @@ export function renderEnumTypeAliases(entity) {
|
|
|
58
74
|
const SCALAR_TS_BY_SUBTYPE = {
|
|
59
75
|
[FIELD_SUBTYPE_STRING]: "string",
|
|
60
76
|
[FIELD_SUBTYPE_CLASS]: "string",
|
|
77
|
+
[FIELD_SUBTYPE_UUID]: "string",
|
|
61
78
|
[FIELD_SUBTYPE_INT]: "number",
|
|
62
79
|
[FIELD_SUBTYPE_SHORT]: "number",
|
|
63
80
|
[FIELD_SUBTYPE_BYTE]: "number",
|
|
64
81
|
[FIELD_SUBTYPE_LONG]: "number",
|
|
65
82
|
[FIELD_SUBTYPE_DOUBLE]: "number",
|
|
66
83
|
[FIELD_SUBTYPE_FLOAT]: "number",
|
|
67
|
-
|
|
84
|
+
// field.decimal is precision-exact: Drizzle's pg `numeric` column infers as
|
|
85
|
+
// `string` (the driver returns NUMERIC as a string to avoid float rounding),
|
|
86
|
+
// so the value-object/structural-interface scalar mapping must match.
|
|
87
|
+
[FIELD_SUBTYPE_DECIMAL]: "string",
|
|
68
88
|
[FIELD_SUBTYPE_CURRENCY]: "number",
|
|
69
89
|
[FIELD_SUBTYPE_BOOLEAN]: "boolean",
|
|
70
90
|
[FIELD_SUBTYPE_DATE]: "string",
|
|
71
91
|
[FIELD_SUBTYPE_TIME]: "string",
|
|
72
92
|
[FIELD_SUBTYPE_TIMESTAMP]: "string",
|
|
73
93
|
};
|
|
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
94
|
/**
|
|
82
95
|
* One-line TS type expression for a field on a value-only object.
|
|
83
96
|
* Returns a `Code` so cross-module `field.object` refs can be hoisted via
|
|
@@ -99,7 +112,7 @@ function valueObjectFieldType(entity, field) {
|
|
|
99
112
|
if (field.subType === FIELD_SUBTYPE_ENUM) {
|
|
100
113
|
const values = enumValues(field);
|
|
101
114
|
if (values !== undefined) {
|
|
102
|
-
const alias =
|
|
115
|
+
const alias = enumUnionAliasName(entity.name, field);
|
|
103
116
|
return field.isArray ? code `${alias}[]` : code `${alias}`;
|
|
104
117
|
}
|
|
105
118
|
return field.isArray ? code `string[]` : code `string`;
|
|
@@ -1 +1 @@
|
|
|
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
|
|
1
|
+
{"version":3,"file":"inferred-types.js","sourceRoot":"","sources":["../../src/templates/inferred-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output-parser.d.ts","sourceRoot":"","sources":["../../src/templates/output-parser.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,KAAK,QAAQ,EASd,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"output-parser.d.ts","sourceRoot":"","sources":["../../src/templates/output-parser.ts"],"names":[],"mappings":"AAUA,OAAO,EACL,KAAK,QAAQ,EASd,MAAM,0BAA0B,CAAC;AAsElC;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAmM/E"}
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
// identical payload-VO interface in `prompts.ts`; either type can be used
|
|
9
9
|
// interchangeably with parse results.
|
|
10
10
|
import { TYPE_OBJECT, TYPE_FIELD, TYPE_TEMPLATE, TEMPLATE_SUBTYPE_OUTPUT, FIELD_SUBTYPE_OBJECT, FIELD_ATTR_OBJECT_REF, TEMPLATE_ATTR_PAYLOAD_REF, TEMPLATE_ATTR_FORMAT, } from "@metaobjectsdev/metadata";
|
|
11
|
-
import { schemaLiteral,
|
|
12
|
-
import {
|
|
11
|
+
import { schemaLiteral, mirrorInitializer, } from "./extract-schema-emitter.js";
|
|
12
|
+
import { extractMapHelpersUsed } from "./fr010-field-mapping.js";
|
|
13
|
+
import { nestedMirrorInterfaces, nestedMappers, rootMapperName, delegateHelpers, usedHelpers, hasNested, } from "./extract-delegate-emitter.js";
|
|
13
14
|
const SCALAR_ZOD = {
|
|
14
15
|
string: "z.string()",
|
|
15
16
|
class: "z.string()",
|
|
@@ -90,12 +91,12 @@ export function renderOutputParser(root, templateName) {
|
|
|
90
91
|
const errorName = `${templateName}ValidationError`;
|
|
91
92
|
const parseName = `parse${templateName}`;
|
|
92
93
|
const safeParseName = `safeParse${templateName}`;
|
|
93
|
-
// FR-010: emit the tolerant
|
|
94
|
+
// FR-010: emit the tolerant extract() API alongside the strict Zod parser when the
|
|
94
95
|
// template targets json/xml. The @payloadRef already resolved to a value-object above,
|
|
95
|
-
// so a
|
|
96
|
+
// so a ExtractSchema can always be baked. text-format outputs get no extract.
|
|
96
97
|
const format = tmpl.ownAttr(TEMPLATE_ATTR_FORMAT) ?? "text";
|
|
97
98
|
const lc = format.toLowerCase();
|
|
98
|
-
const
|
|
99
|
+
const emitExtractLenient = lc === "json" || lc === "xml";
|
|
99
100
|
const strictBody = `const ${schemaName} = ${schema};
|
|
100
101
|
|
|
101
102
|
export type ${dataName} = z.infer<typeof ${schemaName}>;
|
|
@@ -131,64 +132,127 @@ export function ${safeParseName}(
|
|
|
131
132
|
: { success: false, error: result.error };
|
|
132
133
|
}
|
|
133
134
|
`;
|
|
134
|
-
if (!
|
|
135
|
+
if (!emitExtractLenient) {
|
|
135
136
|
return `import { z } from "zod";\n\n${strictBody}`;
|
|
136
137
|
}
|
|
137
|
-
// ---- FR-010 tolerant
|
|
138
|
-
const
|
|
139
|
-
const
|
|
140
|
-
const
|
|
141
|
-
const
|
|
138
|
+
// ---- FR-010 tolerant extract block (json/xml only) ----
|
|
139
|
+
const extractedName = `${templateName}Extracted`;
|
|
140
|
+
const extractLenientFnName = `extractLenient${templateName}`;
|
|
141
|
+
const tryExtractLenientName = `tryExtractLenient${templateName}`;
|
|
142
|
+
const extractLenientWithName = `extractLenient${templateName}WithLoader`;
|
|
143
|
+
const schemaConstName = `${templateName}ExtractSchema`;
|
|
144
|
+
const payloadFqnConst = `${templateName.toUpperCase()}_PAYLOAD_NAME`;
|
|
145
|
+
const formatEnum = format.toLowerCase() === "xml" ? "Format.XML" : "Format.JSON";
|
|
142
146
|
const schemaLit = schemaLiteral(vo, format, payloadRef);
|
|
143
|
-
const mirrorDecl = mirrorInterface(vo, recoveredName);
|
|
144
147
|
const initializer = mirrorInitializer(vo);
|
|
145
|
-
const mapHelpers =
|
|
146
|
-
//
|
|
148
|
+
const mapHelpers = extractMapHelpersUsed(vo);
|
|
149
|
+
// The nullable mirror is shared by BOTH extract paths. Use the nested-aware emitter so the
|
|
150
|
+
// payload mirror's nested-object / array-of-object components are typed (not `unknown`), and
|
|
151
|
+
// so a mirror interface is emitted for every reachable nested value-object. The payload mirror
|
|
152
|
+
// keeps the canonical `<Template>Extracted` name (instead of `<PayloadVO>Extracted`) so the
|
|
153
|
+
// existing self-contained extract<Name>() initializer continues to satisfy it.
|
|
154
|
+
const mirrorDecls = nestedMirrorInterfaces(vo, root, extractedName);
|
|
155
|
+
const payloadHasNested = hasNested(vo, root);
|
|
156
|
+
// Render-package imports the extract block needs. Only pull in the names the emitted
|
|
147
157
|
// source actually references, so the file has no unused imports (tsc noUnusedLocals-safe).
|
|
148
|
-
const renderImports = ["
|
|
158
|
+
const renderImports = ["extract", "extractSchema", "Format"];
|
|
149
159
|
if (schemaLit.includes("scalar("))
|
|
150
160
|
renderImports.push("scalar");
|
|
151
161
|
if (schemaLit.includes("enumField("))
|
|
152
162
|
renderImports.push("enumField");
|
|
153
163
|
if (schemaLit.includes("FieldKind."))
|
|
154
164
|
renderImports.push("FieldKind");
|
|
155
|
-
renderImports.push("type
|
|
165
|
+
renderImports.push("type ExtractSchema", "type ExtractOptions", "type ExtractionResult");
|
|
156
166
|
renderImports.push(...mapHelpers);
|
|
157
|
-
const
|
|
158
|
-
const ${schemaConstName}:
|
|
167
|
+
const selfContained = `/** Baked extract descriptor for the ${templateName} output. */
|
|
168
|
+
const ${schemaConstName}: ExtractSchema = ${schemaLit};
|
|
159
169
|
|
|
160
|
-
${
|
|
170
|
+
${mirrorDecls}
|
|
161
171
|
|
|
162
172
|
/**
|
|
163
|
-
*
|
|
164
|
-
* nullable mirror (\`${
|
|
165
|
-
* plus the per-field
|
|
173
|
+
* Self-contained tolerant best-effort extraction of a dirty LLM response; never throws.
|
|
174
|
+
* Returns a nullable mirror (\`${extractedName}\`) with fields null where lost/malformed,
|
|
175
|
+
* plus the per-field extraction report. Does NOT populate nested-object / array-of-object
|
|
176
|
+
* components (those stay null — the historical FR-010 gap). For full nested extraction, use
|
|
177
|
+
* \`${extractLenientWithName}(root, text)\`, which delegates to the runtime extract.
|
|
166
178
|
*/
|
|
167
|
-
export function ${
|
|
179
|
+
export function ${extractLenientFnName}(
|
|
168
180
|
text: string,
|
|
169
|
-
opts?:
|
|
170
|
-
):
|
|
171
|
-
const outcome =
|
|
181
|
+
opts?: ExtractOptions,
|
|
182
|
+
): ExtractionResult<${extractedName}> {
|
|
183
|
+
const outcome = extract(text, ${schemaConstName}, opts);
|
|
172
184
|
const d = outcome.data;
|
|
173
|
-
const data: ${
|
|
185
|
+
const data: ${extractedName} = ${initializer};
|
|
174
186
|
return { data, report: outcome.report };
|
|
175
187
|
}
|
|
176
188
|
|
|
177
189
|
/**
|
|
178
|
-
*
|
|
179
|
-
* field was lost. On success, \`result\` carries the
|
|
190
|
+
* Extraction as a bool gate: \`true\` when the response was non-empty and no required
|
|
191
|
+
* field was lost. On success, \`result\` carries the extracted mirror + report.
|
|
180
192
|
*/
|
|
181
|
-
export function ${
|
|
193
|
+
export function ${tryExtractLenientName}(
|
|
182
194
|
text: string,
|
|
183
|
-
): { ok: boolean; result:
|
|
184
|
-
const result = ${
|
|
195
|
+
): { ok: boolean; result: ExtractionResult<${extractedName}> } {
|
|
196
|
+
const result = ${extractLenientFnName}(text);
|
|
185
197
|
const ok = !result.report.isEmpty() && !result.report.hasLostRequired();
|
|
186
198
|
return { ok, result };
|
|
187
199
|
}
|
|
188
200
|
`;
|
|
201
|
+
// ---- Runtime-delegating extract (closes the nested gap) ----
|
|
202
|
+
// Resolves this payload's MetaObject from a loaded MetaRoot by its baked simple name and
|
|
203
|
+
// delegates to extractObject() in @metaobjectsdev/runtime-ts, which assembles the FULL nested
|
|
204
|
+
// object graph reflection-free. The assembled ValueObject graph is then mapped into the typed
|
|
205
|
+
// nullable mirror graph by the generated from<VO>Extracted mappers. Codegen-wrapping-runtime
|
|
206
|
+
// (a generated DAO calling the dynamic-metadata runtime) — mirrors the Java/Kotlin pilots.
|
|
207
|
+
//
|
|
208
|
+
// The baked PAYLOAD_NAME is the resolved payload VO's SIMPLE name (root.findObject matches on
|
|
209
|
+
// the object's `name`, not its FQN). The root mapper is named for the TEMPLATE (so it returns
|
|
210
|
+
// the canonically-named `<Template>Extracted` mirror); nested mappers use their VO names.
|
|
211
|
+
const payloadName = vo.name;
|
|
212
|
+
const rootMapper = rootMapperName(templateName);
|
|
213
|
+
const delegating = `
|
|
214
|
+
/** Payload value-object name this parser extracts — resolved against a loaded MetaRoot at runtime. */
|
|
215
|
+
export const ${payloadFqnConst} = ${JSON.stringify(payloadName)};
|
|
216
|
+
|
|
217
|
+
${nestedMappers(vo, root, rootMapper, extractedName)}
|
|
218
|
+
|
|
219
|
+
${delegateHelpers(usedHelpers(vo, root))}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Runtime-delegating tolerant extraction; never throws. Unlike \`${extractLenientFnName}(text)\`, this FULLY
|
|
223
|
+
* populates nested-object and array-of-object components by delegating to the metadata-driven
|
|
224
|
+
* runtime \`extractObject\` (which assembles the whole graph reflection-free via the Phase A object
|
|
225
|
+
* model), then maps the assembled graph into the typed \`${extractedName}\` mirror.
|
|
226
|
+
*
|
|
227
|
+
* @param root a loaded MetaRoot (e.g. \`(await new MetaDataLoader().load(...)).root\`) that declares
|
|
228
|
+
* the \`${payloadRef}\` value-object.
|
|
229
|
+
*/
|
|
230
|
+
export function ${extractLenientWithName}(
|
|
231
|
+
root: MetaRoot,
|
|
232
|
+
text: string,
|
|
233
|
+
opts?: Partial<ExtractOptions> | null,
|
|
234
|
+
): ExtractionResult<${extractedName}> {
|
|
235
|
+
const mo = root.findObject(${payloadFqnConst});
|
|
236
|
+
if (mo === undefined) {
|
|
237
|
+
throw new Error(\`${extractLenientWithName}: payload "\${${payloadFqnConst}}" not found in the supplied MetaRoot\`);
|
|
238
|
+
}
|
|
239
|
+
const outcome = extractObject(mo, text, ${formatEnum}, opts);
|
|
240
|
+
return { data: ${rootMapper}(outcome.data), report: outcome.report };
|
|
241
|
+
}
|
|
242
|
+
`;
|
|
243
|
+
// The delegating overload needs runtime-ts (extractObject) + the MetaRoot type from metadata.
|
|
244
|
+
// It is always emitted (the gap-closing path), regardless of whether THIS payload has nested
|
|
245
|
+
// fields — a flat payload still benefits from the loader-driven path and keeps the API uniform.
|
|
246
|
+
void payloadHasNested;
|
|
247
|
+
const metadataImport = `import type { MetaRoot } from "@metaobjectsdev/metadata";\n`;
|
|
248
|
+
const runtimeImport = `import { extractObject } from "@metaobjectsdev/runtime-ts";\n`;
|
|
189
249
|
return (`import { z } from "zod";\n` +
|
|
190
|
-
`import {\n ${renderImports.join(",\n ")},\n} from "@metaobjectsdev/render";\n
|
|
250
|
+
`import {\n ${renderImports.join(",\n ")},\n} from "@metaobjectsdev/render";\n` +
|
|
251
|
+
metadataImport +
|
|
252
|
+
runtimeImport +
|
|
253
|
+
`\n` +
|
|
191
254
|
`${strictBody}\n` +
|
|
192
|
-
`${
|
|
255
|
+
`${selfContained}\n` +
|
|
256
|
+
`${delegating}`);
|
|
193
257
|
}
|
|
194
258
|
//# sourceMappingURL=output-parser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"output-parser.js","sourceRoot":"","sources":["../../src/templates/output-parser.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,EAAE;AACF,6EAA6E;AAC7E,iFAAiF;AACjF,yEAAyE;AACzE,iEAAiE;AACjE,6EAA6E;AAC7E,0EAA0E;AAC1E,sCAAsC;AAEtC,OAAO,EAEL,WAAW,EACX,UAAU,EACV,aAAa,EACb,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,aAAa,EACb,
|
|
1
|
+
{"version":3,"file":"output-parser.js","sourceRoot":"","sources":["../../src/templates/output-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// @payloadRef resolves to a value-object, emits a `<TemplateName>.prompt.ts` file
|
|
6
6
|
// exporting `render<TemplateName>Format(overrides?)` backed by the render engine's
|
|
7
7
|
// renderOutputFormat(). The baked OutputFormatSpec's rootName is the payload name,
|
|
8
|
-
// so the prompt fragment and the
|
|
8
|
+
// so the prompt fragment and the extract() codegen agree on the root name.
|
|
9
9
|
//
|
|
10
10
|
// Mirrors the C# OutputPromptGenerator + OutputFormatSpecEmitter (split into a
|
|
11
11
|
// generator factory + this pure renderer, matching the TS output-parser shape).
|
|
@@ -46,7 +46,7 @@ export function renderOutputPrompt(root, templateName) {
|
|
|
46
46
|
if (!vo) {
|
|
47
47
|
throw new Error(`template "${templateName}" @payloadRef "${payloadRef}" not found in metadata root`);
|
|
48
48
|
}
|
|
49
|
-
// rootName == payload name so the prompt fragment and
|
|
49
|
+
// rootName == payload name so the prompt fragment and extract() agree.
|
|
50
50
|
const spec = specLiteral(vo, tmpl, payloadRef);
|
|
51
51
|
const specName = `${templateName}FormatSpec`;
|
|
52
52
|
const fnName = `render${templateName}Format`;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type MetaData } from "@metaobjectsdev/metadata";
|
|
2
|
+
import { type Provider } from "@metaobjectsdev/render";
|
|
3
|
+
/**
|
|
4
|
+
* Render the per-template render-helper source for one `template.output`, AND
|
|
5
|
+
* run the build-time drift gate first. Throws if: the template isn't found /
|
|
6
|
+
* isn't a template.output; @payloadRef is missing or doesn't resolve to an
|
|
7
|
+
* object.value; a required ref for the kind is missing; or ANY referenced
|
|
8
|
+
* mustache drifts from the payload VO (the headline build gate).
|
|
9
|
+
*
|
|
10
|
+
* @param provider the codegen-time provider (e.g. projectProvider(projectRoot))
|
|
11
|
+
* used to resolve + verify each referenced mustache at build time.
|
|
12
|
+
*/
|
|
13
|
+
export declare function renderRenderHelper(root: MetaData, templateName: string, provider: Provider): string;
|
|
14
|
+
//# sourceMappingURL=render-helper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-helper.d.ts","sourceRoot":"","sources":["../../src/templates/render-helper.ts"],"names":[],"mappings":"AA2BA,OAAO,EACL,KAAK,QAAQ,EAiBd,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAGL,KAAK,QAAQ,EAGd,MAAM,wBAAwB,CAAC;AA2EhC;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,QAAQ,EACd,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,QAAQ,GACjB,MAAM,CAsGR"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// server/typescript/packages/codegen-ts/src/templates/render-helper.ts
|
|
2
|
+
//
|
|
3
|
+
// Per-template.output render helper: emits a typed `render<Name>(payload, provider)`
|
|
4
|
+
// that wraps the EXISTING render() engine, AND enforces the mustache↔payload-VO
|
|
5
|
+
// drift check (the EXISTING verify() engine) at BUILD time.
|
|
6
|
+
//
|
|
7
|
+
// Two shapes, keyed off @kind:
|
|
8
|
+
// • document (default) → renders @textRef in @format → one string.
|
|
9
|
+
// • email → renders @subjectRef + @htmlBodyRef (+ optional
|
|
10
|
+
// @textBodyRef) → a structured EmailDocument.
|
|
11
|
+
//
|
|
12
|
+
// The headline is the BUILD-TIME drift gate: BEFORE emitting, every referenced
|
|
13
|
+
// mustache is resolved via the codegen-time provider and verify()'d against the
|
|
14
|
+
// payload field tree. If a referenced text is unresolvable OR carries any
|
|
15
|
+
// NON-warning verify error (e.g. `{{field}}` not on the payload VO), this THROWS
|
|
16
|
+
// and FAILS codegen — naming the template, the ref, the error code, and the
|
|
17
|
+
// offending field. This is what makes the build fail when a mustache references
|
|
18
|
+
// a field the payload VO doesn't declare.
|
|
19
|
+
//
|
|
20
|
+
// Reuse, not reimplementation:
|
|
21
|
+
// • render() — the runtime helper delegates to it (emitted call).
|
|
22
|
+
// • verify() — run here at build time for the drift gate.
|
|
23
|
+
// • derivePayloadFieldTree (replicated minimally below — codegen-ts must NOT
|
|
24
|
+
// depend on the cli package; the walk is the same as cli's payload-field-tree).
|
|
25
|
+
// • PayloadField — the verify() field-tree shape; serialized into the emitted
|
|
26
|
+
// `verify:` literal so render()'s runtime drift check runs too.
|
|
27
|
+
import { TYPE_OBJECT, TYPE_FIELD, TYPE_TEMPLATE, FIELD_SUBTYPE_OBJECT, FIELD_ATTR_OBJECT_REF, TEMPLATE_SUBTYPE_OUTPUT, TEMPLATE_ATTR_PAYLOAD_REF, TEMPLATE_ATTR_TEXT_REF, TEMPLATE_ATTR_FORMAT, TEMPLATE_ATTR_MAX_CHARS, TEMPLATE_ATTR_KIND, TEMPLATE_KIND_EMAIL, TEMPLATE_KIND_DEFAULT, TEMPLATE_ATTR_SUBJECT_REF, TEMPLATE_ATTR_HTML_BODY_REF, TEMPLATE_ATTR_TEXT_BODY_REF, } from "@metaobjectsdev/metadata";
|
|
28
|
+
import { verify, ERR_REQUIRED_SLOT_UNUSED, } from "@metaobjectsdev/render";
|
|
29
|
+
function findObject(root, name) {
|
|
30
|
+
return root.ownChildren().find((c) => c.type === TYPE_OBJECT && c.name === name);
|
|
31
|
+
}
|
|
32
|
+
function findTemplate(root, name) {
|
|
33
|
+
return root.ownChildren().find((c) => c.type === TYPE_TEMPLATE && c.name === name);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Walk an `object.value` view-object into a render `PayloadField[]`. Object-ref
|
|
37
|
+
* fields recurse into their referenced view-object; a `seen` set guards a
|
|
38
|
+
* (pathological) reference cycle. Replicates cli's `derivePayloadFieldTree` —
|
|
39
|
+
* codegen-ts must not depend on the cli package (wrong layer / would cycle), so
|
|
40
|
+
* the same small walk lives here against the metadata constants codegen-ts
|
|
41
|
+
* already imports.
|
|
42
|
+
*/
|
|
43
|
+
function derivePayloadFieldTree(root, voName, seen = new Set()) {
|
|
44
|
+
if (seen.has(voName))
|
|
45
|
+
return [];
|
|
46
|
+
const vo = findObject(root, voName);
|
|
47
|
+
if (!vo)
|
|
48
|
+
return [];
|
|
49
|
+
const nextSeen = new Set(seen).add(voName);
|
|
50
|
+
const fields = [];
|
|
51
|
+
for (const f of vo.children().filter((c) => c.type === TYPE_FIELD)) {
|
|
52
|
+
if (f.subType === FIELD_SUBTYPE_OBJECT) {
|
|
53
|
+
const ref = f.ownAttr(FIELD_ATTR_OBJECT_REF);
|
|
54
|
+
if (typeof ref === "string") {
|
|
55
|
+
fields.push({ name: f.name, fields: derivePayloadFieldTree(root, ref, nextSeen) });
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
fields.push({ name: f.name });
|
|
60
|
+
}
|
|
61
|
+
return fields;
|
|
62
|
+
}
|
|
63
|
+
/** Serialize a PayloadField[] as a stable, deterministic TS array literal so the
|
|
64
|
+
* emitted render() call runs the same runtime drift check the build gate ran. */
|
|
65
|
+
function fieldTreeLiteral(fields) {
|
|
66
|
+
// JSON.stringify is deterministic for this shape (no functions/cycles by
|
|
67
|
+
// construction) and produces valid TS object/array literal syntax.
|
|
68
|
+
return JSON.stringify(fields);
|
|
69
|
+
}
|
|
70
|
+
/** Run the build-time drift gate for one referenced mustache. Throws (fails
|
|
71
|
+
* codegen) when the ref is unresolvable OR verify() reports a non-warning error.
|
|
72
|
+
* Warnings (ERR_REQUIRED_SLOT_UNUSED) are tolerated. */
|
|
73
|
+
function gateRef(templateName, ref, provider, fields) {
|
|
74
|
+
const text = provider.resolve(ref);
|
|
75
|
+
if (text === undefined) {
|
|
76
|
+
throw new Error(`render-helper drift: template "${templateName}" ref "${ref}" — unresolved (provider returned no text)`);
|
|
77
|
+
}
|
|
78
|
+
const errors = verify(text, fields, { provider }).filter((e) => e.code !== ERR_REQUIRED_SLOT_UNUSED);
|
|
79
|
+
if (errors.length > 0) {
|
|
80
|
+
const e = errors[0];
|
|
81
|
+
throw new Error(`render-helper drift: template "${templateName}" ref "${ref}" — ${e.code}: {{${e.path}}} not on payload VO`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Render the per-template render-helper source for one `template.output`, AND
|
|
86
|
+
* run the build-time drift gate first. Throws if: the template isn't found /
|
|
87
|
+
* isn't a template.output; @payloadRef is missing or doesn't resolve to an
|
|
88
|
+
* object.value; a required ref for the kind is missing; or ANY referenced
|
|
89
|
+
* mustache drifts from the payload VO (the headline build gate).
|
|
90
|
+
*
|
|
91
|
+
* @param provider the codegen-time provider (e.g. projectProvider(projectRoot))
|
|
92
|
+
* used to resolve + verify each referenced mustache at build time.
|
|
93
|
+
*/
|
|
94
|
+
export function renderRenderHelper(root, templateName, provider) {
|
|
95
|
+
const tmpl = findTemplate(root, templateName);
|
|
96
|
+
if (!tmpl) {
|
|
97
|
+
throw new Error(`template "${templateName}" not found in metadata root`);
|
|
98
|
+
}
|
|
99
|
+
if (tmpl.subType !== TEMPLATE_SUBTYPE_OUTPUT) {
|
|
100
|
+
throw new Error(`template "${templateName}" is not a template.output (got subtype "${tmpl.subType}")`);
|
|
101
|
+
}
|
|
102
|
+
const payloadRef = tmpl.ownAttr(TEMPLATE_ATTR_PAYLOAD_REF);
|
|
103
|
+
if (typeof payloadRef !== "string") {
|
|
104
|
+
throw new Error(`template "${templateName}" missing @payloadRef`);
|
|
105
|
+
}
|
|
106
|
+
const vo = findObject(root, payloadRef);
|
|
107
|
+
if (!vo) {
|
|
108
|
+
throw new Error(`template "${templateName}" @payloadRef "${payloadRef}" not found in metadata root`);
|
|
109
|
+
}
|
|
110
|
+
const fields = derivePayloadFieldTree(root, payloadRef);
|
|
111
|
+
const ft = fieldTreeLiteral(fields);
|
|
112
|
+
const fnName = `render${templateName}`;
|
|
113
|
+
const kind = (tmpl.ownAttr(TEMPLATE_ATTR_KIND) ?? TEMPLATE_KIND_DEFAULT)
|
|
114
|
+
.toLowerCase();
|
|
115
|
+
if (kind === TEMPLATE_KIND_EMAIL) {
|
|
116
|
+
const subjectRef = tmpl.ownAttr(TEMPLATE_ATTR_SUBJECT_REF);
|
|
117
|
+
const htmlBodyRef = tmpl.ownAttr(TEMPLATE_ATTR_HTML_BODY_REF);
|
|
118
|
+
const textBodyRef = tmpl.ownAttr(TEMPLATE_ATTR_TEXT_BODY_REF);
|
|
119
|
+
if (typeof subjectRef !== "string") {
|
|
120
|
+
throw new Error(`template "${templateName}" (email) missing @subjectRef`);
|
|
121
|
+
}
|
|
122
|
+
if (typeof htmlBodyRef !== "string") {
|
|
123
|
+
throw new Error(`template "${templateName}" (email) missing @htmlBodyRef`);
|
|
124
|
+
}
|
|
125
|
+
// BUILD-TIME drift gate — every email part-ref is resolved + verified.
|
|
126
|
+
gateRef(templateName, subjectRef, provider, fields);
|
|
127
|
+
gateRef(templateName, htmlBodyRef, provider, fields);
|
|
128
|
+
if (typeof textBodyRef === "string") {
|
|
129
|
+
gateRef(templateName, textBodyRef, provider, fields);
|
|
130
|
+
}
|
|
131
|
+
const textBodyLine = typeof textBodyRef === "string"
|
|
132
|
+
? `\n textBody: render({ ref: ${JSON.stringify(textBodyRef)}, payload, format: "text", provider, verify: ${ft} }),`
|
|
133
|
+
: "";
|
|
134
|
+
return `import { render } from "@metaobjectsdev/render";
|
|
135
|
+
import type { Provider, EmailDocument } from "@metaobjectsdev/render";
|
|
136
|
+
import type { ${payloadRef} } from "./payloads.js";
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Render the ${templateName} email (subject + html body${typeof textBodyRef === "string" ? " + text body" : ""}) from a
|
|
140
|
+
* typed ${payloadRef} payload. Wraps the render() engine; the payload field tree is
|
|
141
|
+
* baked in so render()'s runtime drift check matches the build-time gate.
|
|
142
|
+
*/
|
|
143
|
+
export function ${fnName}(payload: ${payloadRef}, provider: Provider): EmailDocument {
|
|
144
|
+
return {
|
|
145
|
+
subject: render({ ref: ${JSON.stringify(subjectRef)}, payload, format: "text", provider, verify: ${ft} }),
|
|
146
|
+
htmlBody: render({ ref: ${JSON.stringify(htmlBodyRef)}, payload, format: "html", provider, verify: ${ft} }),${textBodyLine}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
`;
|
|
150
|
+
}
|
|
151
|
+
// --- document kind ---
|
|
152
|
+
const textRef = tmpl.ownAttr(TEMPLATE_ATTR_TEXT_REF);
|
|
153
|
+
if (typeof textRef !== "string") {
|
|
154
|
+
throw new Error(`template "${templateName}" (document) missing @textRef`);
|
|
155
|
+
}
|
|
156
|
+
const format = (tmpl.ownAttr(TEMPLATE_ATTR_FORMAT) ?? "text").toLowerCase();
|
|
157
|
+
const maxCharsAttr = tmpl.ownAttr(TEMPLATE_ATTR_MAX_CHARS);
|
|
158
|
+
const maxChars = typeof maxCharsAttr === "number"
|
|
159
|
+
? maxCharsAttr
|
|
160
|
+
: typeof maxCharsAttr === "string" && maxCharsAttr.trim() !== ""
|
|
161
|
+
? Number(maxCharsAttr)
|
|
162
|
+
: undefined;
|
|
163
|
+
// BUILD-TIME drift gate.
|
|
164
|
+
gateRef(templateName, textRef, provider, fields);
|
|
165
|
+
const maxCharsArg = maxChars !== undefined && Number.isFinite(maxChars) ? `, maxChars: ${maxChars}` : "";
|
|
166
|
+
return `import { render } from "@metaobjectsdev/render";
|
|
167
|
+
import type { Provider } from "@metaobjectsdev/render";
|
|
168
|
+
import type { ${payloadRef} } from "./payloads.js";
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Render the ${templateName} document from a typed ${payloadRef} payload. Wraps the
|
|
172
|
+
* render() engine; the payload field tree is baked in so render()'s runtime drift
|
|
173
|
+
* check matches the build-time gate enforced when this file was generated.
|
|
174
|
+
*/
|
|
175
|
+
export function ${fnName}(payload: ${payloadRef}, provider: Provider): string {
|
|
176
|
+
return render({ ref: ${JSON.stringify(textRef)}, payload, format: ${JSON.stringify(format)}, provider, verify: ${ft}${maxCharsArg} });
|
|
177
|
+
}
|
|
178
|
+
`;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=render-helper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-helper.js","sourceRoot":"","sources":["../../src/templates/render-helper.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,EAAE;AACF,qFAAqF;AACrF,gFAAgF;AAChF,4DAA4D;AAC5D,EAAE;AACF,+BAA+B;AAC/B,qEAAqE;AACrE,0EAA0E;AAC1E,wEAAwE;AACxE,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,0EAA0E;AAC1E,iFAAiF;AACjF,4EAA4E;AAC5E,gFAAgF;AAChF,0CAA0C;AAC1C,EAAE;AACF,+BAA+B;AAC/B,qEAAqE;AACrE,6DAA6D;AAC7D,+EAA+E;AAC/E,oFAAoF;AACpF,gFAAgF;AAChF,oEAAoE;AAEpE,OAAO,EAEL,WAAW,EACX,UAAU,EACV,aAAa,EACb,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,yBAAyB,EACzB,sBAAsB,EACtB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,2BAA2B,EAC3B,2BAA2B,GAC5B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,MAAM,EACN,wBAAwB,GAIzB,MAAM,wBAAwB,CAAC;AAEhC,SAAS,UAAU,CAAC,IAAc,EAAE,IAAY;IAC9C,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACnF,CAAC;AAED,SAAS,YAAY,CAAC,IAAc,EAAE,IAAY;IAChD,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACrF,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,sBAAsB,CAC7B,IAAc,EACd,MAAc,EACd,OAA4B,IAAI,GAAG,EAAE;IAErC,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,EAAE,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACpC,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,CAAC;IACnB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,EAAE,CAAC;QACnE,IAAI,CAAC,CAAC,OAAO,KAAK,oBAAoB,EAAE,CAAC;YACvC,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;YAC7C,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,sBAAsB,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;gBACnF,SAAS;YACX,CAAC;QACH,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;kFACkF;AAClF,SAAS,gBAAgB,CAAC,MAAsB;IAC9C,yEAAyE;IACzE,mEAAmE;IACnE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED;;yDAEyD;AACzD,SAAS,OAAO,CACd,YAAoB,EACpB,GAAW,EACX,QAAkB,EAClB,MAAsB;IAEtB,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CACb,kCAAkC,YAAY,UAAU,GAAG,4CAA4C,CACxG,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAkB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,CACrE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,wBAAwB,CAC3C,CAAC;IACF,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,kCAAkC,YAAY,UAAU,GAAG,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,sBAAsB,CAC5G,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAChC,IAAc,EACd,YAAoB,EACpB,QAAkB;IAElB,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,aAAa,YAAY,8BAA8B,CAAC,CAAC;IAC3E,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,KAAK,uBAAuB,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CACb,aAAa,YAAY,4CAA4C,IAAI,CAAC,OAAO,IAAI,CACtF,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC3D,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,aAAa,YAAY,uBAAuB,CAAC,CAAC;IACpE,CAAC;IACD,MAAM,EAAE,GAAG,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACxC,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CACb,aAAa,YAAY,kBAAkB,UAAU,8BAA8B,CACpF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,sBAAsB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACxD,MAAM,EAAE,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,SAAS,YAAY,EAAE,CAAC;IAEvC,MAAM,IAAI,GAAG,CAAE,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAwB,IAAI,qBAAqB,CAAC;SAC7F,WAAW,EAAE,CAAC;IAEjB,IAAI,IAAI,KAAK,mBAAmB,EAAE,CAAC;QACjC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;QAC3D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;QAC9D,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,aAAa,YAAY,+BAA+B,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,aAAa,YAAY,gCAAgC,CAAC,CAAC;QAC7E,CAAC;QAED,uEAAuE;QACvE,OAAO,CAAC,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpD,OAAO,CAAC,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACrD,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;YACpC,OAAO,CAAC,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,YAAY,GAChB,OAAO,WAAW,KAAK,QAAQ;YAC7B,CAAC,CAAC,iCAAiC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,gDAAgD,EAAE,MAAM;YACtH,CAAC,CAAC,EAAE,CAAC;QAET,OAAO;;gBAEK,UAAU;;;gBAGV,YAAY,8BAA8B,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE;WACpG,UAAU;;;kBAGH,MAAM,aAAa,UAAU;;6BAElB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,gDAAgD,EAAE;8BAC3E,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,gDAAgD,EAAE,OAAO,YAAY;;;CAG7H,CAAC;IACA,CAAC;IAED,wBAAwB;IACxB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACrD,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,aAAa,YAAY,+BAA+B,CAAC,CAAC;IAC5E,CAAC;IACD,MAAM,MAAM,GAAG,CAAE,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAwB,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IACpG,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC3D,MAAM,QAAQ,GACZ,OAAO,YAAY,KAAK,QAAQ;QAC9B,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE;YAC9D,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;YACtB,CAAC,CAAC,SAAS,CAAC;IAElB,yBAAyB;IACzB,OAAO,CAAC,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IAEjD,MAAM,WAAW,GACf,QAAQ,KAAK,SAAS,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,eAAe,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAEvF,OAAO;;gBAEO,UAAU;;;gBAGV,YAAY,0BAA0B,UAAU;;;;kBAI9C,MAAM,aAAa,UAAU;yBACtB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,sBAAsB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,uBAAuB,EAAE,GAAG,WAAW;;CAElI,CAAC;AACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;AAiCjE;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CAgC5D;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,UAAU,GAAG,IAAI,CA0DzD"}
|