@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.
Files changed (323) hide show
  1. package/README.md +1 -1
  2. package/dist/column-mapper.d.ts.map +1 -1
  3. package/dist/column-mapper.js +24 -8
  4. package/dist/column-mapper.js.map +1 -1
  5. package/dist/constants.d.ts +8 -0
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/constants.js +16 -0
  8. package/dist/constants.js.map +1 -1
  9. package/dist/docs-paths.d.ts +58 -0
  10. package/dist/docs-paths.d.ts.map +1 -0
  11. package/dist/docs-paths.js +89 -0
  12. package/dist/docs-paths.js.map +1 -0
  13. package/dist/enum-import.d.ts +14 -0
  14. package/dist/enum-import.d.ts.map +1 -0
  15. package/dist/enum-import.js +35 -0
  16. package/dist/enum-import.js.map +1 -0
  17. package/dist/enum-shared.d.ts +32 -0
  18. package/dist/enum-shared.d.ts.map +1 -0
  19. package/dist/enum-shared.js +83 -0
  20. package/dist/enum-shared.js.map +1 -0
  21. package/dist/generator-registry.d.ts +22 -0
  22. package/dist/generator-registry.d.ts.map +1 -0
  23. package/dist/generator-registry.js +161 -0
  24. package/dist/generator-registry.js.map +1 -0
  25. package/dist/generator.d.ts +6 -0
  26. package/dist/generator.d.ts.map +1 -1
  27. package/dist/generator.js.map +1 -1
  28. package/dist/generators/api-doc-render.d.ts +17 -0
  29. package/dist/generators/api-doc-render.d.ts.map +1 -0
  30. package/dist/generators/api-doc-render.js +431 -0
  31. package/dist/generators/api-doc-render.js.map +1 -0
  32. package/dist/generators/api-docs-file.d.ts +21 -0
  33. package/dist/generators/api-docs-file.d.ts.map +1 -0
  34. package/dist/generators/api-docs-file.js +112 -0
  35. package/dist/generators/api-docs-file.js.map +1 -0
  36. package/dist/generators/api-field-shape.d.ts +39 -0
  37. package/dist/generators/api-field-shape.d.ts.map +1 -0
  38. package/dist/generators/api-field-shape.js +92 -0
  39. package/dist/generators/api-field-shape.js.map +1 -0
  40. package/dist/generators/api-label.d.ts +3 -0
  41. package/dist/generators/api-label.d.ts.map +1 -0
  42. package/dist/generators/api-label.js +8 -0
  43. package/dist/generators/api-label.js.map +1 -0
  44. package/dist/generators/api-model.d.ts +122 -0
  45. package/dist/generators/api-model.d.ts.map +1 -0
  46. package/dist/generators/api-model.js +809 -0
  47. package/dist/generators/api-model.js.map +1 -0
  48. package/dist/generators/docs-data-builder.d.ts +26 -4
  49. package/dist/generators/docs-data-builder.d.ts.map +1 -1
  50. package/dist/generators/docs-data-builder.js +436 -164
  51. package/dist/generators/docs-data-builder.js.map +1 -1
  52. package/dist/generators/docs-data.d.ts +136 -27
  53. package/dist/generators/docs-data.d.ts.map +1 -1
  54. package/dist/generators/docs-data.js +1 -1
  55. package/dist/generators/docs-data.js.map +1 -1
  56. package/dist/generators/docs-file.d.ts +19 -0
  57. package/dist/generators/docs-file.d.ts.map +1 -1
  58. package/dist/generators/docs-file.js +154 -27
  59. package/dist/generators/docs-file.js.map +1 -1
  60. package/dist/generators/entity-file.d.ts.map +1 -1
  61. package/dist/generators/entity-file.js +29 -14
  62. package/dist/generators/entity-file.js.map +1 -1
  63. package/dist/generators/extractor-file.d.ts.map +1 -1
  64. package/dist/generators/extractor-file.js +2 -1
  65. package/dist/generators/extractor-file.js.map +1 -1
  66. package/dist/generators/field-anchor.d.ts +7 -0
  67. package/dist/generators/field-anchor.d.ts.map +1 -0
  68. package/dist/generators/field-anchor.js +23 -0
  69. package/dist/generators/field-anchor.js.map +1 -0
  70. package/dist/generators/index.d.ts +8 -1
  71. package/dist/generators/index.d.ts.map +1 -1
  72. package/dist/generators/index.js +6 -0
  73. package/dist/generators/index.js.map +1 -1
  74. package/dist/generators/mermaid-er.d.ts +14 -0
  75. package/dist/generators/mermaid-er.d.ts.map +1 -1
  76. package/dist/generators/mermaid-er.js +14 -0
  77. package/dist/generators/mermaid-er.js.map +1 -1
  78. package/dist/generators/output-parser-file.d.ts.map +1 -1
  79. package/dist/generators/output-parser-file.js +3 -4
  80. package/dist/generators/output-parser-file.js.map +1 -1
  81. package/dist/generators/output-prompt-file.d.ts.map +1 -1
  82. package/dist/generators/output-prompt-file.js +2 -2
  83. package/dist/generators/output-prompt-file.js.map +1 -1
  84. package/dist/generators/prompt-render-file.d.ts.map +1 -1
  85. package/dist/generators/prompt-render-file.js +3 -4
  86. package/dist/generators/prompt-render-file.js.map +1 -1
  87. package/dist/generators/queries-file.d.ts.map +1 -1
  88. package/dist/generators/queries-file.js +8 -3
  89. package/dist/generators/queries-file.js.map +1 -1
  90. package/dist/generators/render-helper-file.d.ts.map +1 -1
  91. package/dist/generators/render-helper-file.js +2 -2
  92. package/dist/generators/render-helper-file.js.map +1 -1
  93. package/dist/generators/routes-file-hono.d.ts.map +1 -1
  94. package/dist/generators/routes-file-hono.js +5 -1
  95. package/dist/generators/routes-file-hono.js.map +1 -1
  96. package/dist/generators/routes-file.d.ts +3 -0
  97. package/dist/generators/routes-file.d.ts.map +1 -1
  98. package/dist/generators/routes-file.js +6 -1
  99. package/dist/generators/routes-file.js.map +1 -1
  100. package/dist/generators/template-doc-builder.d.ts +19 -0
  101. package/dist/generators/template-doc-builder.d.ts.map +1 -0
  102. package/dist/generators/template-doc-builder.js +220 -0
  103. package/dist/generators/template-doc-builder.js.map +1 -0
  104. package/dist/generators/template-doc-data.d.ts +62 -0
  105. package/dist/generators/template-doc-data.d.ts.map +1 -0
  106. package/dist/generators/template-doc-data.js +16 -0
  107. package/dist/generators/template-doc-data.js.map +1 -0
  108. package/dist/generators/template-payload-tree.d.ts +15 -0
  109. package/dist/generators/template-payload-tree.d.ts.map +1 -0
  110. package/dist/generators/template-payload-tree.js +61 -0
  111. package/dist/generators/template-payload-tree.js.map +1 -0
  112. package/dist/generators/template-source-annotate.d.ts +74 -0
  113. package/dist/generators/template-source-annotate.d.ts.map +1 -0
  114. package/dist/generators/template-source-annotate.js +184 -0
  115. package/dist/generators/template-source-annotate.js.map +1 -0
  116. package/dist/generators/template-source-render.d.ts +24 -0
  117. package/dist/generators/template-source-render.d.ts.map +1 -0
  118. package/dist/generators/template-source-render.js +175 -0
  119. package/dist/generators/template-source-render.js.map +1 -0
  120. package/dist/generators/trace-helper-file.d.ts +9 -0
  121. package/dist/generators/trace-helper-file.d.ts.map +1 -0
  122. package/dist/generators/trace-helper-file.js +196 -0
  123. package/dist/generators/trace-helper-file.js.map +1 -0
  124. package/dist/index.d.ts +29 -4
  125. package/dist/index.d.ts.map +1 -1
  126. package/dist/index.js +28 -2
  127. package/dist/index.js.map +1 -1
  128. package/dist/metaobjects-config.d.ts +75 -2
  129. package/dist/metaobjects-config.d.ts.map +1 -1
  130. package/dist/metaobjects-config.js +43 -0
  131. package/dist/metaobjects-config.js.map +1 -1
  132. package/dist/naming.d.ts +19 -0
  133. package/dist/naming.d.ts.map +1 -1
  134. package/dist/naming.js +41 -0
  135. package/dist/naming.js.map +1 -1
  136. package/dist/payload-codegen.d.ts.map +1 -1
  137. package/dist/payload-codegen.js +12 -4
  138. package/dist/payload-codegen.js.map +1 -1
  139. package/dist/projection/extract-view-spec.d.ts.map +1 -1
  140. package/dist/projection/extract-view-spec.js +51 -25
  141. package/dist/projection/extract-view-spec.js.map +1 -1
  142. package/dist/relation-resolver.d.ts +16 -0
  143. package/dist/relation-resolver.d.ts.map +1 -1
  144. package/dist/relation-resolver.js +82 -1
  145. package/dist/relation-resolver.js.map +1 -1
  146. package/dist/render-context.d.ts +4 -0
  147. package/dist/render-context.d.ts.map +1 -1
  148. package/dist/render-context.js.map +1 -1
  149. package/dist/render-engine/embedded-templates.generated.d.ts +2 -0
  150. package/dist/render-engine/embedded-templates.generated.d.ts.map +1 -0
  151. package/dist/render-engine/embedded-templates.generated.js +15 -0
  152. package/dist/render-engine/embedded-templates.generated.js.map +1 -0
  153. package/dist/render-engine/framework-provider.d.ts.map +1 -1
  154. package/dist/render-engine/framework-provider.js +26 -13
  155. package/dist/render-engine/framework-provider.js.map +1 -1
  156. package/dist/runner.d.ts.map +1 -1
  157. package/dist/runner.js +17 -0
  158. package/dist/runner.js.map +1 -1
  159. package/dist/templates/docs-file.d.ts +2 -6
  160. package/dist/templates/docs-file.d.ts.map +1 -1
  161. package/dist/templates/docs-file.js +2 -5
  162. package/dist/templates/docs-file.js.map +1 -1
  163. package/dist/templates/drizzle-schema.d.ts.map +1 -1
  164. package/dist/templates/drizzle-schema.js +30 -2
  165. package/dist/templates/drizzle-schema.js.map +1 -1
  166. package/dist/templates/entity-constants.d.ts +7 -0
  167. package/dist/templates/entity-constants.d.ts.map +1 -1
  168. package/dist/templates/entity-constants.js +1 -1
  169. package/dist/templates/entity-constants.js.map +1 -1
  170. package/dist/templates/entity-file.d.ts.map +1 -1
  171. package/dist/templates/entity-file.js +16 -5
  172. package/dist/templates/entity-file.js.map +1 -1
  173. package/dist/templates/enums-file.d.ts +11 -0
  174. package/dist/templates/enums-file.d.ts.map +1 -0
  175. package/dist/templates/enums-file.js +44 -0
  176. package/dist/templates/enums-file.js.map +1 -0
  177. package/dist/templates/extract-delegate-emitter.d.ts.map +1 -1
  178. package/dist/templates/extract-delegate-emitter.js +5 -7
  179. package/dist/templates/extract-delegate-emitter.js.map +1 -1
  180. package/dist/templates/extract-schema-emitter.d.ts.map +1 -1
  181. package/dist/templates/extract-schema-emitter.js +5 -1
  182. package/dist/templates/extract-schema-emitter.js.map +1 -1
  183. package/dist/templates/extractor.d.ts.map +1 -1
  184. package/dist/templates/extractor.js +56 -39
  185. package/dist/templates/extractor.js.map +1 -1
  186. package/dist/templates/field-meta.d.ts.map +1 -1
  187. package/dist/templates/field-meta.js +1 -5
  188. package/dist/templates/field-meta.js.map +1 -1
  189. package/dist/templates/filter-allowlist.d.ts +7 -2
  190. package/dist/templates/filter-allowlist.d.ts.map +1 -1
  191. package/dist/templates/filter-allowlist.js +17 -9
  192. package/dist/templates/filter-allowlist.js.map +1 -1
  193. package/dist/templates/filter-type.d.ts +7 -1
  194. package/dist/templates/filter-type.d.ts.map +1 -1
  195. package/dist/templates/filter-type.js +9 -5
  196. package/dist/templates/filter-type.js.map +1 -1
  197. package/dist/templates/find-templates.d.ts +4 -0
  198. package/dist/templates/find-templates.d.ts.map +1 -0
  199. package/dist/templates/find-templates.js +15 -0
  200. package/dist/templates/find-templates.js.map +1 -0
  201. package/dist/templates/fr010-field-mapping.d.ts +2 -0
  202. package/dist/templates/fr010-field-mapping.d.ts.map +1 -1
  203. package/dist/templates/fr010-field-mapping.js +10 -6
  204. package/dist/templates/fr010-field-mapping.js.map +1 -1
  205. package/dist/templates/inferred-types.d.ts +44 -7
  206. package/dist/templates/inferred-types.d.ts.map +1 -1
  207. package/dist/templates/inferred-types.js +107 -16
  208. package/dist/templates/inferred-types.js.map +1 -1
  209. package/dist/templates/mermaid-er.d.ts +35 -2
  210. package/dist/templates/mermaid-er.d.ts.map +1 -1
  211. package/dist/templates/mermaid-er.js +174 -7
  212. package/dist/templates/mermaid-er.js.map +1 -1
  213. package/dist/templates/output-parser.d.ts.map +1 -1
  214. package/dist/templates/output-parser.js +30 -79
  215. package/dist/templates/output-parser.js.map +1 -1
  216. package/dist/templates/output-prompt.d.ts.map +1 -1
  217. package/dist/templates/output-prompt.js +2 -2
  218. package/dist/templates/output-prompt.js.map +1 -1
  219. package/dist/templates/queries-file.d.ts.map +1 -1
  220. package/dist/templates/queries-file.js +112 -4
  221. package/dist/templates/queries-file.js.map +1 -1
  222. package/dist/templates/queries.d.ts +5 -0
  223. package/dist/templates/queries.d.ts.map +1 -1
  224. package/dist/templates/queries.js +7 -7
  225. package/dist/templates/queries.js.map +1 -1
  226. package/dist/templates/recover-schema-emitter.d.ts +8 -0
  227. package/dist/templates/recover-schema-emitter.d.ts.map +1 -0
  228. package/dist/templates/recover-schema-emitter.js +64 -0
  229. package/dist/templates/recover-schema-emitter.js.map +1 -0
  230. package/dist/templates/relations-block.js +10 -0
  231. package/dist/templates/relations-block.js.map +1 -1
  232. package/dist/templates/render-helper.d.ts.map +1 -1
  233. package/dist/templates/render-helper.js +4 -4
  234. package/dist/templates/render-helper.js.map +1 -1
  235. package/dist/templates/routes-file.d.ts.map +1 -1
  236. package/dist/templates/routes-file.js +183 -6
  237. package/dist/templates/routes-file.js.map +1 -1
  238. package/dist/templates/tph-discriminator.d.ts +56 -0
  239. package/dist/templates/tph-discriminator.d.ts.map +1 -0
  240. package/dist/templates/tph-discriminator.js +180 -0
  241. package/dist/templates/tph-discriminator.js.map +1 -0
  242. package/dist/templates/value-object-file.d.ts +2 -1
  243. package/dist/templates/value-object-file.d.ts.map +1 -1
  244. package/dist/templates/value-object-file.js +32 -4
  245. package/dist/templates/value-object-file.js.map +1 -1
  246. package/dist/templates/zod-validators.d.ts +64 -1
  247. package/dist/templates/zod-validators.d.ts.map +1 -1
  248. package/dist/templates/zod-validators.js +181 -8
  249. package/dist/templates/zod-validators.js.map +1 -1
  250. package/package.json +103 -34
  251. package/src/column-mapper.ts +25 -8
  252. package/src/constants.ts +18 -0
  253. package/src/docs-paths.ts +128 -0
  254. package/src/enum-import.ts +43 -0
  255. package/src/enum-shared.ts +95 -0
  256. package/src/generator-registry.ts +204 -0
  257. package/src/generator.ts +6 -0
  258. package/src/generators/api-doc-render.ts +572 -0
  259. package/src/generators/api-docs-file.ts +146 -0
  260. package/src/generators/api-field-shape.ts +114 -0
  261. package/src/generators/api-label.ts +7 -0
  262. package/src/generators/api-model.ts +1067 -0
  263. package/src/generators/docs-data-builder.ts +479 -185
  264. package/src/generators/docs-data.ts +139 -28
  265. package/src/generators/docs-file.ts +205 -39
  266. package/src/generators/entity-file.ts +31 -15
  267. package/src/generators/extractor-file.ts +2 -1
  268. package/src/generators/field-anchor.ts +24 -0
  269. package/src/generators/index.ts +8 -1
  270. package/src/generators/mermaid-er.ts +14 -0
  271. package/src/generators/output-parser-file.ts +3 -4
  272. package/src/generators/output-prompt-file.ts +2 -1
  273. package/src/generators/prompt-render-file.ts +3 -4
  274. package/src/generators/queries-file.ts +9 -3
  275. package/src/generators/render-helper-file.ts +2 -1
  276. package/src/generators/routes-file-hono.ts +5 -1
  277. package/src/generators/routes-file.ts +7 -1
  278. package/src/generators/template-doc-builder.ts +306 -0
  279. package/src/generators/template-doc-data.ts +85 -0
  280. package/src/generators/template-payload-tree.ts +71 -0
  281. package/src/generators/template-source-annotate.ts +290 -0
  282. package/src/generators/template-source-render.ts +203 -0
  283. package/src/generators/trace-helper-file.ts +301 -0
  284. package/src/index.ts +55 -4
  285. package/src/metaobjects-config.ts +117 -2
  286. package/src/naming.ts +48 -0
  287. package/src/payload-codegen.ts +14 -3
  288. package/src/projection/extract-view-spec.ts +49 -30
  289. package/src/relation-resolver.ts +103 -1
  290. package/src/render-context.ts +4 -0
  291. package/src/render-engine/embedded-templates.generated.ts +14 -0
  292. package/src/render-engine/framework-provider.ts +25 -11
  293. package/src/runner.ts +21 -0
  294. package/src/templates/docs-file.ts +2 -9
  295. package/src/templates/drizzle-schema.ts +31 -1
  296. package/src/templates/entity-constants.ts +1 -1
  297. package/src/templates/entity-file.ts +16 -5
  298. package/src/templates/enums-file.ts +50 -0
  299. package/src/templates/extract-delegate-emitter.ts +5 -6
  300. package/src/templates/extractor.ts +68 -38
  301. package/src/templates/field-meta.ts +0 -6
  302. package/src/templates/filter-allowlist.ts +17 -10
  303. package/src/templates/filter-type.ts +8 -6
  304. package/src/templates/find-templates.ts +15 -0
  305. package/src/templates/fr010-field-mapping.ts +10 -8
  306. package/src/templates/inferred-types.ts +108 -18
  307. package/src/templates/mermaid-er.ts +176 -8
  308. package/src/templates/output-parser.ts +30 -79
  309. package/src/templates/output-prompt.ts +2 -1
  310. package/src/templates/queries-file.ts +132 -3
  311. package/src/templates/queries.ts +15 -7
  312. package/src/templates/relations-block.ts +17 -0
  313. package/src/templates/render-helper.ts +4 -3
  314. package/src/templates/routes-file.ts +233 -6
  315. package/src/templates/tph-discriminator.ts +232 -0
  316. package/src/templates/value-object-file.ts +38 -4
  317. package/src/templates/zod-validators.ts +204 -7
  318. package/templates/api/agent-api.md.mustache +30 -0
  319. package/templates/api/entity-api.md.mustache +69 -0
  320. package/templates/api/index.md.mustache +21 -0
  321. package/templates/docs/entity-page.md.mustache +33 -21
  322. package/templates/docs/template-page.md.mustache +56 -0
  323. package/src/templates/extract-schema-emitter.ts +0 -111
