@metaobjectsdev/codegen-ts 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/column-mapper.d.ts.map +1 -1
- package/dist/column-mapper.js +24 -8
- package/dist/column-mapper.js.map +1 -1
- package/dist/constants.d.ts +8 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +16 -0
- package/dist/constants.js.map +1 -1
- package/dist/docs-paths.d.ts +58 -0
- package/dist/docs-paths.d.ts.map +1 -0
- package/dist/docs-paths.js +89 -0
- package/dist/docs-paths.js.map +1 -0
- package/dist/enum-import.d.ts +14 -0
- package/dist/enum-import.d.ts.map +1 -0
- package/dist/enum-import.js +35 -0
- package/dist/enum-import.js.map +1 -0
- package/dist/enum-shared.d.ts +32 -0
- package/dist/enum-shared.d.ts.map +1 -0
- package/dist/enum-shared.js +83 -0
- package/dist/enum-shared.js.map +1 -0
- package/dist/generator-registry.d.ts +22 -0
- package/dist/generator-registry.d.ts.map +1 -0
- package/dist/generator-registry.js +161 -0
- package/dist/generator-registry.js.map +1 -0
- package/dist/generator.d.ts +6 -0
- package/dist/generator.d.ts.map +1 -1
- package/dist/generator.js.map +1 -1
- package/dist/generators/api-doc-render.d.ts +17 -0
- package/dist/generators/api-doc-render.d.ts.map +1 -0
- package/dist/generators/api-doc-render.js +431 -0
- package/dist/generators/api-doc-render.js.map +1 -0
- package/dist/generators/api-docs-file.d.ts +21 -0
- package/dist/generators/api-docs-file.d.ts.map +1 -0
- package/dist/generators/api-docs-file.js +112 -0
- package/dist/generators/api-docs-file.js.map +1 -0
- package/dist/generators/api-field-shape.d.ts +39 -0
- package/dist/generators/api-field-shape.d.ts.map +1 -0
- package/dist/generators/api-field-shape.js +92 -0
- package/dist/generators/api-field-shape.js.map +1 -0
- package/dist/generators/api-label.d.ts +3 -0
- package/dist/generators/api-label.d.ts.map +1 -0
- package/dist/generators/api-label.js +8 -0
- package/dist/generators/api-label.js.map +1 -0
- package/dist/generators/api-model.d.ts +122 -0
- package/dist/generators/api-model.d.ts.map +1 -0
- package/dist/generators/api-model.js +809 -0
- package/dist/generators/api-model.js.map +1 -0
- package/dist/generators/docs-data-builder.d.ts +26 -4
- package/dist/generators/docs-data-builder.d.ts.map +1 -1
- package/dist/generators/docs-data-builder.js +436 -164
- package/dist/generators/docs-data-builder.js.map +1 -1
- package/dist/generators/docs-data.d.ts +136 -27
- package/dist/generators/docs-data.d.ts.map +1 -1
- package/dist/generators/docs-data.js +1 -1
- package/dist/generators/docs-data.js.map +1 -1
- package/dist/generators/docs-file.d.ts +19 -0
- package/dist/generators/docs-file.d.ts.map +1 -1
- package/dist/generators/docs-file.js +154 -27
- package/dist/generators/docs-file.js.map +1 -1
- package/dist/generators/entity-file.d.ts.map +1 -1
- package/dist/generators/entity-file.js +29 -14
- package/dist/generators/entity-file.js.map +1 -1
- package/dist/generators/extractor-file.d.ts.map +1 -1
- package/dist/generators/extractor-file.js +2 -1
- package/dist/generators/extractor-file.js.map +1 -1
- package/dist/generators/field-anchor.d.ts +7 -0
- package/dist/generators/field-anchor.d.ts.map +1 -0
- package/dist/generators/field-anchor.js +23 -0
- package/dist/generators/field-anchor.js.map +1 -0
- package/dist/generators/index.d.ts +8 -1
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +6 -0
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/mermaid-er.d.ts +14 -0
- package/dist/generators/mermaid-er.d.ts.map +1 -1
- package/dist/generators/mermaid-er.js +14 -0
- package/dist/generators/mermaid-er.js.map +1 -1
- package/dist/generators/output-parser-file.d.ts.map +1 -1
- package/dist/generators/output-parser-file.js +3 -4
- package/dist/generators/output-parser-file.js.map +1 -1
- package/dist/generators/output-prompt-file.d.ts.map +1 -1
- package/dist/generators/output-prompt-file.js +2 -2
- package/dist/generators/output-prompt-file.js.map +1 -1
- package/dist/generators/prompt-render-file.d.ts.map +1 -1
- package/dist/generators/prompt-render-file.js +3 -4
- package/dist/generators/prompt-render-file.js.map +1 -1
- package/dist/generators/queries-file.d.ts.map +1 -1
- package/dist/generators/queries-file.js +8 -3
- package/dist/generators/queries-file.js.map +1 -1
- package/dist/generators/render-helper-file.d.ts.map +1 -1
- package/dist/generators/render-helper-file.js +2 -2
- package/dist/generators/render-helper-file.js.map +1 -1
- package/dist/generators/routes-file-hono.d.ts.map +1 -1
- package/dist/generators/routes-file-hono.js +5 -1
- package/dist/generators/routes-file-hono.js.map +1 -1
- package/dist/generators/routes-file.d.ts +3 -0
- package/dist/generators/routes-file.d.ts.map +1 -1
- package/dist/generators/routes-file.js +6 -1
- package/dist/generators/routes-file.js.map +1 -1
- package/dist/generators/template-doc-builder.d.ts +19 -0
- package/dist/generators/template-doc-builder.d.ts.map +1 -0
- package/dist/generators/template-doc-builder.js +220 -0
- package/dist/generators/template-doc-builder.js.map +1 -0
- package/dist/generators/template-doc-data.d.ts +62 -0
- package/dist/generators/template-doc-data.d.ts.map +1 -0
- package/dist/generators/template-doc-data.js +16 -0
- package/dist/generators/template-doc-data.js.map +1 -0
- package/dist/generators/template-payload-tree.d.ts +15 -0
- package/dist/generators/template-payload-tree.d.ts.map +1 -0
- package/dist/generators/template-payload-tree.js +61 -0
- package/dist/generators/template-payload-tree.js.map +1 -0
- package/dist/generators/template-source-annotate.d.ts +74 -0
- package/dist/generators/template-source-annotate.d.ts.map +1 -0
- package/dist/generators/template-source-annotate.js +184 -0
- package/dist/generators/template-source-annotate.js.map +1 -0
- package/dist/generators/template-source-render.d.ts +24 -0
- package/dist/generators/template-source-render.d.ts.map +1 -0
- package/dist/generators/template-source-render.js +175 -0
- package/dist/generators/template-source-render.js.map +1 -0
- package/dist/generators/trace-helper-file.d.ts +9 -0
- package/dist/generators/trace-helper-file.d.ts.map +1 -0
- package/dist/generators/trace-helper-file.js +196 -0
- package/dist/generators/trace-helper-file.js.map +1 -0
- package/dist/index.d.ts +29 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -2
- package/dist/index.js.map +1 -1
- package/dist/metaobjects-config.d.ts +75 -2
- package/dist/metaobjects-config.d.ts.map +1 -1
- package/dist/metaobjects-config.js +43 -0
- package/dist/metaobjects-config.js.map +1 -1
- package/dist/naming.d.ts +19 -0
- package/dist/naming.d.ts.map +1 -1
- package/dist/naming.js +41 -0
- package/dist/naming.js.map +1 -1
- package/dist/payload-codegen.d.ts.map +1 -1
- package/dist/payload-codegen.js +12 -4
- 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 +51 -25
- package/dist/projection/extract-view-spec.js.map +1 -1
- package/dist/relation-resolver.d.ts +16 -0
- package/dist/relation-resolver.d.ts.map +1 -1
- package/dist/relation-resolver.js +82 -1
- package/dist/relation-resolver.js.map +1 -1
- package/dist/render-context.d.ts +4 -0
- package/dist/render-context.d.ts.map +1 -1
- package/dist/render-context.js.map +1 -1
- package/dist/render-engine/embedded-templates.generated.d.ts +2 -0
- package/dist/render-engine/embedded-templates.generated.d.ts.map +1 -0
- package/dist/render-engine/embedded-templates.generated.js +15 -0
- package/dist/render-engine/embedded-templates.generated.js.map +1 -0
- package/dist/render-engine/framework-provider.d.ts.map +1 -1
- package/dist/render-engine/framework-provider.js +26 -13
- package/dist/render-engine/framework-provider.js.map +1 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +17 -0
- package/dist/runner.js.map +1 -1
- package/dist/templates/docs-file.d.ts +2 -6
- package/dist/templates/docs-file.d.ts.map +1 -1
- package/dist/templates/docs-file.js +2 -5
- package/dist/templates/docs-file.js.map +1 -1
- package/dist/templates/drizzle-schema.d.ts.map +1 -1
- package/dist/templates/drizzle-schema.js +30 -2
- package/dist/templates/drizzle-schema.js.map +1 -1
- package/dist/templates/entity-constants.d.ts +7 -0
- package/dist/templates/entity-constants.d.ts.map +1 -1
- package/dist/templates/entity-constants.js +1 -1
- package/dist/templates/entity-constants.js.map +1 -1
- package/dist/templates/entity-file.d.ts.map +1 -1
- package/dist/templates/entity-file.js +16 -5
- package/dist/templates/entity-file.js.map +1 -1
- package/dist/templates/enums-file.d.ts +11 -0
- package/dist/templates/enums-file.d.ts.map +1 -0
- package/dist/templates/enums-file.js +44 -0
- package/dist/templates/enums-file.js.map +1 -0
- package/dist/templates/extract-delegate-emitter.d.ts.map +1 -1
- package/dist/templates/extract-delegate-emitter.js +5 -7
- package/dist/templates/extract-delegate-emitter.js.map +1 -1
- package/dist/templates/extract-schema-emitter.d.ts.map +1 -1
- package/dist/templates/extract-schema-emitter.js +5 -1
- package/dist/templates/extract-schema-emitter.js.map +1 -1
- package/dist/templates/extractor.d.ts.map +1 -1
- package/dist/templates/extractor.js +56 -39
- package/dist/templates/extractor.js.map +1 -1
- package/dist/templates/field-meta.d.ts.map +1 -1
- package/dist/templates/field-meta.js +1 -5
- package/dist/templates/field-meta.js.map +1 -1
- package/dist/templates/filter-allowlist.d.ts +7 -2
- package/dist/templates/filter-allowlist.d.ts.map +1 -1
- package/dist/templates/filter-allowlist.js +17 -9
- package/dist/templates/filter-allowlist.js.map +1 -1
- package/dist/templates/filter-type.d.ts +7 -1
- package/dist/templates/filter-type.d.ts.map +1 -1
- package/dist/templates/filter-type.js +9 -5
- package/dist/templates/filter-type.js.map +1 -1
- package/dist/templates/find-templates.d.ts +4 -0
- package/dist/templates/find-templates.d.ts.map +1 -0
- package/dist/templates/find-templates.js +15 -0
- package/dist/templates/find-templates.js.map +1 -0
- package/dist/templates/fr010-field-mapping.d.ts +2 -0
- package/dist/templates/fr010-field-mapping.d.ts.map +1 -1
- package/dist/templates/fr010-field-mapping.js +10 -6
- package/dist/templates/fr010-field-mapping.js.map +1 -1
- package/dist/templates/inferred-types.d.ts +44 -7
- package/dist/templates/inferred-types.d.ts.map +1 -1
- package/dist/templates/inferred-types.js +107 -16
- package/dist/templates/inferred-types.js.map +1 -1
- package/dist/templates/mermaid-er.d.ts +35 -2
- package/dist/templates/mermaid-er.d.ts.map +1 -1
- package/dist/templates/mermaid-er.js +174 -7
- package/dist/templates/mermaid-er.js.map +1 -1
- package/dist/templates/output-parser.d.ts.map +1 -1
- package/dist/templates/output-parser.js +30 -79
- package/dist/templates/output-parser.js.map +1 -1
- package/dist/templates/output-prompt.d.ts.map +1 -1
- package/dist/templates/output-prompt.js +2 -2
- package/dist/templates/output-prompt.js.map +1 -1
- package/dist/templates/queries-file.d.ts.map +1 -1
- package/dist/templates/queries-file.js +112 -4
- package/dist/templates/queries-file.js.map +1 -1
- package/dist/templates/queries.d.ts +5 -0
- package/dist/templates/queries.d.ts.map +1 -1
- package/dist/templates/queries.js +7 -7
- package/dist/templates/queries.js.map +1 -1
- package/dist/templates/recover-schema-emitter.d.ts +8 -0
- package/dist/templates/recover-schema-emitter.d.ts.map +1 -0
- package/dist/templates/recover-schema-emitter.js +64 -0
- package/dist/templates/recover-schema-emitter.js.map +1 -0
- package/dist/templates/relations-block.js +10 -0
- package/dist/templates/relations-block.js.map +1 -1
- package/dist/templates/render-helper.d.ts.map +1 -1
- package/dist/templates/render-helper.js +4 -4
- package/dist/templates/render-helper.js.map +1 -1
- package/dist/templates/routes-file.d.ts.map +1 -1
- package/dist/templates/routes-file.js +183 -6
- package/dist/templates/routes-file.js.map +1 -1
- package/dist/templates/tph-discriminator.d.ts +56 -0
- package/dist/templates/tph-discriminator.d.ts.map +1 -0
- package/dist/templates/tph-discriminator.js +180 -0
- package/dist/templates/tph-discriminator.js.map +1 -0
- package/dist/templates/value-object-file.d.ts +2 -1
- package/dist/templates/value-object-file.d.ts.map +1 -1
- package/dist/templates/value-object-file.js +32 -4
- package/dist/templates/value-object-file.js.map +1 -1
- package/dist/templates/zod-validators.d.ts +64 -1
- package/dist/templates/zod-validators.d.ts.map +1 -1
- package/dist/templates/zod-validators.js +181 -8
- package/dist/templates/zod-validators.js.map +1 -1
- package/package.json +103 -34
- package/src/column-mapper.ts +25 -8
- package/src/constants.ts +18 -0
- package/src/docs-paths.ts +128 -0
- package/src/enum-import.ts +43 -0
- package/src/enum-shared.ts +95 -0
- package/src/generator-registry.ts +204 -0
- package/src/generator.ts +6 -0
- package/src/generators/api-doc-render.ts +572 -0
- package/src/generators/api-docs-file.ts +146 -0
- package/src/generators/api-field-shape.ts +114 -0
- package/src/generators/api-label.ts +7 -0
- package/src/generators/api-model.ts +1067 -0
- package/src/generators/docs-data-builder.ts +479 -185
- package/src/generators/docs-data.ts +139 -28
- package/src/generators/docs-file.ts +205 -39
- package/src/generators/entity-file.ts +31 -15
- package/src/generators/extractor-file.ts +2 -1
- package/src/generators/field-anchor.ts +24 -0
- package/src/generators/index.ts +8 -1
- package/src/generators/mermaid-er.ts +14 -0
- package/src/generators/output-parser-file.ts +3 -4
- package/src/generators/output-prompt-file.ts +2 -1
- package/src/generators/prompt-render-file.ts +3 -4
- package/src/generators/queries-file.ts +9 -3
- package/src/generators/render-helper-file.ts +2 -1
- package/src/generators/routes-file-hono.ts +5 -1
- package/src/generators/routes-file.ts +7 -1
- package/src/generators/template-doc-builder.ts +306 -0
- package/src/generators/template-doc-data.ts +85 -0
- package/src/generators/template-payload-tree.ts +71 -0
- package/src/generators/template-source-annotate.ts +290 -0
- package/src/generators/template-source-render.ts +203 -0
- package/src/generators/trace-helper-file.ts +301 -0
- package/src/index.ts +55 -4
- package/src/metaobjects-config.ts +117 -2
- package/src/naming.ts +48 -0
- package/src/payload-codegen.ts +14 -3
- package/src/projection/extract-view-spec.ts +49 -30
- package/src/relation-resolver.ts +103 -1
- package/src/render-context.ts +4 -0
- package/src/render-engine/embedded-templates.generated.ts +14 -0
- package/src/render-engine/framework-provider.ts +25 -11
- package/src/runner.ts +21 -0
- package/src/templates/docs-file.ts +2 -9
- package/src/templates/drizzle-schema.ts +31 -1
- package/src/templates/entity-constants.ts +1 -1
- package/src/templates/entity-file.ts +16 -5
- package/src/templates/enums-file.ts +50 -0
- package/src/templates/extract-delegate-emitter.ts +5 -6
- package/src/templates/extractor.ts +68 -38
- package/src/templates/field-meta.ts +0 -6
- package/src/templates/filter-allowlist.ts +17 -10
- package/src/templates/filter-type.ts +8 -6
- package/src/templates/find-templates.ts +15 -0
- package/src/templates/fr010-field-mapping.ts +10 -8
- package/src/templates/inferred-types.ts +108 -18
- package/src/templates/mermaid-er.ts +176 -8
- package/src/templates/output-parser.ts +30 -79
- package/src/templates/output-prompt.ts +2 -1
- package/src/templates/queries-file.ts +132 -3
- package/src/templates/queries.ts +15 -7
- package/src/templates/relations-block.ts +17 -0
- package/src/templates/render-helper.ts +4 -3
- package/src/templates/routes-file.ts +233 -6
- package/src/templates/tph-discriminator.ts +232 -0
- package/src/templates/value-object-file.ts +38 -4
- package/src/templates/zod-validators.ts +204 -7
- package/templates/api/agent-api.md.mustache +30 -0
- package/templates/api/entity-api.md.mustache +69 -0
- package/templates/api/index.md.mustache +21 -0
- package/templates/docs/entity-page.md.mustache +33 -21
- package/templates/docs/template-page.md.mustache +56 -0
- package/src/templates/extract-schema-emitter.ts +0 -111
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// Annotated-template IR (linked-template-source-docs, Task 1).
|
|
2
|
+
//
|
|
3
|
+
// annotateTemplate parses a Mustache template into an ordered TplToken[] where
|
|
4
|
+
// every {{variable}} / {{#section}} is resolved to the payload field it
|
|
5
|
+
// references plus that field's doc link. It tokenizes with the SAME parser
|
|
6
|
+
// verify walks (`parseTemplate` from @metaobjectsdev/render) and resolves each
|
|
7
|
+
// path with verify's EXPORTED `resolveTemplateVariable` — so the annotator and
|
|
8
|
+
// the build-time drift gate share ONE resolution and can never disagree (a
|
|
9
|
+
// later conformance gate asserts exactly that).
|
|
10
|
+
//
|
|
11
|
+
// Reuse, not reimplementation:
|
|
12
|
+
// • parseTemplate — the render verify engine's Mustache.parse.
|
|
13
|
+
// • resolveTemplateVariable — verify's context-stack walk (sections push the
|
|
14
|
+
// nested subtree; dotted paths descend). Generic
|
|
15
|
+
// over the node, so an ENRICHED tree (carrying
|
|
16
|
+
// owner/type/required) resolves identically.
|
|
17
|
+
//
|
|
18
|
+
// The annotator is a pure function over an enriched payload tree + the source —
|
|
19
|
+
// no metadata import, no I/O — so it is unit-testable and golden-pinnable.
|
|
20
|
+
import { parseTemplate, resolveTemplateVariable, } from "@metaobjectsdev/render";
|
|
21
|
+
import { fieldAnchorSlug } from "./field-anchor.js";
|
|
22
|
+
/** The doc-page href for a resolved field: `./<OwnerVO>.md#field-<name>`. The
|
|
23
|
+
* anchor slug comes from the SHARED `fieldAnchorSlug()` (prefixed — avoids
|
|
24
|
+
* colliding with other page anchors), the SAME helper the entity page uses to
|
|
25
|
+
* emit its per-field `<a id="field-<name>">` anchor, so the link and the anchor
|
|
26
|
+
* can never drift. */
|
|
27
|
+
function fieldHref(owner, name) {
|
|
28
|
+
return `./${owner}.md#${fieldAnchorSlug(name)}`;
|
|
29
|
+
}
|
|
30
|
+
function toResolvedField(f) {
|
|
31
|
+
return { owner: f.owner, name: f.name, type: f.type, required: f.required };
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parse `source` into an annotated IR, resolving each variable/section against
|
|
35
|
+
* the enriched `payload` tree using verify's shared resolution.
|
|
36
|
+
*/
|
|
37
|
+
export function annotateTemplate(source, payload, opts) {
|
|
38
|
+
const root = payload;
|
|
39
|
+
const out = [];
|
|
40
|
+
let cursor = 0;
|
|
41
|
+
// How a resolved field's href is built: the injected layout-aware resolver
|
|
42
|
+
// when provided, else the flat default (byte-identical to today's output).
|
|
43
|
+
const buildFieldHref = opts.fieldHref ?? fieldHref;
|
|
44
|
+
// Emit verbatim source between `cursor` and `to` as a text token, advancing
|
|
45
|
+
// the cursor. This recovers literal text AND any span Mustache trimmed as
|
|
46
|
+
// standalone (e.g. the newline after a standalone partial/section), so the
|
|
47
|
+
// concatenated tokens reproduce the source byte-for-byte.
|
|
48
|
+
function emitTextUpTo(to) {
|
|
49
|
+
if (to > cursor) {
|
|
50
|
+
out.push({ kind: "text", text: source.slice(cursor, to) });
|
|
51
|
+
cursor = to;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function resolveAt(stack, path) {
|
|
55
|
+
const hit = resolveTemplateVariable(stack, path);
|
|
56
|
+
if (!hit)
|
|
57
|
+
return undefined;
|
|
58
|
+
const field = toResolvedField(hit);
|
|
59
|
+
return { field, href: buildFieldHref(field.owner, field.name) };
|
|
60
|
+
}
|
|
61
|
+
// Build a variable token ({{x}} or {{&x}}/{{{x}}}). The implicit iterator
|
|
62
|
+
// `.` is always valid against the current context; any other path resolves
|
|
63
|
+
// against the enriched tree (carrying field + href when found).
|
|
64
|
+
function makeVarToken(kind, raw, value, stack) {
|
|
65
|
+
if (value === ".")
|
|
66
|
+
return { kind, raw, path: value, valid: true };
|
|
67
|
+
const r = resolveAt(stack, value);
|
|
68
|
+
return r
|
|
69
|
+
? { kind, raw, path: value, field: r.field, href: r.href, valid: true }
|
|
70
|
+
: { kind, raw, path: value, valid: false };
|
|
71
|
+
}
|
|
72
|
+
function walk(tokens, stack) {
|
|
73
|
+
for (const tok of tokens) {
|
|
74
|
+
const type = tok[0];
|
|
75
|
+
const value = tok[1];
|
|
76
|
+
const start = tok[2];
|
|
77
|
+
const end = tok[3];
|
|
78
|
+
// Recover any source between the previous token and this tag (literal
|
|
79
|
+
// text, or trimmed standalone whitespace).
|
|
80
|
+
emitTextUpTo(start);
|
|
81
|
+
switch (type) {
|
|
82
|
+
case "text": {
|
|
83
|
+
out.push({ kind: "text", text: source.slice(start, end) });
|
|
84
|
+
cursor = end;
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case "name": {
|
|
88
|
+
// {{x}} — escaped variable.
|
|
89
|
+
const raw = source.slice(start, end);
|
|
90
|
+
cursor = end;
|
|
91
|
+
out.push(makeVarToken("var", raw, value, stack));
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
case "&":
|
|
95
|
+
case "{": {
|
|
96
|
+
// {{&x}} / {{{x}}} — unescaped variable (mustache.js emits "&" for both).
|
|
97
|
+
const raw = source.slice(start, end);
|
|
98
|
+
cursor = end;
|
|
99
|
+
out.push(makeVarToken("unescaped", raw, value, stack));
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
case "#":
|
|
103
|
+
case "^": {
|
|
104
|
+
// {{#x}}…{{/x}} (section) / {{^x}}…{{/x}} (inverted). `end` is the end
|
|
105
|
+
// of the OPENING tag; subTokens at [4]; [5] is where the closing tag
|
|
106
|
+
// begins. Emit the open tag, recurse the body in the pushed context,
|
|
107
|
+
// then emit the close tag.
|
|
108
|
+
const sub = Array.isArray(tok[4]) ? tok[4] : [];
|
|
109
|
+
const closeStart = tok[5];
|
|
110
|
+
const openRaw = source.slice(start, end);
|
|
111
|
+
cursor = end;
|
|
112
|
+
const isImplicit = value === ".";
|
|
113
|
+
const r = isImplicit ? undefined : resolveAt(stack, value);
|
|
114
|
+
const kind = type === "#" ? "section" : "inverted";
|
|
115
|
+
out.push(r
|
|
116
|
+
? {
|
|
117
|
+
kind,
|
|
118
|
+
raw: openRaw,
|
|
119
|
+
path: value,
|
|
120
|
+
field: r.field,
|
|
121
|
+
href: r.href,
|
|
122
|
+
}
|
|
123
|
+
: { kind, raw: openRaw, path: value });
|
|
124
|
+
// `#` over a container pushes its element fields; `^` (and `#` over a
|
|
125
|
+
// scalar conditional) keep the current context — EXACTLY verify's rule.
|
|
126
|
+
const hit = isImplicit
|
|
127
|
+
? undefined
|
|
128
|
+
: resolveTemplateVariable(stack, value);
|
|
129
|
+
const nested = type === "#" ? hit?.fields : undefined;
|
|
130
|
+
const childStack = nested !== undefined ? [...stack, nested] : stack;
|
|
131
|
+
walk(sub, childStack);
|
|
132
|
+
// The closing tag `{{/value}}` runs from closeStart to the end of the
|
|
133
|
+
// section. Recover any body remainder Mustache trimmed, then emit close.
|
|
134
|
+
emitTextUpTo(closeStart);
|
|
135
|
+
// The close tag's exact end isn't in the token; derive it from the
|
|
136
|
+
// literal `{{/…}}` form starting at closeStart so the raw is verbatim.
|
|
137
|
+
const closeRaw = readCloseTag(source, closeStart, value);
|
|
138
|
+
out.push({ kind: "close", raw: closeRaw, path: value });
|
|
139
|
+
cursor = closeStart + closeRaw.length;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
case ">": {
|
|
143
|
+
// {{>ref}} — partial.
|
|
144
|
+
const raw = source.slice(start, end);
|
|
145
|
+
cursor = end;
|
|
146
|
+
const href = opts.resolvePartialHref?.(value);
|
|
147
|
+
out.push(href !== undefined
|
|
148
|
+
? { kind: "partial", raw, ref: value, href }
|
|
149
|
+
: { kind: "partial", raw, ref: value });
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
case "!": {
|
|
153
|
+
// {{! comment }}.
|
|
154
|
+
out.push({ kind: "comment", raw: source.slice(start, end) });
|
|
155
|
+
cursor = end;
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
default: {
|
|
159
|
+
// set-delimiter (=) or any other: preserve verbatim as text.
|
|
160
|
+
if (Number.isFinite(end) && end > start) {
|
|
161
|
+
out.push({ kind: "text", text: source.slice(start, end) });
|
|
162
|
+
cursor = end;
|
|
163
|
+
}
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
walk(parseTemplate(source), [root]);
|
|
170
|
+
// Any trailing source after the last token (e.g. a standalone-trimmed final
|
|
171
|
+
// newline) is recovered as text.
|
|
172
|
+
emitTextUpTo(source.length);
|
|
173
|
+
return out;
|
|
174
|
+
}
|
|
175
|
+
// Read the verbatim closing tag `{{/name}}` (with any inner whitespace the
|
|
176
|
+
// author wrote) starting at `from`. Mustache only gives the close-tag start, so
|
|
177
|
+
// we locate the terminating `}}` from there to recover the exact source span.
|
|
178
|
+
function readCloseTag(source, from, _name) {
|
|
179
|
+
const close = source.indexOf("}}", from);
|
|
180
|
+
if (close === -1)
|
|
181
|
+
return source.slice(from);
|
|
182
|
+
return source.slice(from, close + 2);
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=template-source-annotate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-source-annotate.js","sourceRoot":"","sources":["../../src/generators/template-source-annotate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { TplToken } from "./template-source-annotate.js";
|
|
2
|
+
/**
|
|
3
|
+
* Reconstruct the verbatim template source from the tokens and wrap it in a
|
|
4
|
+
* ```mustache fenced block. Concatenating `text` (text tokens) / `raw` (tag
|
|
5
|
+
* tokens) round-trips the original source byte-for-byte (the annotator pins
|
|
6
|
+
* this), so the fence body is the clean, highlightable source.
|
|
7
|
+
*/
|
|
8
|
+
export declare function renderSourceBlock(tokens: TplToken[]): string;
|
|
9
|
+
/**
|
|
10
|
+
* A Markdown table of the unique referenced variables. Resolved variables link
|
|
11
|
+
* to their field doc (`[owner.name](href)`); unresolved ones are em-dashed and
|
|
12
|
+
* carry a "not on payload" note in the Type cell. Returns "" when there are no
|
|
13
|
+
* variables (keeps the page clean).
|
|
14
|
+
*/
|
|
15
|
+
export declare function renderVariablesTable(tokens: TplToken[]): string;
|
|
16
|
+
/**
|
|
17
|
+
* The collapsed <details> "Linked view": a <pre> reproducing the template where
|
|
18
|
+
* each token is an inline-styled <span> (color by kind) and each resolved
|
|
19
|
+
* variable/section is additionally wrapped in a clickable <a href>. Whitespace
|
|
20
|
+
* and newlines are preserved inside the <pre>. Collapsed by default (no `open`)
|
|
21
|
+
* so the plain/agent view stays clean; a human expands it for the clickable vars.
|
|
22
|
+
*/
|
|
23
|
+
export declare function renderRichLinkedHtml(tokens: TplToken[]): string;
|
|
24
|
+
//# sourceMappingURL=template-source-render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-source-render.d.ts","sourceRoot":"","sources":["../../src/generators/template-source-render.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAI9D;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAG5D;AAoDD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAsB/D;AAsCD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAyC/D"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
// Template-source renderers (linked-template-source-docs, Task 3).
|
|
2
|
+
//
|
|
3
|
+
// ONE annotated IR (the TplToken[] from annotateTemplate), THREE doc forms — no
|
|
4
|
+
// re-derivation, no second parse. All three are pure functions over the tokens:
|
|
5
|
+
//
|
|
6
|
+
// • renderSourceBlock — the verbatim template inside a ```mustache fence.
|
|
7
|
+
// The annotator round-trips the source via text/raw,
|
|
8
|
+
// so the fenced body equals the original byte-for-byte
|
|
9
|
+
// and any viewer/site highlighter colors it.
|
|
10
|
+
// • renderVariablesTable — a Markdown table of the UNIQUE referenced variables
|
|
11
|
+
// (vars + sections that resolve to a field), each a
|
|
12
|
+
// Markdown-native `[owner.name](href)` link (or flagged
|
|
13
|
+
// "not on payload" when unresolved). Agent-clean.
|
|
14
|
+
// • renderRichLinkedHtml — a collapsed <details> whose <pre> reproduces the
|
|
15
|
+
// template with each token in a SELF-CONTAINED
|
|
16
|
+
// inline-styled <span> (color per kind) and each
|
|
17
|
+
// resolved variable/section wrapped in a clickable
|
|
18
|
+
// <a href>. Inline styles only (no external CSS) so it
|
|
19
|
+
// renders identically on GitHub and a static site.
|
|
20
|
+
//
|
|
21
|
+
// Color (block + rich view), links (table + rich view), agent-cleanliness (block
|
|
22
|
+
// + table) — all from the same source of truth.
|
|
23
|
+
// ── 1. Source block ────────────────────────────────────────────────────────
|
|
24
|
+
/**
|
|
25
|
+
* Reconstruct the verbatim template source from the tokens and wrap it in a
|
|
26
|
+
* ```mustache fenced block. Concatenating `text` (text tokens) / `raw` (tag
|
|
27
|
+
* tokens) round-trips the original source byte-for-byte (the annotator pins
|
|
28
|
+
* this), so the fence body is the clean, highlightable source.
|
|
29
|
+
*/
|
|
30
|
+
export function renderSourceBlock(tokens) {
|
|
31
|
+
const source = reconstructSource(tokens);
|
|
32
|
+
return "```mustache\n" + source + "\n```";
|
|
33
|
+
}
|
|
34
|
+
/** Concatenate the verbatim span of every token (text or tag raw). */
|
|
35
|
+
function reconstructSource(tokens) {
|
|
36
|
+
let out = "";
|
|
37
|
+
for (const t of tokens)
|
|
38
|
+
out += t.kind === "text" ? t.text : t.raw;
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
/** Collect the unique referenced variables (vars/unescaped + sections/inverted
|
|
42
|
+
* that carry a path), deduped by path, in first-seen order. Implicit-iterator
|
|
43
|
+
* `.` tokens and close tokens are not "variables" and are skipped. */
|
|
44
|
+
function collectVarRows(tokens) {
|
|
45
|
+
const seen = new Set();
|
|
46
|
+
const rows = [];
|
|
47
|
+
for (const t of tokens) {
|
|
48
|
+
const isRef = t.kind === "var" ||
|
|
49
|
+
t.kind === "unescaped" ||
|
|
50
|
+
t.kind === "section" ||
|
|
51
|
+
t.kind === "inverted";
|
|
52
|
+
if (!isRef)
|
|
53
|
+
continue;
|
|
54
|
+
if (t.path === "." || seen.has(t.path))
|
|
55
|
+
continue;
|
|
56
|
+
seen.add(t.path);
|
|
57
|
+
rows.push({
|
|
58
|
+
path: t.path,
|
|
59
|
+
owner: t.field?.owner,
|
|
60
|
+
name: t.field?.name,
|
|
61
|
+
type: t.field?.type,
|
|
62
|
+
required: t.field?.required,
|
|
63
|
+
href: t.href,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return rows;
|
|
67
|
+
}
|
|
68
|
+
/** Markdown-escape a table cell whose text may contain a `|`. */
|
|
69
|
+
function mdCell(text) {
|
|
70
|
+
return text.replace(/\|/g, "\\|");
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A Markdown table of the unique referenced variables. Resolved variables link
|
|
74
|
+
* to their field doc (`[owner.name](href)`); unresolved ones are em-dashed and
|
|
75
|
+
* carry a "not on payload" note in the Type cell. Returns "" when there are no
|
|
76
|
+
* variables (keeps the page clean).
|
|
77
|
+
*/
|
|
78
|
+
export function renderVariablesTable(tokens) {
|
|
79
|
+
const rows = collectVarRows(tokens);
|
|
80
|
+
if (rows.length === 0)
|
|
81
|
+
return "";
|
|
82
|
+
const lines = [
|
|
83
|
+
"| Variable | Field | Type | Required |",
|
|
84
|
+
"| --- | --- | --- | --- |",
|
|
85
|
+
];
|
|
86
|
+
for (const r of rows) {
|
|
87
|
+
const variable = `\`{{${mdCell(r.path)}}}\``;
|
|
88
|
+
if (r.href && r.owner && r.name) {
|
|
89
|
+
const field = `[${r.owner}.${r.name}](${r.href})`;
|
|
90
|
+
const type = r.type ? mdCell(r.type) : "—";
|
|
91
|
+
const required = r.required ? "yes" : "no";
|
|
92
|
+
lines.push(`| ${variable} | ${field} | ${type} | ${required} |`);
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
// Unresolved: no field/type/required. Keep the 4-column shape; flag it
|
|
96
|
+
// "not on payload" in the Field cell, em-dash the rest.
|
|
97
|
+
lines.push(`| ${variable} | — (not on payload) | — | — |`);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return lines.join("\n");
|
|
101
|
+
}
|
|
102
|
+
// ── 3. Rich linked HTML ────────────────────────────────────────────────────
|
|
103
|
+
// Per-kind inline color (self-contained — no external CSS, no classes). Chosen
|
|
104
|
+
// for legibility on both GitHub's light/dark Markdown and a generic docs site.
|
|
105
|
+
const STYLE_VAR = "color:#0969da"; // blue — escaped/unescaped variable
|
|
106
|
+
const STYLE_SECTION = "color:#8250df"; // purple — section / inverted / close
|
|
107
|
+
const STYLE_PARTIAL = "color:#1a7f7a"; // teal — partial reference
|
|
108
|
+
const STYLE_COMMENT = "color:#6e7781;font-style:italic"; // gray italic — comment
|
|
109
|
+
/** HTML-escape literal text so `<`, `>`, `&`, `"` in the template don't break
|
|
110
|
+
* the surrounding HTML. Quotes are escaped too so token raw is safe in any
|
|
111
|
+
* attribute-adjacent position. */
|
|
112
|
+
function escapeHtml(s) {
|
|
113
|
+
return s
|
|
114
|
+
.replace(/&/g, "&")
|
|
115
|
+
.replace(/</g, "<")
|
|
116
|
+
.replace(/>/g, ">")
|
|
117
|
+
.replace(/"/g, """);
|
|
118
|
+
}
|
|
119
|
+
/** An inline-styled span for a token kind, escaping the inner verbatim text. */
|
|
120
|
+
function styledSpan(style, inner) {
|
|
121
|
+
return `<span style="${style}">${inner}</span>`;
|
|
122
|
+
}
|
|
123
|
+
/** A styled span for a token kind, wrapped in a clickable `<a href>` when the
|
|
124
|
+
* token resolved to a link (else the bare span). The raw text is HTML-escaped. */
|
|
125
|
+
function linkSpan(style, raw, href) {
|
|
126
|
+
const span = styledSpan(style, escapeHtml(raw));
|
|
127
|
+
return href ? `<a href="${escapeHtml(href)}">${span}</a>` : span;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The collapsed <details> "Linked view": a <pre> reproducing the template where
|
|
131
|
+
* each token is an inline-styled <span> (color by kind) and each resolved
|
|
132
|
+
* variable/section is additionally wrapped in a clickable <a href>. Whitespace
|
|
133
|
+
* and newlines are preserved inside the <pre>. Collapsed by default (no `open`)
|
|
134
|
+
* so the plain/agent view stays clean; a human expands it for the clickable vars.
|
|
135
|
+
*/
|
|
136
|
+
export function renderRichLinkedHtml(tokens) {
|
|
137
|
+
let pre = "";
|
|
138
|
+
for (const t of tokens) {
|
|
139
|
+
switch (t.kind) {
|
|
140
|
+
case "text": {
|
|
141
|
+
// Default color; escape literal text verbatim (preserves newlines).
|
|
142
|
+
pre += escapeHtml(t.text);
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
case "var":
|
|
146
|
+
case "unescaped": {
|
|
147
|
+
pre += linkSpan(STYLE_VAR, t.raw, t.href);
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
case "section":
|
|
151
|
+
case "inverted":
|
|
152
|
+
case "close": {
|
|
153
|
+
// Only open tags (section/inverted) carry an href; close tags don't.
|
|
154
|
+
const href = "href" in t ? t.href : undefined;
|
|
155
|
+
pre += linkSpan(STYLE_SECTION, t.raw, href);
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
case "partial": {
|
|
159
|
+
pre += linkSpan(STYLE_PARTIAL, t.raw, t.href);
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
case "comment": {
|
|
163
|
+
pre += styledSpan(STYLE_COMMENT, escapeHtml(t.raw));
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return ("<details>\n" +
|
|
169
|
+
"<summary>Linked view</summary>\n\n" +
|
|
170
|
+
'<pre style="white-space:pre-wrap;word-break:break-word">' +
|
|
171
|
+
pre +
|
|
172
|
+
"</pre>\n\n" +
|
|
173
|
+
"</details>");
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=template-source-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-source-render.js","sourceRoot":"","sources":["../../src/generators/template-source-render.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,EAAE;AACF,gFAAgF;AAChF,gFAAgF;AAChF,EAAE;AACF,gFAAgF;AAChF,iFAAiF;AACjF,mFAAmF;AACnF,yEAAyE;AACzE,kFAAkF;AAClF,gFAAgF;AAChF,oFAAoF;AACpF,8EAA8E;AAC9E,+EAA+E;AAC/E,2EAA2E;AAC3E,6EAA6E;AAC7E,+EAA+E;AAC/E,mFAAmF;AACnF,+EAA+E;AAC/E,EAAE;AACF,iFAAiF;AACjF,gDAAgD;AAIhD,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAkB;IACnD,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,OAAO,eAAe,GAAG,MAAM,GAAG,OAAO,CAAC;AAC3C,CAAC;AAED,sEAAsE;AACtE,SAAS,iBAAiB,CAAC,MAAkB;IAC5C,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,GAAG,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAClE,OAAO,GAAG,CAAC;AACZ,CAAC;AAaD;;uEAEuE;AACvE,SAAS,cAAc,CAAC,MAAkB;IACzC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACxB,MAAM,KAAK,GACV,CAAC,CAAC,IAAI,KAAK,KAAK;YAChB,CAAC,CAAC,IAAI,KAAK,WAAW;YACtB,CAAC,CAAC,IAAI,KAAK,SAAS;YACpB,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC;QACvB,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,IAAI,CAAC,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAAE,SAAS;QACjD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACjB,IAAI,CAAC,IAAI,CAAC;YACT,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK;YACrB,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI;YACnB,IAAI,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI;YACnB,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ;YAC3B,IAAI,EAAE,CAAC,CAAC,IAAI;SACZ,CAAC,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACb,CAAC;AAED,iEAAiE;AACjE,SAAS,MAAM,CAAC,IAAY;IAC3B,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAkB;IACtD,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEjC,MAAM,KAAK,GAAa;QACvB,wCAAwC;QACxC,2BAA2B;KAC3B,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAG,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;QAC7C,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YACjC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC;YAClD,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;YAC3C,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,MAAM,KAAK,MAAM,IAAI,MAAM,QAAQ,IAAI,CAAC,CAAC;QAClE,CAAC;aAAM,CAAC;YACP,uEAAuE;YACvE,wDAAwD;YACxD,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,iCAAiC,CAAC,CAAC;QAC5D,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED,8EAA8E;AAE9E,+EAA+E;AAC/E,+EAA+E;AAC/E,MAAM,SAAS,GAAG,eAAe,CAAC,CAAC,oCAAoC;AACvE,MAAM,aAAa,GAAG,eAAe,CAAC,CAAC,sCAAsC;AAC7E,MAAM,aAAa,GAAG,eAAe,CAAC,CAAC,2BAA2B;AAClE,MAAM,aAAa,GAAG,iCAAiC,CAAC,CAAC,wBAAwB;AAEjF;;mCAEmC;AACnC,SAAS,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC;SACN,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC3B,CAAC;AAED,gFAAgF;AAChF,SAAS,UAAU,CAAC,KAAa,EAAE,KAAa;IAC/C,OAAO,gBAAgB,KAAK,KAAK,KAAK,SAAS,CAAC;AACjD,CAAC;AAED;mFACmF;AACnF,SAAS,QAAQ,CAChB,KAAa,EACb,GAAW,EACX,IAAwB;IAExB,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAChD,OAAO,IAAI,CAAC,CAAC,CAAC,YAAY,UAAU,CAAC,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAClE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAkB;IACtD,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACxB,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;YAChB,KAAK,MAAM,CAAC,CAAC,CAAC;gBACb,oEAAoE;gBACpE,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC1B,MAAM;YACP,CAAC;YACD,KAAK,KAAK,CAAC;YACX,KAAK,WAAW,CAAC,CAAC,CAAC;gBAClB,GAAG,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC1C,MAAM;YACP,CAAC;YACD,KAAK,SAAS,CAAC;YACf,KAAK,UAAU,CAAC;YAChB,KAAK,OAAO,CAAC,CAAC,CAAC;gBACd,qEAAqE;gBACrE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC9C,GAAG,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBAC5C,MAAM;YACP,CAAC;YACD,KAAK,SAAS,CAAC,CAAC,CAAC;gBAChB,GAAG,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC9C,MAAM;YACP,CAAC;YACD,KAAK,SAAS,CAAC,CAAC,CAAC;gBAChB,GAAG,IAAI,UAAU,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACpD,MAAM;YACP,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,CACN,aAAa;QACb,oCAAoC;QACpC,0DAA0D;QAC1D,GAAG;QACH,YAAY;QACZ,YAAY,CACZ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type GeneratorFactory } from "../generator.js";
|
|
2
|
+
export interface TraceHelperOpts {
|
|
3
|
+
/** Output directory prefix relative to the target's outDir. Default: "" (root). */
|
|
4
|
+
outDir?: string;
|
|
5
|
+
/** Optional named output target (registry key). Defaults to "default". */
|
|
6
|
+
target?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare const traceHelperFile: GeneratorFactory<TraceHelperOpts>;
|
|
9
|
+
//# sourceMappingURL=trace-helper-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-helper-file.d.ts","sourceRoot":"","sources":["../../src/generators/trace-helper-file.ts"],"names":[],"mappings":"AA6BA,OAAO,EAGL,KAAK,gBAAgB,EAEtB,MAAM,iBAAiB,CAAC;AAQzB,MAAM,WAAW,eAAe;IAC9B,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAiBD,eAAO,MAAM,eAAe,EA4OvB,gBAAgB,CAAC,eAAe,CAAC,CAAC"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// server/typescript/packages/codegen-ts/src/generators/trace-helper-file.ts
|
|
2
|
+
//
|
|
3
|
+
// Stock generator that emits one <Entity>.trace.ts helper file for each concrete
|
|
4
|
+
// entity that (a) extends LlmCallBase (directly or transitively) and (b) nests a
|
|
5
|
+
// template.prompt with @payloadRef and/or @responseRef.
|
|
6
|
+
//
|
|
7
|
+
// The emitted helper exports an async function `record<Entity>(om, responseMo, input)`
|
|
8
|
+
// that EXTRACTS the typed response VO itself and persists ONE row = base envelope +
|
|
9
|
+
// raw I/O (via buildLlmCallRow) PLUS the typed voRequest/voResponse columns. The
|
|
10
|
+
// helper is typed against the generated payload interfaces (request + response VOs)
|
|
11
|
+
// so call-sites get compile-time checks.
|
|
12
|
+
//
|
|
13
|
+
// NOTE: ObjectManager does not expose its loaded metadata root, so the caller must
|
|
14
|
+
// pass the resolved `responseMo: MetaObject` explicitly. The generated helper
|
|
15
|
+
// documents this in its JSDoc.
|
|
16
|
+
//
|
|
17
|
+
// Consumer wiring (metaobjects.config.ts):
|
|
18
|
+
// generators: [..., entityFile(), queriesFile(), traceHelperFile(), barrel()]
|
|
19
|
+
import { TYPE_OBJECT, TYPE_TEMPLATE, TEMPLATE_SUBTYPE_PROMPT, TEMPLATE_ATTR_PAYLOAD_REF, TEMPLATE_ATTR_RESPONSE_REF, TEMPLATE_ATTR_FORMAT, TEMPLATE_ATTR_TEXT_REF, } from "@metaobjectsdev/metadata";
|
|
20
|
+
import { perEntity, } from "../generator.js";
|
|
21
|
+
import { generatePayloadInterfacesBatch } from "../payload-codegen.js";
|
|
22
|
+
import { GENERATED_HEADER } from "../constants.js";
|
|
23
|
+
import { tphDiscriminatorPin } from "../templates/zod-validators.js";
|
|
24
|
+
/** Short name of the shipped abstract base every trace entity extends. */
|
|
25
|
+
const LLM_CALL_BASE = "LlmCallBase";
|
|
26
|
+
/** Walk the super chain looking for a node named LLM_CALL_BASE. */
|
|
27
|
+
function extendsBase(obj) {
|
|
28
|
+
let cur = obj.superResolved;
|
|
29
|
+
while (cur !== undefined) {
|
|
30
|
+
if (cur.name === LLM_CALL_BASE)
|
|
31
|
+
return true;
|
|
32
|
+
cur = cur.superResolved;
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
/** Capitalise the first character. */
|
|
37
|
+
function pascal(s) {
|
|
38
|
+
return s.length > 0 ? s[0].toUpperCase() + s.slice(1) : s;
|
|
39
|
+
}
|
|
40
|
+
export const traceHelperFile = function traceHelperFile(opts) {
|
|
41
|
+
const dirPrefix = opts?.outDir ? `${opts.outDir.replace(/\/$/, "")}/` : "";
|
|
42
|
+
const generator = {
|
|
43
|
+
name: "trace-helper",
|
|
44
|
+
generate: perEntity((entity, ctx) => {
|
|
45
|
+
// Only concrete entities derived from LlmCallBase.
|
|
46
|
+
if (entity.isAbstract)
|
|
47
|
+
return [];
|
|
48
|
+
if (!extendsBase(entity))
|
|
49
|
+
return [];
|
|
50
|
+
// Find the nested template.prompt.
|
|
51
|
+
const prompt = entity.ownChildren().find((c) => c.type === TYPE_TEMPLATE && c.subType === TEMPLATE_SUBTYPE_PROMPT);
|
|
52
|
+
if (prompt === undefined)
|
|
53
|
+
return [];
|
|
54
|
+
const payloadRef = prompt.ownAttr(TEMPLATE_ATTR_PAYLOAD_REF);
|
|
55
|
+
const responseRef = prompt.ownAttr(TEMPLATE_ATTR_RESPONSE_REF);
|
|
56
|
+
// @responseRef types the result; @payloadRef types the request. Both gate
|
|
57
|
+
// the helper: the entity must declare voRequest/voResponse field.object
|
|
58
|
+
// columns (authored) for these writes to land, and the prompt's refs name
|
|
59
|
+
// the VOs to render/extract into.
|
|
60
|
+
if (typeof responseRef !== "string")
|
|
61
|
+
return [];
|
|
62
|
+
if (typeof payloadRef !== "string")
|
|
63
|
+
return [];
|
|
64
|
+
const entityName = entity.name;
|
|
65
|
+
const fnName = `record${pascal(entityName)}`;
|
|
66
|
+
// STI: a trace entity that is a TPH subtype stamps its declared
|
|
67
|
+
// discriminator value as callType and drops callType from the caller input
|
|
68
|
+
// (industry-standard STI — the discriminator is framework-managed).
|
|
69
|
+
const tphPin = tphDiscriminatorPin(entity);
|
|
70
|
+
const sti = tphPin !== undefined;
|
|
71
|
+
const callTypeValue = sti ? tphPin.value : entityName;
|
|
72
|
+
// Emitted record<Entity> fragments. The caller never supplies the derived
|
|
73
|
+
// status/errorDetail (the helper computes them from extraction), and an STI
|
|
74
|
+
// subtype additionally drops the framework-managed callType discriminator.
|
|
75
|
+
const recordInputOmit = sti
|
|
76
|
+
? `"llmRequest" | "status" | "errorDetail" | "callType"`
|
|
77
|
+
: `"llmRequest" | "status" | "errorDetail"`;
|
|
78
|
+
// The object spread passed to buildLlmCallRow: STI subtypes stamp their
|
|
79
|
+
// discriminator value, all helpers fold in the derived status/errorDetail.
|
|
80
|
+
const recordBuildArg = sti
|
|
81
|
+
? `{ ...input, callType: ${JSON.stringify(callTypeValue)}, status, errorDetail }`
|
|
82
|
+
: `{ ...input, status, errorDetail }`;
|
|
83
|
+
// Derive the parse format from the prompt's @format attr.
|
|
84
|
+
// "xml" → Format.XML; absent or any other value → Format.JSON.
|
|
85
|
+
const promptFormat = prompt.ownAttr(TEMPLATE_ATTR_FORMAT);
|
|
86
|
+
const formatLiteral = typeof promptFormat === "string" && promptFormat.toLowerCase() === "xml"
|
|
87
|
+
? "Format.XML"
|
|
88
|
+
: "Format.JSON";
|
|
89
|
+
// Collect VO names for interface emission (dedupe via batch emitter).
|
|
90
|
+
// Both refs are guaranteed strings by the guards above.
|
|
91
|
+
const interfaces = generatePayloadInterfacesBatch(ctx.loadedRoot, [payloadRef, responseRef]);
|
|
92
|
+
const requestType = payloadRef;
|
|
93
|
+
// A renderable prompt (carries @textRef) gets an additional call<Entity> helper
|
|
94
|
+
// that renders the prompt text, calls the LLM, then parses + persists a trace row.
|
|
95
|
+
const textRef = prompt.ownAttr(TEMPLATE_ATTR_TEXT_REF);
|
|
96
|
+
const renderable = typeof textRef === "string";
|
|
97
|
+
// Same @format attr, two intentionally different shapes: extract() takes the
|
|
98
|
+
// Format enum (formatLiteral, above → Format.XML/Format.JSON), render() takes the
|
|
99
|
+
// raw format string (renderFormat, here → e.g. "json"/"xml", default "text").
|
|
100
|
+
const renderFormat = typeof promptFormat === "string" ? promptFormat : "text";
|
|
101
|
+
// Build the import block — all imports MUST stay at the top of the emitted file.
|
|
102
|
+
// `extract` + `render` both live in @metaobjectsdev/render: import them together
|
|
103
|
+
// (one de-duplicated statement) when the prompt is renderable, else import only
|
|
104
|
+
// `extract`.
|
|
105
|
+
const importLines = [
|
|
106
|
+
`import type { ObjectManager } from "@metaobjectsdev/runtime-ts";`,
|
|
107
|
+
`import {`,
|
|
108
|
+
` LlmCallDbRecorder,`,
|
|
109
|
+
` buildLlmCallRow,`,
|
|
110
|
+
` persistLlmCallRow,`,
|
|
111
|
+
` extractSchemaFor,`,
|
|
112
|
+
` Format,`,
|
|
113
|
+
` type LlmCallInput,`,
|
|
114
|
+
` type LlmCallRow,`,
|
|
115
|
+
`} from "@metaobjectsdev/runtime-ts";`,
|
|
116
|
+
renderable
|
|
117
|
+
? `import { extract, render, type Provider } from "@metaobjectsdev/render";`
|
|
118
|
+
: `import { extract } from "@metaobjectsdev/render";`,
|
|
119
|
+
`import type { MetaObject } from "@metaobjectsdev/metadata";`,
|
|
120
|
+
];
|
|
121
|
+
if (renderable) {
|
|
122
|
+
importLines.push(`import {`, ` runLlmCall,`, ` type RunLlmCallInput,`, ` type RunLlmCallDeps,`, ` type LlmClient,`, ` type LlmRequest,`, ` type CostFn,`, ` type Clock,`, ` type IdGen,`, `} from "@metaobjectsdev/ai-runtime";`);
|
|
123
|
+
}
|
|
124
|
+
const lines = [
|
|
125
|
+
`// ${GENERATED_HEADER} — DO NOT EDIT.`,
|
|
126
|
+
``,
|
|
127
|
+
...importLines,
|
|
128
|
+
``,
|
|
129
|
+
`// ---- Payload interfaces (inlined) ------------------------------------------`,
|
|
130
|
+
``,
|
|
131
|
+
interfaces.trimEnd(),
|
|
132
|
+
``,
|
|
133
|
+
`// ---- Typed result -----------------------------------------------------------`,
|
|
134
|
+
``,
|
|
135
|
+
`export interface ${entityName}TraceResult {`,
|
|
136
|
+
` status: "ok" | "error";`,
|
|
137
|
+
` errorDetail: string | null;`,
|
|
138
|
+
` /** Parsed response VO, or null when extraction reported a lost-required field. */`,
|
|
139
|
+
` /** Note: voResponse is the plain extracted record typed as the response shape (structural, not an instance). */`,
|
|
140
|
+
` voResponse: ${responseRef} | null;`,
|
|
141
|
+
`}`,
|
|
142
|
+
``,
|
|
143
|
+
`// ---- Record helper ----------------------------------------------------------`,
|
|
144
|
+
``,
|
|
145
|
+
`/**`,
|
|
146
|
+
` * Record a single ${entityName} LLM call: extract the response VO and persist a`,
|
|
147
|
+
` * trace row via ObjectManager regardless of whether extraction succeeded.`,
|
|
148
|
+
` *`,
|
|
149
|
+
` * @param om - ObjectManager wired to the application database.`,
|
|
150
|
+
` * @param responseMo - MetaObject for \`${responseRef}\` (resolve via the loaded`,
|
|
151
|
+
` * metadata root: \`root.findObject("${responseRef}")\`).`,
|
|
152
|
+
` * Passed explicitly because ObjectManager does not expose`,
|
|
153
|
+
` * its loaded metadata root.`,
|
|
154
|
+
` * @param input - LLM call inputs; type \`llmRequest\` as \`${requestType}\`.`,
|
|
155
|
+
` * @param opts - Optional \`redact\` hook applied to the row before persist`,
|
|
156
|
+
` * (scrub PII/secrets on the typed path, same as the generic`,
|
|
157
|
+
` * recordLlmCall/callLlm helpers).`,
|
|
158
|
+
` */`,
|
|
159
|
+
`export async function ${fnName}(`,
|
|
160
|
+
` om: ObjectManager,`,
|
|
161
|
+
` responseMo: MetaObject,`,
|
|
162
|
+
` input: Omit<LlmCallInput, ${recordInputOmit}> & { llmRequest: ${requestType} },`,
|
|
163
|
+
` opts?: { redact?: (row: LlmCallRow) => LlmCallRow },`,
|
|
164
|
+
`): Promise<${entityName}TraceResult> {`,
|
|
165
|
+
` const schema = extractSchemaFor(responseMo, ${formatLiteral});`,
|
|
166
|
+
` const outcome = extract(input.llmResponseText, schema);`,
|
|
167
|
+
` const failed = outcome.report.hasLostRequired();`,
|
|
168
|
+
` const status = failed ? ("error" as const) : ("ok" as const);`,
|
|
169
|
+
' const errorDetail = failed ? `lost required: ${outcome.report.lostRequired().join(", ")}` : null;',
|
|
170
|
+
` const base = buildLlmCallRow(${recordBuildArg});`,
|
|
171
|
+
` const row = { ...base, voRequest: input.llmRequest, voResponse: failed ? null : outcome.data };`,
|
|
172
|
+
` await persistLlmCallRow(new LlmCallDbRecorder(om, "${entityName}"), row, opts?.redact ? { redact: opts.redact } : undefined);`,
|
|
173
|
+
` return { status, errorDetail, voResponse: failed ? null : (outcome.data as ${responseRef}) };`,
|
|
174
|
+
`}`,
|
|
175
|
+
``,
|
|
176
|
+
];
|
|
177
|
+
if (renderable) {
|
|
178
|
+
const callFn = `call${pascal(entityName)}`;
|
|
179
|
+
lines.push(``, `// ---- Call helper (GENERATE -> CALL -> record) -------------------------------`, ``, `export interface ${entityName}CallDeps {`, ` om: ObjectManager;`, ` responseMo: MetaObject;`, ` client: LlmClient;`, ` /** Prompt-TEXT resolver for render() (NOT the LLM client). */`, ` provider: Provider;`, ` model: string;`, ` system?: string;`, ` params?: Record<string, unknown>;`, ` cost?: CostFn;`, ` clock?: Clock;`, ` ids?: IdGen;`, ` traceId?: string;`, ` parentSpanId?: string;`, ` sessionId?: string;`, ` /** Optional row-redaction hook applied before persist (scrub PII/secrets). */`, ` redact?: (row: LlmCallRow) => LlmCallRow;`, `}`, ``, `/**`, ` * Render the ${entityName} prompt, call the LLM, then parse + persist a trace`, ` * row (finally-style: a call/parse failure still writes a row).`, ` */`, `export async function ${callFn}(`, ` payload: ${requestType},`, ` deps: ${entityName}CallDeps,`, `): Promise<${entityName}TraceResult> {`, ` const prompt = render({ ref: ${JSON.stringify(textRef)}, payload, format: ${JSON.stringify(renderFormat)}, provider: deps.provider });`,
|
|
180
|
+
// Build request/input/deps conditionally so that an absent optional (T |
|
|
181
|
+
// undefined) is never assigned to an optional T? property — required for
|
|
182
|
+
// exactOptionalPropertyTypes-strict consumer projects.
|
|
183
|
+
` const request: LlmRequest = { prompt, model: deps.model };`, ` if (deps.system !== undefined) request.system = deps.system;`, ` if (deps.params !== undefined) request.params = deps.params;`, ` const runInput: RunLlmCallInput = { callType: ${JSON.stringify(callTypeValue)}, request };`, ` if (deps.traceId !== undefined) runInput.traceId = deps.traceId;`, ` if (deps.parentSpanId !== undefined) runInput.parentSpanId = deps.parentSpanId;`, ` if (deps.sessionId !== undefined) runInput.sessionId = deps.sessionId;`, ` const runDeps: RunLlmCallDeps = { client: deps.client };`, ` if (deps.cost !== undefined) runDeps.cost = deps.cost;`, ` if (deps.clock !== undefined) runDeps.clock = deps.clock;`, ` if (deps.ids !== undefined) runDeps.ids = deps.ids;`, ` const { input: recInput, completion } = await runLlmCall(runInput, runDeps);`, ` let voResponse: ${responseRef} | null = null;`, ` let status = recInput.status;`, ` let errorDetail = recInput.errorDetail;`, ` if (completion !== undefined) {`, ` const outcome = extract(completion.body, extractSchemaFor(deps.responseMo, ${formatLiteral}));`, ` if (outcome.report.hasLostRequired()) {`, ` status = "error";`, ' errorDetail = `lost required: ${outcome.report.lostRequired().join(", ")}`;', ` } else {`, ` voResponse = outcome.data as ${responseRef};`, ` }`, ` }`, ` const row = { ...buildLlmCallRow({ ...recInput, status, errorDetail }), voRequest: payload, voResponse };`, ` await persistLlmCallRow(new LlmCallDbRecorder(deps.om, ${JSON.stringify(entityName)}), row, deps.redact ? { redact: deps.redact } : undefined);`, ` return { status, errorDetail, voResponse };`, `}`);
|
|
184
|
+
}
|
|
185
|
+
return [{
|
|
186
|
+
path: `${dirPrefix}${entityName}.trace.ts`,
|
|
187
|
+
content: lines.join("\n"),
|
|
188
|
+
}];
|
|
189
|
+
}),
|
|
190
|
+
};
|
|
191
|
+
if (opts?.target) {
|
|
192
|
+
generator.target = opts.target;
|
|
193
|
+
}
|
|
194
|
+
return generator;
|
|
195
|
+
};
|
|
196
|
+
//# sourceMappingURL=trace-helper-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace-helper-file.js","sourceRoot":"","sources":["../../src/generators/trace-helper-file.ts"],"names":[],"mappings":"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"}
|