@@ -0,0 +1,220 @@
1
+ // Walk one `template.output` node (+ root) into the NEUTRAL TemplateDocData
2
+ // shape the `docs/template-page.md` Mustache template consumes. The attr reads
3
+ // MIRROR render-helper-file.ts / templates/render-helper.ts (@kind, @payloadRef,
4
+ // @textRef, @format, @maxChars, @requiredTags; for email @subjectRef /
5
+ // @htmlBodyRef / @textBodyRef) — but this builder emits DESCRIPTION, never code:
6
+ // no helper signatures, no language types. `capability` is a FIXED, neutral
7
+ // sentence per @kind.
8
+ import { TEMPLATE_ATTR_PAYLOAD_REF, TEMPLATE_ATTR_TEXT_REF, TEMPLATE_ATTR_FORMAT, TEMPLATE_ATTR_MAX_CHARS, TEMPLATE_ATTR_KIND, TEMPLATE_KIND_EMAIL, TEMPLATE_KIND_DOCUMENT, TEMPLATE_KIND_DEFAULT, TEMPLATE_ATTR_SUBJECT_REF, TEMPLATE_ATTR_HTML_BODY_REF, TEMPLATE_ATTR_TEXT_BODY_REF, TEMPLATE_ATTR_REQUIRED_TAGS, DOC_ATTR_DESCRIPTION, stripPackage, } from "@metaobjectsdev/metadata";
9
+ import { TYPE_TEMPLATE, TEMPLATE_SUBTYPE_OUTPUT, } from "@metaobjectsdev/metadata";
10
+ import { GENERATED_HEADER } from "../constants.js";
11
+ import { docPageHref, docPageNode } from "../docs-paths.js";
12
+ import { fieldAnchorSlug } from "./field-anchor.js";
13
+ import { buildEnrichedPayloadTree } from "./template-payload-tree.js";
14
+ import { annotateTemplate } from "./template-source-annotate.js";
15
+ import { renderSourceBlock, renderVariablesTable, renderRichLinkedHtml, } from "./template-source-render.js";
16
+ // FIXED, language-NEUTRAL capability sentences. NO type names, NO signatures.
17
+ const CAPABILITY_DOCUMENT = "A render helper is generated for this template: it takes the payload and " +
18
+ "returns the rendered output as a single string.";
19
+ const CAPABILITY_EMAIL = "A render helper is generated for this template: it takes the payload and " +
20
+ "returns the rendered email — subject, HTML body, and an optional text body.";
21
+ /** Read an attr that may be a string or string[] (string-array attrs come back
22
+ * as string[]; a bare comma string is split defensively). Returns a trimmed,
23
+ * non-empty string list. */
24
+ function attrStringList(value) {
25
+ if (Array.isArray(value)) {
26
+ return value.filter((v) => typeof v === "string" && v.length > 0);
27
+ }
28
+ if (typeof value === "string" && value.trim() !== "") {
29
+ return value.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
30
+ }
31
+ return [];
32
+ }
33
+ function readMaxChars(value) {
34
+ if (typeof value === "number" && Number.isFinite(value))
35
+ return value;
36
+ if (typeof value === "string" && value.trim() !== "") {
37
+ const n = Number(value);
38
+ if (Number.isFinite(n))
39
+ return n;
40
+ }
41
+ return undefined;
42
+ }
43
+ function templateDescription(t) {
44
+ const v = t.attr(DOC_ATTR_DESCRIPTION);
45
+ return typeof v === "string" && v.length > 0 ? v : undefined;
46
+ }
47
+ /** Page-placement node for a metadata object resolved by short name, with the
48
+ * SAME package-less fallback the Payload cross-link and field hrefs share: when
49
+ * the object can't be resolved off the root, fall back to a root-level node so a
50
+ * link is still emitted. Keeps every inbound href routing through the one
51
+ * `docPageHref(layout, …)` placement. */
52
+ function pageNodeByName(root, name) {
53
+ const obj = root?.findObject(name);
54
+ return obj !== undefined ? docPageNode(obj) : { name };
55
+ }
56
+ /** Build the TemplateDocData for one `template.output` node. */
57
+ export function buildTemplateDocData(template, opts) {
58
+ const layout = opts?.layout ?? "flat";
59
+ const root = opts?.loadedRoot;
60
+ const kindRaw = (template.ownAttr(TEMPLATE_ATTR_KIND) ??
61
+ TEMPLATE_KIND_DEFAULT).toLowerCase();
62
+ const isEmail = kindRaw === TEMPLATE_KIND_EMAIL;
63
+ const kind = isEmail ? TEMPLATE_KIND_EMAIL : TEMPLATE_KIND_DOCUMENT;
64
+ const payloadRefRaw = template.ownAttr(TEMPLATE_ATTR_PAYLOAD_REF);
65
+ const payloadName = typeof payloadRefRaw === "string" && payloadRefRaw.length > 0
66
+ ? stripPackage(payloadRefRaw)
67
+ : "unknown";
68
+ const requiredTags = attrStringList(template.ownAttr(TEMPLATE_ATTR_REQUIRED_TAGS));
69
+ const maxChars = readMaxChars(template.ownAttr(TEMPLATE_ATTR_MAX_CHARS));
70
+ let format = "";
71
+ let parts;
72
+ const sourceRefs = [];
73
+ if (isEmail) {
74
+ const subjectRef = template.ownAttr(TEMPLATE_ATTR_SUBJECT_REF);
75
+ const htmlBodyRef = template.ownAttr(TEMPLATE_ATTR_HTML_BODY_REF);
76
+ const textBodyRef = template.ownAttr(TEMPLATE_ATTR_TEXT_BODY_REF);
77
+ parts = [];
78
+ if (typeof subjectRef === "string") {
79
+ parts.push({ label: "Subject", ref: subjectRef, format: "text", escaped: false });
80
+ sourceRefs.push(subjectRef);
81
+ }
82
+ if (typeof htmlBodyRef === "string") {
83
+ parts.push({ label: "HTML body", ref: htmlBodyRef, format: "html", escaped: true });
84
+ sourceRefs.push(htmlBodyRef);
85
+ }
86
+ if (typeof textBodyRef === "string") {
87
+ parts.push({ label: "Text body", ref: textBodyRef, format: "text", escaped: false });
88
+ sourceRefs.push(textBodyRef);
89
+ }
90
+ }
91
+ else {
92
+ format = (template.ownAttr(TEMPLATE_ATTR_FORMAT) ?? "text").toLowerCase();
93
+ const textRef = template.ownAttr(TEMPLATE_ATTR_TEXT_REF);
94
+ if (typeof textRef === "string")
95
+ sourceRefs.push(textRef);
96
+ }
97
+ // Cross-link to the payload entity's page. The href is derived from the SAME
98
+ // page-placement function used to write that entity page, so it resolves in
99
+ // BOTH layouts (package layout folds the correct relative path).
100
+ const payloadLink = docPageHref(layout, docPageNode(template), pageNodeByName(root, payloadName));
101
+ const data = {
102
+ generatedMarker: `<!-- ${GENERATED_HEADER} — DO NOT EDIT. -->`,
103
+ name: template.name,
104
+ kind,
105
+ isEmail,
106
+ format,
107
+ payload: { name: payloadName, link: payloadLink },
108
+ sourceRefs,
109
+ capability: isEmail ? CAPABILITY_EMAIL : CAPABILITY_DOCUMENT,
110
+ };
111
+ if (parts !== undefined)
112
+ data.parts = parts;
113
+ if (requiredTags.length > 0) {
114
+ data.requiredTags = requiredTags;
115
+ data.hasRequiredTags = true;
116
+ }
117
+ if (maxChars !== undefined)
118
+ data.maxChars = maxChars;
119
+ // ── "## Template source" section (Task 4) ────────────────────────────────
120
+ // Resolve each referenced mustache's SOURCE TEXT via the page provider, then
121
+ // annotate it against the ENRICHED payload tree (owner/type/required per node)
122
+ // and pre-render the three doc forms. Only when a provider + a resolvable
123
+ // payload VO are available; a ref that doesn't resolve is skipped (no crash).
124
+ if (opts?.provider !== undefined && root !== undefined && payloadName !== "unknown") {
125
+ const section = buildTemplateSourceSection({
126
+ provider: opts.provider,
127
+ root,
128
+ layout,
129
+ template,
130
+ payloadName,
131
+ // Document: the single @textRef (unlabeled). Email: one labeled part each.
132
+ refs: parts !== undefined
133
+ ? parts.map((p) => ({ label: p.label, ref: p.ref }))
134
+ : sourceRefs.map((ref) => ({ ref })),
135
+ });
136
+ if (section !== undefined)
137
+ data.templateSourceSection = section;
138
+ }
139
+ const desc = templateDescription(template);
140
+ if (desc !== undefined) {
141
+ data.descriptionQuote = desc.split("\n").map((l) => `> ${l}`.trimEnd()).join("\n");
142
+ }
143
+ return data;
144
+ }
145
+ /**
146
+ * Build the PRE-RENDERED "## Template source" section markdown. For each ref:
147
+ * resolve its mustache source via the provider, annotate it against the enriched
148
+ * payload tree, and emit the fenced source block + the linked variables table +
149
+ * the rich `<details>` linked view. A document template yields one block; an
150
+ * email yields one `### <label>` sub-section per part. Refs whose source the
151
+ * provider can't resolve are skipped (graceful — the build-time drift gate
152
+ * already errors on a truly unresolved ref). Returns `undefined` when NOTHING
153
+ * resolved, so the caller omits the section entirely.
154
+ */
155
+ function buildTemplateSourceSection(args) {
156
+ const { provider, root, layout, template, payloadName, refs } = args;
157
+ const tree = buildEnrichedPayloadTree(root, payloadName);
158
+ const fromNode = docPageNode(template);
159
+ // Layout-aware field href: route through the SAME docPageHref the Payload
160
+ // cross-link uses, so the link lands on the owner VO's REAL page in BOTH
161
+ // layouts (flat → `./Owner.md`, package → `../<pkg>/Owner.md`).
162
+ const fieldHref = (owner, name) => `${docPageHref(layout, fromNode, pageNodeByName(root, owner))}#${fieldAnchorSlug(name)}`;
163
+ const resolvePartialHref = makePartialHrefResolver(root, layout, fromNode);
164
+ const isMultipart = refs.length > 1 || refs.some((r) => r.label !== undefined);
165
+ const blocks = [];
166
+ for (const spec of refs) {
167
+ const source = provider.resolve(spec.ref);
168
+ if (source === undefined)
169
+ continue; // missing source → skip this part.
170
+ const tokens = annotateTemplate(source, tree, {
171
+ ownerVoName: payloadName,
172
+ resolvePartialHref,
173
+ fieldHref,
174
+ });
175
+ const parts = [];
176
+ if (isMultipart && spec.label !== undefined)
177
+ parts.push(`### ${spec.label}`);
178
+ parts.push(renderSourceBlock(tokens));
179
+ const table = renderVariablesTable(tokens);
180
+ if (table !== "")
181
+ parts.push(table);
182
+ parts.push(renderRichLinkedHtml(tokens));
183
+ blocks.push(parts.join("\n\n"));
184
+ }
185
+ if (blocks.length === 0)
186
+ return undefined;
187
+ return ["## Template source", "", blocks.join("\n\n")].join("\n");
188
+ }
189
+ /**
190
+ * A `{{>ref}}` partial-href resolver: returns a relative href to the page of the
191
+ * `template.output` node that documents `ref` (it is one of that template's
192
+ * source refs — @textRef or an email part ref), else undefined (the partial is
193
+ * highlight-only). The href routes through the SAME `docPageHref(layout, …)` the
194
+ * field/Payload links use, so it resolves in BOTH layouts (flat → `./Name.md`,
195
+ * package → a correct relative path like `../comms/OrderEmail.md`).
196
+ */
197
+ function makePartialHrefResolver(root, layout, fromNode) {
198
+ // Map each documented source ref → the template node that documents it.
199
+ const refToTemplate = new Map();
200
+ for (const child of root.ownChildren()) {
201
+ if (child.type !== TYPE_TEMPLATE || child.subType !== TEMPLATE_SUBTYPE_OUTPUT)
202
+ continue;
203
+ for (const attr of [
204
+ TEMPLATE_ATTR_TEXT_REF,
205
+ TEMPLATE_ATTR_SUBJECT_REF,
206
+ TEMPLATE_ATTR_HTML_BODY_REF,
207
+ TEMPLATE_ATTR_TEXT_BODY_REF,
208
+ ]) {
209
+ const v = child.ownAttr(attr);
210
+ if (typeof v === "string" && v.length > 0 && !refToTemplate.has(v)) {
211
+ refToTemplate.set(v, child);
212
+ }
213
+ }
214
+ }
215
+ return (ref) => {
216
+ const node = refToTemplate.get(ref);
217
+ return node !== undefined ? docPageHref(layout, fromNode, docPageNode(node)) : undefined;
218
+ };
219
+ }
220
+ //# sourceMappingURL=template-doc-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-doc-builder.js","sourceRoot":"","sources":["../../src/generators/template-doc-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /** One part of a multipart (email) template — a single rendered source ref with
2
+ * its format and whether the renderer escapes its output for that format. */
3
+ export interface TemplateOutputPart {
4
+ /** Human-readable part label, e.g. "Subject", "HTML body", "Text body". */
5
+ label: string;
6
+ /** The logical text ref rendered for this part (e.g. "email/welcome.html"). */
7
+ ref: string;
8
+ /** Render format for this part: "text" | "html" (subject/text = text, html = html). */
9
+ format: string;
10
+ /** True iff the renderer escapes output for this part's format (html → true). */
11
+ escaped: boolean;
12
+ }
13
+ export interface TemplateDocData {
14
+ /** @markdown — the generated-by marker, echoed at the top of the page. */
15
+ generatedMarker: string;
16
+ /** Raw template node name — also the emitted filename (`<name>.md`). */
17
+ name: string;
18
+ /** @kind — "document" | "email". */
19
+ kind: "document" | "email";
20
+ /** Convenience flag for the Mustache template (no "is X" primitive). */
21
+ isEmail: boolean;
22
+ /** @markdown — description as a blockquote (one `> ` per line). Present iff
23
+ * the template declares a @description. Mirrors EntityDocData. */
24
+ descriptionQuote?: string;
25
+ /** Document: the @format (e.g. "html"). Email: "" — the parts carry format. */
26
+ format: string;
27
+ /** Email only: the ordered multipart parts (subject, html body, text body?). */
28
+ parts?: TemplateOutputPart[];
29
+ /** The payload object the template renders from. `link` is `./<rawName>.md` —
30
+ * the payload entity's own doc page (raw-name convention, matching the
31
+ * entity-page filename + the entity's Used-by back-link). */
32
+ payload: {
33
+ name: string;
34
+ link: string;
35
+ };
36
+ /** @requiredTags, if declared. Drives both the Input "Required fields" line
37
+ * and the Render-contract "Required tags" bullet. */
38
+ requiredTags?: string[];
39
+ /** Present-and-non-empty flag for @requiredTags (Mustache has no "non-empty
40
+ * array" primitive; same idiom as EntityDocData's `has*` flags). */
41
+ hasRequiredTags?: boolean;
42
+ /** @maxChars, if declared (document only in practice). */
43
+ maxChars?: number;
44
+ /** The template refs this page renders: [@textRef] for a document, or the
45
+ * 2–3 email part refs. Drives the Source section. */
46
+ sourceRefs: string[];
47
+ /** FIXED, language-NEUTRAL capability sentence per @kind. No type names, no
48
+ * function signatures. See template-doc-builder.ts. */
49
+ capability: string;
50
+ /**
51
+ * @markdown — the PRE-RENDERED "## Template source" section body (linked-
52
+ * template-source-docs, Task 4). Present iff at least one referenced mustache
53
+ * resolved to source via the page provider. For a document template it is one
54
+ * block; for an email it is one `### <part>` sub-section per part. Each carries
55
+ * the fenced ```mustache source, a linked variables table, and the rich
56
+ * `<details>` linked view — ALL pre-rendered in the builder (the page template
57
+ * just emits this markdown verbatim, like `descriptionQuote`), so the mustache
58
+ * page never re-parses the embedded `{{field}}` tokens. Absent when no
59
+ * referenced source resolved (the section is omitted, not empty). */
60
+ templateSourceSection?: string;
61
+ }
62
+ //# sourceMappingURL=template-doc-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-doc-data.d.ts","sourceRoot":"","sources":["../../src/generators/template-doc-data.ts"],"names":[],"mappings":"AAeA;8EAC8E;AAC9E,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,GAAG,EAAE,MAAM,CAAC;IACZ,uFAAuF;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,iFAAiF;IACjF,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,eAAe,EAAE,MAAM,CAAC;IAExB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IAEb,oCAAoC;IACpC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;IAC3B,wEAAwE;IACxE,OAAO,EAAE,OAAO,CAAC;IAEjB;uEACmE;IACnE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;IAEf,gFAAgF;IAChF,KAAK,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAE7B;;kEAE8D;IAC9D,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAExC;0DACsD;IACtD,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB;yEACqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAC;IAE1B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;0DACsD;IACtD,UAAU,EAAE,MAAM,EAAE,CAAC;IAErB;4DACwD;IACxD,UAAU,EAAE,MAAM,CAAC;IAEnB;;;;;;;;;yEASqE;IACrE,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC"}
@@ -0,0 +1,16 @@
1
+ // Data-dict shape for the NEUTRAL template.output doc page (the "render
2
+ // contract" page). Sibling of EntityDocData (docs-data.ts) — same public-API
3
+ // stability contract: template authors who write a custom Mustache file for
4
+ // `docs/template-page.md` reference these keys.
5
+ //
6
+ // CRITICAL — NEUTRALITY: this shape carries NO language assumptions. There are
7
+ // no generated-helper signatures, no language type names, no SDK tokens. The
8
+ // `capability` field is a FIXED, language-neutral English sentence per @kind
9
+ // (see template-doc-builder.ts). The page describes the RENDER CONTRACT (what
10
+ // the template references, validates, and produces), not any one port's code.
11
+ //
12
+ // Markdown-flavored, like EntityDocData: a few fields are pre-rendered (the
13
+ // parts table is structural, but escaping / raw-vs-escaped wording lives in the
14
+ // builder so the template stays trivial and cross-port walks don't re-derive it).
15
+ export {};
16
+ //# sourceMappingURL=template-doc-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-doc-data.js","sourceRoot":"","sources":["../../src/generators/template-doc-data.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,6EAA6E;AAC7E,4EAA4E;AAC5E,gDAAgD;AAChD,EAAE;AACF,+EAA+E;AAC/E,6EAA6E;AAC7E,6EAA6E;AAC7E,8EAA8E;AAC9E,8EAA8E;AAC9E,EAAE;AACF,4EAA4E;AAC5E,gFAAgF;AAChF,kFAAkF"}
@@ -0,0 +1,15 @@
1
+ import { type MetaRoot } from "@metaobjectsdev/metadata";
2
+ import type { AnnotatePayloadField } from "./template-source-annotate.js";
3
+ /**
4
+ * Walk the payload VO `voName` into an enriched `AnnotatePayloadField[]`. Each
5
+ * node carries `owner` (the short name of the VO that DECLARES the field — the
6
+ * link target), `type` (the neutral logical type), and `required`. Object-ref
7
+ * fields recurse into their referenced VO with `owner` switched to that nested
8
+ * VO; a `seen` set guards a (pathological) reference cycle (returns `[]` rather
9
+ * than recursing forever).
10
+ *
11
+ * Returns `[]` when the VO can't be resolved — the annotator then leaves the
12
+ * referencing variables unresolved (flagged "not on payload"), never throws.
13
+ */
14
+ export declare function buildEnrichedPayloadTree(root: MetaRoot, voName: string, seen?: ReadonlySet<string>): AnnotatePayloadField[];
15
+ //# sourceMappingURL=template-payload-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-payload-tree.d.ts","sourceRoot":"","sources":["../../src/generators/template-payload-tree.ts"],"names":[],"mappings":"AAoBA,OAAO,EAEL,KAAK,QAAQ,EAId,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAE1E;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,QAAQ,EACd,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,WAAW,CAAC,MAAM,CAAa,GACpC,oBAAoB,EAAE,CAyBxB"}
@@ -0,0 +1,61 @@
1
+ // Enriched payload-field tree for the template-source annotator
2
+ // (linked-template-source-docs, Task 4).
3
+ //
4
+ // The render-helper drift gate walks the payload VO into a bare `PayloadField[]`
5
+ // (name + nested fields) — enough to VERIFY that a `{{field}}` exists. The doc
6
+ // page needs MORE per node: which VO OWNS the field (so the link points at the
7
+ // right entity page), the field's NEUTRAL type, and whether it's required — the
8
+ // exact same facts the entity Constraints table shows.
9
+ //
10
+ // This walk produces that `AnnotatePayloadField[]`. It is the same recursion the
11
+ // render-helper's `derivePayloadFieldTree` does (object-ref fields recurse into
12
+ // their referenced VO; a `seen` set guards a reference cycle) — but it carries
13
+ // owner/type/required and SWITCHES owner to the nested VO when it descends, so a
14
+ // `{{address.city}}` resolves to `Address.city` and links to `./Address.md`.
15
+ //
16
+ // Reuse, not reimplementation:
17
+ // • isFieldRequired / neutralTypeStr — the SAME helpers the entity Constraints
18
+ // table uses, so the documented type/required can never drift from the
19
+ // entity page.
20
+ import { FIELD_SUBTYPE_OBJECT, FIELD_ATTR_OBJECT_REF, stripPackage, } from "@metaobjectsdev/metadata";
21
+ import { isFieldRequired, neutralTypeStr } from "./docs-data-builder.js";
22
+ /**
23
+ * Walk the payload VO `voName` into an enriched `AnnotatePayloadField[]`. Each
24
+ * node carries `owner` (the short name of the VO that DECLARES the field — the
25
+ * link target), `type` (the neutral logical type), and `required`. Object-ref
26
+ * fields recurse into their referenced VO with `owner` switched to that nested
27
+ * VO; a `seen` set guards a (pathological) reference cycle (returns `[]` rather
28
+ * than recursing forever).
29
+ *
30
+ * Returns `[]` when the VO can't be resolved — the annotator then leaves the
31
+ * referencing variables unresolved (flagged "not on payload"), never throws.
32
+ */
33
+ export function buildEnrichedPayloadTree(root, voName, seen = new Set()) {
34
+ if (seen.has(voName))
35
+ return [];
36
+ const vo = root.findObject(voName);
37
+ if (vo === undefined)
38
+ return [];
39
+ const owner = stripPackage(vo.name);
40
+ const nextSeen = new Set(seen).add(voName);
41
+ const out = [];
42
+ for (const f of vo.fields()) {
43
+ const node = {
44
+ name: f.name,
45
+ owner,
46
+ type: neutralTypeStr(f),
47
+ required: isFieldRequired(f),
48
+ };
49
+ if (f.subType === FIELD_SUBTYPE_OBJECT) {
50
+ const ref = f.ownAttr(FIELD_ATTR_OBJECT_REF);
51
+ if (typeof ref === "string" && ref.length > 0) {
52
+ // Owner switches to the nested VO for its fields (the recursion below
53
+ // re-derives `owner` from the resolved VO's own name).
54
+ node.fields = buildEnrichedPayloadTree(root, stripPackage(ref), nextSeen);
55
+ }
56
+ }
57
+ out.push(node);
58
+ }
59
+ return out;
60
+ }
61
+ //# sourceMappingURL=template-payload-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-payload-tree.js","sourceRoot":"","sources":["../../src/generators/template-payload-tree.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,yCAAyC;AACzC,EAAE;AACF,iFAAiF;AACjF,+EAA+E;AAC/E,+EAA+E;AAC/E,gFAAgF;AAChF,uDAAuD;AACvD,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAChF,+EAA+E;AAC/E,iFAAiF;AACjF,6EAA6E;AAC7E,EAAE;AACF,+BAA+B;AAC/B,iFAAiF;AACjF,2EAA2E;AAC3E,mBAAmB;AAEnB,OAAO,EAGL,oBAAoB,EACpB,qBAAqB,EACrB,YAAY,GACb,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGzE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,wBAAwB,CACtC,IAAc,EACd,MAAc,EACd,OAA4B,IAAI,GAAG,EAAE;IAErC,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,EAAE,GAA2B,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC3D,IAAI,EAAE,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAyB;YACjC,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK;YACL,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;YACvB,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;SAC7B,CAAC;QACF,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,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9C,sEAAsE;gBACtE,uDAAuD;gBACvD,IAAI,CAAC,MAAM,GAAG,wBAAwB,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,74 @@
1
+ import { type PayloadField } from "@metaobjectsdev/render";
2
+ /**
3
+ * An enriched payload-field node. Structurally a verify `PayloadField` (so the
4
+ * shared resolver walks it), plus the per-field doc metadata the annotator needs
5
+ * to emit a `ResolvedField` + link: `owner` (the VO that declares the field),
6
+ * `type`, and `required`. Container fields (object / array-of-object) carry
7
+ * `fields` whose nodes are owned by the nested VO.
8
+ */
9
+ export interface AnnotatePayloadField extends PayloadField {
10
+ owner: string;
11
+ type: string;
12
+ required: boolean;
13
+ fields?: AnnotatePayloadField[];
14
+ }
15
+ /** The field a `{{variable}}` / `{{#section}}` resolves to. */
16
+ export interface ResolvedField {
17
+ owner: string;
18
+ name: string;
19
+ type: string;
20
+ required: boolean;
21
+ }
22
+ /** One ordered token of the annotated template. `raw` is the verbatim source
23
+ * span of the tag (text tokens carry `text`), so the source round-trips. */
24
+ export type TplToken = {
25
+ kind: "text";
26
+ text: string;
27
+ } | {
28
+ kind: "var" | "unescaped";
29
+ raw: string;
30
+ path: string;
31
+ field?: ResolvedField;
32
+ href?: string;
33
+ valid: boolean;
34
+ } | {
35
+ kind: "section" | "inverted" | "close";
36
+ raw: string;
37
+ path: string;
38
+ field?: ResolvedField;
39
+ href?: string;
40
+ } | {
41
+ kind: "partial";
42
+ raw: string;
43
+ ref: string;
44
+ href?: string;
45
+ } | {
46
+ kind: "comment";
47
+ raw: string;
48
+ };
49
+ export interface AnnotateOptions {
50
+ /** The root payload VO's short name (owner of the root-context fields). Used
51
+ * only for diagnostics / callers; per-field owner comes off the tree node. */
52
+ ownerVoName: string;
53
+ /**
54
+ * Resolve a partial `{{>ref}}` to a doc-page href, if the ref names a
55
+ * documented template. Returns the href or undefined (highlight-only).
56
+ * Optional — when absent, partials are captured ref-only (no href).
57
+ */
58
+ resolvePartialHref?: (ref: string) => string | undefined;
59
+ /**
60
+ * Override how a resolved field's doc-page href is built (owner page + the
61
+ * shared `#field-<name>` fragment). Optional — when absent, the flat default
62
+ * `./<owner>.md#field-<name>` is used (byte-identical to today). A caller with
63
+ * the output layout + page placement in scope injects a layout-aware resolver
64
+ * (the SAME `docPageHref(layout, …)` the Payload cross-link uses) so the link
65
+ * resolves under package layout too.
66
+ */
67
+ fieldHref?: (owner: string, name: string) => string;
68
+ }
69
+ /**
70
+ * Parse `source` into an annotated IR, resolving each variable/section against
71
+ * the enriched `payload` tree using verify's shared resolution.
72
+ */
73
+ export declare function annotateTemplate(source: string, payload: AnnotatePayloadField[], opts: AnnotateOptions): TplToken[];
74
+ //# sourceMappingURL=template-source-annotate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-source-annotate.d.ts","sourceRoot":"","sources":["../../src/generators/template-source-annotate.ts"],"names":[],"mappings":"AAoBA,OAAO,EAGN,KAAK,YAAY,EAEjB,MAAM,wBAAwB,CAAC;AAGhC;;;;;;GAMG;AACH,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAED,+DAA+D;AAC/D,MAAM,WAAW,aAAa;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED;6EAC6E;AAC7E,MAAM,MAAM,QAAQ,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IACA,IAAI,EAAE,KAAK,GAAG,WAAW,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;CACd,GACD;IACA,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,OAAO,CAAC;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACb,GACD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpC,MAAM,WAAW,eAAe;IAC/B;mFAC+E;IAC/E,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACzD;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CACpD;AAkBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,oBAAoB,EAAE,EAC/B,IAAI,EAAE,eAAe,GACnB,QAAQ,EAAE,CAmKZ"}