@astryxdesign/cli 0.6.3-canary.ea2f048 → 0.6.3-canary.f04b501

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 (505) hide show
  1. package/README.md +106 -72
  2. package/api/blog/blog.doc.mjs +1 -0
  3. package/api/build/build.doc.mjs +4 -3
  4. package/api/build/build.test.mjs +14 -3
  5. package/api/build/build.type.d.mts +36 -2
  6. package/api/build/build.type.mjs +25 -4
  7. package/api/build/help/help.d.mts +8 -5
  8. package/api/build/help/help.mjs +56 -6
  9. package/api/component/component.doc.mjs +13 -3
  10. package/api/component/component.mjs +31 -2
  11. package/api/component/component.test.mjs +38 -0
  12. package/api/component/component.type.d.mts +22 -11
  13. package/api/component/component.type.mjs +32 -24
  14. package/api/component/detail/blocks/blocks.d.mts +2 -1
  15. package/api/component/detail/blocks/blocks.mjs +4 -3
  16. package/api/component/list/list.d.mts +0 -5
  17. package/api/component/list/list.mjs +37 -9
  18. package/api/discover/discover.doc.mjs +2 -1
  19. package/api/discover/discover.type.d.mts +4 -4
  20. package/api/discover/discover.type.mjs +10 -10
  21. package/api/docs/_adapter.d.mts +32 -24
  22. package/api/docs/_adapter.mjs +81 -87
  23. package/api/docs/compiled-topics.test.mjs +78 -0
  24. package/api/docs/detail/detail.mjs +14 -63
  25. package/api/docs/detail/section/section.d.mts +1 -1
  26. package/api/docs/detail/section/section.mjs +44 -20
  27. package/api/docs/detail/section/section.test.mjs +41 -0
  28. package/api/docs/docs.d.mts +7 -2
  29. package/api/docs/docs.doc.mjs +28 -10
  30. package/api/docs/docs.mjs +16 -9
  31. package/api/docs/docs.test.mjs +6 -0
  32. package/api/docs/docs.type.d.mts +40 -3
  33. package/api/docs/docs.type.mjs +36 -8
  34. package/api/docs/index/index.d.mts +18 -0
  35. package/api/docs/index/index.mjs +32 -0
  36. package/api/docs/index/index.test.mjs +62 -0
  37. package/api/docs/integrationDocs.test.mjs +106 -0
  38. package/api/docs/list/list.mjs +3 -7
  39. package/api/doctor/doctor.d.mts +70 -0
  40. package/api/doctor/doctor.doc.mjs +1 -0
  41. package/api/doctor/doctor.mjs +404 -0
  42. package/api/doctor/doctor.test.mjs +522 -1
  43. package/api/gap-report/gap-report.doc.mjs +8 -4
  44. package/api/hook/_adapter.mjs +19 -5
  45. package/api/hook/hook.doc.mjs +1 -0
  46. package/api/hook/hook.type.d.mts +3 -3
  47. package/api/hook/hook.type.mjs +11 -11
  48. package/api/hook/list/list.d.mts +2 -2
  49. package/api/hook/list/list.mjs +69 -17
  50. package/api/init/init.doc.mjs +5 -0
  51. package/api/init/init.test.mjs +41 -1
  52. package/api/init/remove/remove.mjs +1 -1
  53. package/api/init/run/run.mjs +20 -10
  54. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  55. package/api/integration/add-contribution.mjs +23 -10
  56. package/api/integration/add-contribution.test.mjs +121 -7
  57. package/api/integration/add-theme.mjs +34 -64
  58. package/api/integration/add-theme.test.mjs +105 -21
  59. package/api/integration/authoring-checks.test.mjs +8 -4
  60. package/api/integration/integration-authoring.type.d.mts +1 -1
  61. package/api/integration/integration-block-exports.test.mjs +10 -6
  62. package/api/integration/integrationAdd.doc.mjs +8 -4
  63. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  64. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  65. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  66. package/api/integration/integrationAddDoc.doc.mjs +1 -0
  67. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  68. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  69. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  70. package/api/integration/integrationDocConflicts.doc.mjs +1 -0
  71. package/api/integration/integrationPackCheck.doc.mjs +1 -0
  72. package/api/integration/integrationTemplateConflicts.doc.mjs +1 -0
  73. package/api/integration/pack-check.mjs +49 -7
  74. package/api/integration/pack-check.test.mjs +266 -47
  75. package/api/integration/summarizeIssues.doc.mjs +1 -0
  76. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  77. package/api/integration/validate-integration.mjs +52 -102
  78. package/api/integration/validate-integration.test.mjs +176 -23
  79. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  80. package/api/integration/validateIntegration.doc.mjs +2 -1
  81. package/api/json/assertResponse.doc.mjs +1 -0
  82. package/api/json/envelope-types.test.mjs +76 -0
  83. package/api/json/isError.doc.mjs +1 -0
  84. package/api/json/parseResponse.doc.mjs +3 -2
  85. package/api/layout/expand/expand.mjs +7 -5
  86. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  87. package/api/layout/grammar/grammar.mjs +2 -1
  88. package/api/layout/layoutCheck.doc.mjs +1 -0
  89. package/api/layout/layoutExpand.doc.mjs +2 -1
  90. package/api/layout/layoutGrammar.doc.mjs +1 -0
  91. package/api/search/search-return-type.test.mjs +54 -0
  92. package/api/search/search.d.mts +3 -10
  93. package/api/search/search.doc.mjs +6 -1
  94. package/api/search/search.mjs +31 -14
  95. package/api/search/search.test.mjs +34 -0
  96. package/api/search/search.type.d.mts +2 -2
  97. package/api/search/search.type.mjs +1 -1
  98. package/api/swizzle/copy/copy.mjs +28 -11
  99. package/api/swizzle/swizzle.doc.mjs +2 -1
  100. package/api/swizzle/swizzle.type.d.mts +2 -2
  101. package/api/swizzle/swizzle.type.mjs +2 -2
  102. package/api/template/copy/copy.mjs +17 -23
  103. package/api/template/copy/copy.test.mjs +17 -0
  104. package/api/template/template-suffix.test.mjs +41 -21
  105. package/api/template/template.d.mts +1 -1
  106. package/api/template/template.doc.mjs +3 -1
  107. package/api/template/template.type.d.mts +6 -6
  108. package/api/template/template.type.mjs +12 -12
  109. package/api/theme/_adapter.d.mts +2 -3
  110. package/api/theme/_adapter.mjs +4 -5
  111. package/api/theme/add/add.binary.test.mjs +84 -0
  112. package/api/theme/add/add.mjs +20 -3
  113. package/api/theme/add/add.staging.test.mjs +66 -0
  114. package/api/theme/add/add.test.mjs +14 -1
  115. package/api/theme/build/build.mjs +133 -42
  116. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  117. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  118. package/api/theme/build/build.test.mjs +127 -0
  119. package/api/theme/build/font-warning.mjs +3 -3
  120. package/api/theme/build/font-warning.test.mjs +5 -2
  121. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  122. package/api/theme/integration-themes.test.mjs +39 -28
  123. package/api/theme/list/list.test.mjs +19 -20
  124. package/api/theme/listThemes.doc.mjs +6 -5
  125. package/api/theme/palette/generate/generate.mjs +8 -3
  126. package/api/theme/palette/generate/generate.test.mjs +96 -0
  127. package/api/theme/palette/generate/generator.d.mts +10 -13
  128. package/api/theme/palette/generate/generator.mjs +15 -4
  129. package/api/theme/palette/generate/generator.test.mjs +10 -0
  130. package/api/theme/template/template.mjs +11 -2
  131. package/api/theme/template/template.test.mjs +15 -0
  132. package/api/theme/theme.type.d.mts +170 -11
  133. package/api/theme/theme.type.mjs +94 -27
  134. package/api/theme/themeAdd.doc.mjs +4 -3
  135. package/api/theme/themeBuild.doc.mjs +8 -4
  136. package/api/theme/themeList.doc.mjs +6 -3
  137. package/api/theme/themeListAvailable.doc.mjs +5 -3
  138. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  139. package/api/theme/themeTargets.doc.mjs +1 -0
  140. package/api/theme/themeTemplate.doc.mjs +5 -1
  141. package/api/upgrade/_adapter.d.mts +12 -3
  142. package/api/upgrade/_adapter.mjs +123 -19
  143. package/api/upgrade/list/list.mjs +2 -1
  144. package/api/upgrade/list/list.test.mjs +73 -0
  145. package/api/upgrade/project-context.test.mjs +272 -0
  146. package/api/upgrade/provider-agreement.test.mjs +152 -0
  147. package/api/upgrade/run/run.mjs +1 -0
  148. package/api/upgrade/status/status.mjs +2 -2
  149. package/api/upgrade/upgrade.doc.mjs +7 -4
  150. package/api/upgrade/upgrade.type.d.mts +9 -5
  151. package/api/upgrade/upgrade.type.mjs +12 -11
  152. package/assets/codemods/integration-discovery.mjs +48 -4
  153. package/assets/codemods/integration-discovery.test.mjs +73 -0
  154. package/assets/codemods/runner.mjs +115 -5
  155. package/assets/codemods/term-log.mjs +32 -8
  156. package/assets/codemods/term-log.test.mjs +19 -1
  157. package/assets/codemods/transform-prop.mjs +109 -0
  158. package/assets/codemods/transform-prop.test.mjs +95 -0
  159. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +216 -0
  160. package/assets/codemods/transforms/next/index.mjs +11 -1
  161. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  162. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  163. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  164. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  165. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  166. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  167. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  168. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  169. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  170. package/assets/docs/README.md +9 -0
  171. package/assets/docs/authoring.doc.mjs +14 -0
  172. package/assets/docs/cli-integrations.doc.mjs +78 -20
  173. package/assets/docs/cli.doc.mjs +15 -0
  174. package/assets/docs/styling-libraries.doc.mjs +1 -1
  175. package/assets/docs/theme.doc.mjs +1 -1
  176. package/assets/docs/working-with-ai.doc.mjs +1 -1
  177. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  178. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  179. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  180. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  181. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  182. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  183. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  184. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  185. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  186. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  187. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  188. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  189. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  190. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  191. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  192. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  193. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  194. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  195. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  196. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  197. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  198. package/authoring/_shared/contract.ts +22 -0
  199. package/authoring/codemod/codemod.doc.mjs +7 -2
  200. package/authoring/codemod/parse.d.mts +8 -8
  201. package/authoring/codemod/parse.mjs +8 -6
  202. package/authoring/config/config.doc.mjs +2 -2
  203. package/authoring/config/debug-composition.test.mjs +92 -0
  204. package/authoring/config/parse.d.mts +13 -13
  205. package/authoring/config/parse.mjs +8 -8
  206. package/authoring/config/type.ts +18 -6
  207. package/authoring/debug/debug.doc.d.mts +11 -0
  208. package/authoring/debug/debug.doc.mjs +182 -0
  209. package/authoring/debug/parse.d.mts +5 -5
  210. package/authoring/debug/parse.mjs +3 -3
  211. package/authoring/doctypes/_schema.d.mts +788 -23
  212. package/authoring/doctypes/_schema.mjs +492 -39
  213. package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
  214. package/authoring/doctypes/base/graph-fields.doc.mjs +62 -0
  215. package/authoring/doctypes/base/type.ts +40 -0
  216. package/authoring/doctypes/command/command.doc.mjs +4 -3
  217. package/authoring/doctypes/command/parse.d.mts +2 -2
  218. package/authoring/doctypes/command/parse.mjs +1 -1
  219. package/authoring/doctypes/command/type.ts +4 -3
  220. package/authoring/doctypes/component/component.doc.mjs +6 -3
  221. package/authoring/doctypes/component/parse.d.mts +2 -2
  222. package/authoring/doctypes/component/parse.mjs +1 -1
  223. package/authoring/doctypes/component/type.ts +6 -5
  224. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  225. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  226. package/authoring/doctypes/enum/parse.d.mts +2 -2
  227. package/authoring/doctypes/enum/parse.mjs +1 -1
  228. package/authoring/doctypes/enum/type.ts +4 -2
  229. package/authoring/doctypes/function/function.doc.mjs +5 -1
  230. package/authoring/doctypes/function/parse.d.mts +2 -2
  231. package/authoring/doctypes/function/parse.mjs +1 -1
  232. package/authoring/doctypes/function/type.ts +7 -3
  233. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  234. package/authoring/doctypes/hook/parse.d.mts +2 -2
  235. package/authoring/doctypes/hook/parse.mjs +1 -1
  236. package/authoring/doctypes/hook/type.ts +5 -4
  237. package/authoring/doctypes/legacy.d.mts +8 -6
  238. package/authoring/doctypes/legacy.mjs +5 -4
  239. package/authoring/doctypes/load-contract.test.mjs +208 -0
  240. package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
  241. package/authoring/doctypes/namespace/namespace.doc.mjs +132 -0
  242. package/authoring/doctypes/namespace/parse.d.mts +12 -0
  243. package/authoring/doctypes/namespace/parse.mjs +25 -0
  244. package/authoring/doctypes/namespace/parse.test.mjs +165 -0
  245. package/authoring/doctypes/namespace/type.ts +71 -0
  246. package/authoring/doctypes/parse.d.mts +22 -18
  247. package/authoring/doctypes/parse.mjs +22 -12
  248. package/authoring/doctypes/parse.test.mjs +77 -3
  249. package/authoring/doctypes/reference/parse.d.mts +2 -2
  250. package/authoring/doctypes/reference/parse.mjs +8 -5
  251. package/authoring/doctypes/reference/reference.doc.mjs +18 -5
  252. package/authoring/doctypes/reference/type.ts +53 -7
  253. package/authoring/doctypes/schema/parse.d.mts +2 -2
  254. package/authoring/doctypes/schema/parse.mjs +1 -1
  255. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  256. package/authoring/doctypes/schema/type.ts +4 -4
  257. package/authoring/doctypes/template/parse.d.mts +92 -1
  258. package/authoring/doctypes/template/parse.mjs +36 -2
  259. package/authoring/doctypes/template/parse.test.mjs +8 -2
  260. package/authoring/doctypes/template/template.doc.mjs +7 -3
  261. package/authoring/doctypes/template/type.ts +5 -2
  262. package/authoring/doctypes/theme/parse.d.mts +35 -0
  263. package/authoring/doctypes/theme/parse.mjs +76 -0
  264. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  265. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  266. package/authoring/doctypes/theme/type.ts +42 -0
  267. package/authoring/doctypes/types.ts +12 -10
  268. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  269. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  270. package/authoring/gap-report/parse.d.mts +10 -10
  271. package/authoring/gap-report/parse.mjs +6 -6
  272. package/authoring/gap-report/type.ts +1 -1
  273. package/authoring/identity/identity.doc.d.mts +9 -0
  274. package/authoring/identity/identity.doc.mjs +61 -0
  275. package/authoring/identity/type.ts +132 -0
  276. package/authoring/index.d.mts +2 -0
  277. package/authoring/index.d.ts +51 -17
  278. package/authoring/index.mjs +3 -1
  279. package/authoring/integration/integration.doc.mjs +15 -8
  280. package/authoring/integration/parse.d.mts +2 -2
  281. package/authoring/integration/parse.mjs +1 -1
  282. package/authoring/integration/parse.test.mjs +10 -1
  283. package/authoring/integration/schema.d.mts +6 -4
  284. package/authoring/integration/schema.mjs +9 -3
  285. package/authoring/integration/type.ts +18 -7
  286. package/authoring/shadcn/receipt.d.mts +6 -6
  287. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  288. package/clients/cli/command-load-failure.test.mjs +83 -0
  289. package/clients/cli/commands/blog.doc.mjs +1 -1
  290. package/clients/cli/commands/blog.mjs +23 -8
  291. package/clients/cli/commands/blog.test.mjs +42 -1
  292. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  293. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  294. package/clients/cli/commands/build-theme.mjs +5 -5
  295. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  296. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  297. package/clients/cli/commands/build.doc.mjs +5 -2
  298. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  299. package/clients/cli/commands/build.mjs +32 -47
  300. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  301. package/clients/cli/commands/build.text-fields.test.mjs +40 -0
  302. package/clients/cli/commands/component/index.mjs +2 -7
  303. package/clients/cli/commands/component-package.test.mjs +46 -0
  304. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  305. package/clients/cli/commands/component.doc.mjs +1 -1
  306. package/clients/cli/commands/component.test.mjs +19 -0
  307. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  308. package/clients/cli/commands/discover.broken-integration.test.mjs +48 -0
  309. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  310. package/clients/cli/commands/discover.doc.mjs +5 -3
  311. package/clients/cli/commands/discover.mjs +3 -3
  312. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  313. package/clients/cli/commands/docs.doc.mjs +14 -4
  314. package/clients/cli/commands/docs.mjs +121 -21
  315. package/clients/cli/commands/docs.test.mjs +88 -0
  316. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  317. package/clients/cli/commands/doctor-integration-docs.doc.mjs +1 -1
  318. package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -1
  319. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  320. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  321. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  322. package/clients/cli/commands/doctor-integration.test.mjs +15 -7
  323. package/clients/cli/commands/doctor.doc.mjs +1 -1
  324. package/clients/cli/commands/doctor.mjs +6 -16
  325. package/clients/cli/commands/doctor.test.mjs +42 -0
  326. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  327. package/clients/cli/commands/gap-report.test.mjs +72 -0
  328. package/clients/cli/commands/hook/index.mjs +7 -17
  329. package/clients/cli/commands/hook.doc.mjs +1 -1
  330. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  331. package/clients/cli/commands/init.doc.mjs +20 -9
  332. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  333. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  334. package/clients/cli/commands/integration-add.doc.mjs +22 -6
  335. package/clients/cli/commands/integration-authoring.test.mjs +13 -9
  336. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  337. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  338. package/clients/cli/commands/integration.doc.mjs +1 -1
  339. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  340. package/clients/cli/commands/json-contract.test.mjs +33 -0
  341. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  342. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  343. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  344. package/clients/cli/commands/layout.doc.mjs +3 -3
  345. package/clients/cli/commands/layout.mjs +21 -9
  346. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  347. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  348. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  349. package/clients/cli/commands/manifest.doc.mjs +1 -1
  350. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  351. package/clients/cli/commands/search.doc.mjs +7 -4
  352. package/clients/cli/commands/search.mjs +17 -7
  353. package/clients/cli/commands/search.test.mjs +75 -0
  354. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  355. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  356. package/clients/cli/commands/template.doc.mjs +29 -7
  357. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  358. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  359. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  360. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  361. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  362. package/clients/cli/commands/theme-palette-generate.doc.mjs +9 -5
  363. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  364. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  365. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  366. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  367. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  368. package/clients/cli/commands/theme.doc.mjs +1 -1
  369. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  370. package/clients/cli/commands/upgrade.doc.mjs +20 -9
  371. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  372. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  373. package/clients/cli/formatters/index.mjs +162 -1
  374. package/clients/cli/formatters/index.test.mjs +91 -0
  375. package/clients/cli/index.mjs +13 -30
  376. package/clients/cli/latest-version-env.test.mjs +50 -0
  377. package/clients/cli/lib/cli-error.test.mjs +7 -0
  378. package/clients/cli/lib/component-format.mjs +9 -9
  379. package/clients/cli/lib/component-format.test.mjs +1 -1
  380. package/clients/cli/lib/define-command.mjs +32 -6
  381. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  382. package/clients/cli/lib/exit-codes.test.mjs +97 -0
  383. package/clients/cli/lib/hook-format.mjs +19 -10
  384. package/clients/cli/lib/json-shim.mjs +38 -2
  385. package/clients/cli/lib/json-shim.test.mjs +83 -0
  386. package/clients/cli/lib/manifest.d.ts +2 -0
  387. package/clients/cli/lib/manifest.mjs +29 -2
  388. package/clients/cli/lib/manifest.test.mjs +17 -0
  389. package/foundation/agent-docs/agent-docs.d.mts +4 -0
  390. package/foundation/agent-docs/agent-docs.mjs +69 -3
  391. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  392. package/foundation/config/integration-debug.test.mjs +28 -3
  393. package/foundation/config/project-themes.test.mjs +11 -19
  394. package/foundation/config/project.d.mts +8 -0
  395. package/foundation/config/project.mjs +190 -32
  396. package/foundation/config/project.test.mjs +129 -16
  397. package/foundation/discovery/authoring-self-docs.d.mts +75 -0
  398. package/foundation/discovery/authoring-self-docs.mjs +224 -0
  399. package/foundation/discovery/authoring-self-docs.test.mjs +154 -0
  400. package/foundation/discovery/authoring-surface.d.mts +74 -0
  401. package/foundation/discovery/authoring-surface.mjs +525 -0
  402. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  403. package/foundation/discovery/cli-self-docs.d.mts +113 -0
  404. package/foundation/discovery/cli-self-docs.mjs +514 -0
  405. package/foundation/discovery/cli-self-docs.test.mjs +437 -0
  406. package/foundation/discovery/component-discovery.d.mts +1 -1
  407. package/foundation/discovery/component-discovery.mjs +2 -1
  408. package/foundation/discovery/component-loader.d.mts +35 -38
  409. package/foundation/discovery/component-loader.mjs +53 -222
  410. package/foundation/discovery/docs-discovery.d.mts +12 -4
  411. package/foundation/discovery/docs-discovery.mjs +214 -98
  412. package/foundation/discovery/docs-discovery.test.mjs +284 -15
  413. package/foundation/discovery/docs-output-budget.d.mts +28 -0
  414. package/foundation/discovery/docs-output-budget.mjs +50 -0
  415. package/foundation/discovery/docs-section-key.d.mts +98 -0
  416. package/foundation/discovery/docs-section-key.mjs +221 -0
  417. package/foundation/discovery/docs-section-key.test.mjs +224 -0
  418. package/foundation/discovery/template-adapter.d.mts +21 -5
  419. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  420. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  421. package/foundation/discovery/template-adapter.mjs +321 -66
  422. package/foundation/discovery/template-adapter.test.mjs +15 -0
  423. package/foundation/discovery/theme-discovery.d.mts +67 -7
  424. package/foundation/discovery/theme-discovery.mjs +916 -186
  425. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  426. package/foundation/discovery/theming-targets.test.mjs +4 -0
  427. package/foundation/doc-compiler/bundle.d.mts +47 -0
  428. package/foundation/doc-compiler/bundle.mjs +218 -0
  429. package/foundation/doc-compiler/bundle.test.mjs +255 -0
  430. package/foundation/doc-compiler/compile.d.mts +362 -0
  431. package/foundation/doc-compiler/compile.mjs +511 -0
  432. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  433. package/foundation/doc-compiler/diagnostics.mjs +277 -0
  434. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  435. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  436. package/foundation/doc-compiler/import.d.mts +24 -0
  437. package/foundation/doc-compiler/import.mjs +59 -0
  438. package/foundation/doc-compiler/inputs.d.mts +102 -0
  439. package/foundation/doc-compiler/inputs.mjs +286 -0
  440. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  441. package/foundation/doc-compiler/ir.d.mts +22 -0
  442. package/foundation/doc-compiler/ir.mjs +464 -0
  443. package/foundation/doc-compiler/lenses.d.mts +33 -0
  444. package/foundation/doc-compiler/lenses.mjs +127 -0
  445. package/foundation/doc-compiler/lower-doc.test.mjs +492 -0
  446. package/foundation/doc-compiler/overlays.d.mts +37 -0
  447. package/foundation/doc-compiler/overlays.mjs +206 -0
  448. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  449. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  450. package/foundation/doc-compiler/read.d.mts +126 -0
  451. package/foundation/doc-compiler/read.mjs +320 -0
  452. package/foundation/doc-compiler/read.test.mjs +313 -0
  453. package/foundation/doc-compiler/source.d.mts +33 -0
  454. package/foundation/doc-compiler/source.mjs +128 -0
  455. package/foundation/fs/module-loader.d.mts +1 -0
  456. package/foundation/fs/module-loader.mjs +50 -1
  457. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  458. package/foundation/fs/path-safety.d.mts +3 -2
  459. package/foundation/fs/path-safety.mjs +49 -19
  460. package/foundation/fs/path-safety.test.mjs +50 -0
  461. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  462. package/foundation/identity/provider-identity.d.mts +90 -0
  463. package/foundation/identity/provider-identity.mjs +320 -0
  464. package/foundation/identity/provider-identity.test.mjs +254 -0
  465. package/foundation/identity/providers.d.mts +7 -0
  466. package/foundation/identity/providers.mjs +16 -0
  467. package/foundation/integrations/autolink.d.mts +58 -1
  468. package/foundation/integrations/autolink.mjs +143 -45
  469. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  470. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  471. package/foundation/integrations/contribution-inventory.d.mts +1 -1
  472. package/foundation/integrations/contribution-inventory.mjs +17 -20
  473. package/foundation/integrations/contribution-inventory.test.mjs +67 -27
  474. package/foundation/integrations/integration-warnings.mjs +6 -0
  475. package/foundation/integrations/integrations.d.mts +49 -2
  476. package/foundation/integrations/integrations.mjs +81 -8
  477. package/foundation/integrations/integrations.test.mjs +384 -1
  478. package/foundation/integrations/provider-conflicts.test.mjs +125 -0
  479. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  480. package/foundation/integrations/provider-resolution.d.mts +152 -0
  481. package/foundation/integrations/provider-resolution.mjs +576 -0
  482. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  483. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  484. package/foundation/integrations/theme-descriptor.mjs +44 -0
  485. package/foundation/integrations/validate-contributions.d.mts +2 -0
  486. package/foundation/integrations/validate-contributions.mjs +114 -10
  487. package/foundation/response/base.d.ts +8 -4
  488. package/foundation/response/error-codes.doc.mjs +3 -4
  489. package/foundation/response/error-codes.mjs +2 -2
  490. package/foundation/response/error-codes.test.mjs +83 -0
  491. package/foundation/response/json-contract.test.mjs +57 -17
  492. package/foundation/response/json.d.mts +4 -2
  493. package/foundation/response/json.mjs +8 -10
  494. package/foundation/response/response-types.doc.mjs +16 -11
  495. package/foundation/response/response-types.doc.test.mjs +158 -0
  496. package/foundation/response/response.doc.mjs +1 -1
  497. package/foundation/text/string-utils.mjs +22 -10
  498. package/foundation/xle/expand.d.mts +2 -0
  499. package/foundation/xle/expand.mjs +3 -2
  500. package/foundation/xle/expand.test.mjs +54 -0
  501. package/package.json +9 -11
  502. package/assets/templates/themes/manifest.json +0 -95
  503. package/clients/cli/lib/update-check.mjs +0 -83
  504. package/clients/cli/lib/update-check.test.mjs +0 -137
  505. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -6,16 +6,16 @@
6
6
  *
7
7
  * Invocation -> type discriminator
8
8
  * ------------------------------------------------------------------
9
- * xds --json discover -> discover.list
10
- * xds --json discover @scope/name -> discover.detail
11
- * xds --json discover @scope/name/Component -> discover.detail.doc
12
- * xds --json discover <searchterm> (1 match) -> discover.detail.doc
13
- * xds --json discover <searchterm> (N matches) -> discover.search
14
- * (not found) -> CLIError
9
+ * astryx --json discover -> discover.list
10
+ * astryx --json discover @scope/name -> discover.detail
11
+ * astryx --json discover @scope/name/Component -> discover.detail.doc
12
+ * astryx --json discover <searchterm> (1 match) -> discover.detail.doc
13
+ * astryx --json discover <searchterm> (N matches) -> discover.search
14
+ * (not found) -> CLIError
15
15
  */
16
16
 
17
17
  /**
18
- * xds --json discover
18
+ * astryx --json discover
19
19
  * @typedef {object} DiscoverListResponse
20
20
  * @property {'discover.list'} type
21
21
  * @property {DiscoverListEntry[]} data
@@ -35,21 +35,21 @@
35
35
  */
36
36
 
37
37
  /**
38
- * xds --json discover @scope/name
38
+ * astryx --json discover @scope/name
39
39
  * @typedef {object} DiscoverDetailResponse
40
40
  * @property {'discover.detail'} type
41
41
  * @property {DiscoverListEntry} data
42
42
  */
43
43
 
44
44
  /**
45
- * xds --json discover @scope/name/Component
45
+ * astryx --json discover @scope/name/Component
46
46
  * @typedef {object} DiscoverDetailDocResponse
47
47
  * @property {'discover.detail.doc'} type
48
48
  * @property {import('@astryxdesign/cli/authoring').ComponentDoc} data
49
49
  */
50
50
 
51
51
  /**
52
- * xds --json discover <searchterm> (multiple matches)
52
+ * astryx --json discover <searchterm> (multiple matches)
53
53
  * @typedef {object} DiscoverSearchResponse
54
54
  * @property {'discover.search'} type
55
55
  * @property {{query: string, matches: DiscoverSearchEntry[]}} data
@@ -16,34 +16,37 @@
16
16
  */
17
17
  export function loadDocsCatalog(cwd?: string): Promise<DocsCatalog>;
18
18
  /**
19
- * @param {string} docPath
20
- * @param {{lang?: string|null}} [opts]
21
- * @returns {Promise<import('./docs.type.mjs').DocsDetailResponse['data']>}
19
+ * One topic, lowered for `lang`: overlaid, extensions merged, keys stamped.
20
+ * Memoized per catalog, so a read that references a topic twice loads it once.
21
+ * Every read of the catalog shares the memoized node, so it is frozen; the
22
+ * lenses hand readers copies.
23
+ * @param {DocsCatalog} catalog
24
+ * @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
25
+ * @param {string | null} [lang]
26
+ * @returns {Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode>}
22
27
  */
23
- export function loadReferenceDocs(docPath: string, { lang }?: {
24
- lang?: string | null;
25
- }): Promise<import("./docs.type.mjs").DocsDetailResponse["data"]>;
28
+ export function lowerTopic(catalog: DocsCatalog, entry: import("../../foundation/discovery/docs-discovery.mjs").DocsTopicEntry, lang?: string | null): Promise<import("../../foundation/doc-compiler/compile.mjs").CompiledReferenceNode>;
26
29
  /**
27
- * Load one catalog entry: its own doc, plus any extension an integration
28
- * merged onto it, in configuration order.
29
- *
30
- * A localization overlay applies to each file before the extensions are
31
- * merged, so an extension written in the base language stays readable under
32
- * `--dense`/`--zh` (it replaces its own sections and leaves the rest
33
- * translated) rather than being dropped.
34
- *
30
+ * How a token reference finds its target: the topic it names in `catalog`,
31
+ * lowered for the same language.
32
+ * @param {DocsCatalog} catalog
33
+ * @param {string | null} lang
34
+ * @returns {(topic: string) => Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode | null>}
35
+ */
36
+ export function referenceTargets(catalog: DocsCatalog, lang: string | null): (topic: string) => Promise<import("../../foundation/doc-compiler/compile.mjs").CompiledReferenceNode | null>;
37
+ /**
38
+ * One topic, compiled for `lang`: lowered, then every token reference linked.
39
+ * @param {DocsCatalog} catalog
35
40
  * @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
36
- * @param {{lang?: string|null}} [opts]
37
- * @returns {Promise<import('./docs.type.mjs').DocsDetailResponse['data']>}
41
+ * @param {string | null} [lang]
42
+ * @returns {Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode>}
38
43
  */
39
- export function loadTopicDoc(entry: import("../../foundation/discovery/docs-discovery.mjs").DocsTopicEntry, { lang }?: {
40
- lang?: string | null;
41
- }): Promise<import("./docs.type.mjs").DocsDetailResponse["data"]>;
44
+ export function compileTopic(catalog: DocsCatalog, entry: import("../../foundation/discovery/docs-discovery.mjs").DocsTopicEntry, lang?: string | null): Promise<import("../../foundation/doc-compiler/compile.mjs").CompiledReferenceNode>;
42
45
  /**
43
46
  * Resolve `topic` against the project's catalog (throwing `ERR_UNKNOWN_TOPIC`
44
- * when unmatched), and load it with any --dense/--zh overlay and any
45
- * integration extension applied. Shared by the detail and section leaves so
46
- * topic normalization and unknown-topic handling live in exactly one place.
47
+ * when unmatched) and lower it with any --dense/--zh overlay and any
48
+ * integration extension applied. Shared by the leaves so topic normalization
49
+ * and unknown-topic handling live in exactly one place.
47
50
  *
48
51
  * @param {string} topic
49
52
  * @param {object} [options]
@@ -53,7 +56,8 @@ export function loadTopicDoc(entry: import("../../foundation/discovery/docs-disc
53
56
  * @param {string} [options.cwd]
54
57
  * @returns {Promise<{
55
58
  * catalog: DocsCatalog,
56
- * docsData: import('./docs.type.mjs').DocsDetailResponse['data'],
59
+ * node: import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode,
60
+ * lang: string | null,
57
61
  * }>}
58
62
  */
59
63
  export function resolveTopicDocs(topic: string, options?: {
@@ -63,6 +67,10 @@ export function resolveTopicDocs(topic: string, options?: {
63
67
  cwd?: string | undefined;
64
68
  }): Promise<{
65
69
  catalog: DocsCatalog;
66
- docsData: import("./docs.type.mjs").DocsDetailResponse["data"];
70
+ node: import("../../foundation/doc-compiler/compile.mjs").CompiledReferenceNode;
71
+ lang: string | null;
67
72
  }>;
68
73
  import { DocsCatalog } from '../../foundation/discovery/docs-discovery.mjs';
74
+ import { OVERLAY_LANGUAGES } from '../../foundation/doc-compiler/read.mjs';
75
+ import { overlayLanguages } from '../../foundation/doc-compiler/read.mjs';
76
+ export { OVERLAY_LANGUAGES, overlayLanguages };
@@ -7,26 +7,33 @@
7
7
  * packages/cli/assets/docs/{topic}.doc.mjs plus every topic the configured
8
8
  * integrations contribute — and, when a --dense/--zh overlay is requested,
9
9
  * the sibling {topic}.doc.dense.mjs / {topic}.doc.zh.mjs.
10
- * @output Catalog access, overlay- and extension-merged reference-doc data,
11
- * and a combined resolve step ({catalog, docsData}) that the detail and
12
- * section leaves share.
13
- * @position Sits beside docs.mjs (api/docs/). Owns everything ≥2 leaves need so
14
- * no leaf re-implements resolution, overlay merging, or unknown-topic
15
- * handling. Discovery itself lives in foundation/discovery/docs-discovery,
16
- * which api/search and the agent-docs block read through the same catalog.
10
+ * @output Catalog access, the compiler input for a topic, and the compiled
11
+ * node for it: lowered (overlaid, extensions merged, keys stamped) or linked
12
+ * (token references resolved too), memoized per catalog.
13
+ * @position Sits beside docs.mjs (api/docs/). Hands topics to
14
+ * foundation/doc-compiler (which loads their files) and memoizes the nodes
15
+ * per catalog, so no leaf, doctor check or search loads, merges, or resolves
16
+ * docs on its own. Discovery itself lives in
17
+ * foundation/discovery/docs-discovery, which the catalog comes from.
17
18
  */
18
19
 
19
- import * as fs from 'node:fs';
20
- import * as path from 'node:path';
21
- import {pathToFileURL} from 'node:url';
22
20
  import {Project} from '../../foundation/config/project.mjs';
21
+ import {DocsCatalog} from '../../foundation/discovery/docs-discovery.mjs';
23
22
  import {
24
- DocsCatalog,
25
- mergeTopic,
26
- } from '../../foundation/discovery/docs-discovery.mjs';
23
+ linkReferenceTopic,
24
+ lowerReferenceTopic,
25
+ } from '../../foundation/doc-compiler/compile.mjs';
26
+ import {
27
+ deepFreeze,
28
+ loadTopicInput,
29
+ OVERLAY_LANGUAGES,
30
+ overlayLanguages,
31
+ } from '../../foundation/doc-compiler/read.mjs';
27
32
  import {AstryxError} from '../error.mjs';
28
33
  import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
29
34
 
35
+ export {OVERLAY_LANGUAGES, overlayLanguages};
36
+
30
37
  /**
31
38
  * The project's topics: the built-in ones plus whatever the configured
32
39
  * integrations contribute.
@@ -50,92 +57,78 @@ export async function loadDocsCatalog(cwd = process.cwd()) {
50
57
  }
51
58
 
52
59
  /**
53
- * @param {string} docPath
54
- * @param {{lang?: string|null}} [opts]
55
- * @returns {Promise<import('./docs.type.mjs').DocsDetailResponse['data']>}
60
+ * The overlay a read applies: none for the authored language.
61
+ * @param {string | null | undefined} lang
62
+ * @returns {string | null}
56
63
  */
57
- export async function loadReferenceDocs(docPath, {lang} = {}) {
58
- const mod = await import(pathToFileURL(docPath).href);
59
- const docs = mod.docs ?? mod.default;
60
- if (!lang || lang === 'en') return docs;
61
-
62
- const dir = path.dirname(docPath);
63
- const base = path.basename(docPath, '.doc.mjs');
64
- const locale = lang === 'dense' ? 'dense' : lang;
65
- const translationPath = path.join(dir, `${base}.doc.${locale}.mjs`);
66
- if (!fs.existsSync(translationPath)) return docs;
64
+ function overlayLanguage(lang) {
65
+ return lang && lang !== 'en' ? lang : null;
66
+ }
67
67
 
68
- const translationMod = await import(pathToFileURL(translationPath).href);
69
- const translation = translationMod.docsZh || translationMod.docsDense;
70
- if (!translation) return docs;
68
+ /** @type {WeakMap<DocsCatalog, Map<string, Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode>>>} */
69
+ const loweredByCatalog = new WeakMap();
71
70
 
72
- // Overlays are keyed to a base section by title (`section`), not by array
73
- // position. Position-keying silently grafted each overlay title onto whatever
74
- // base section happened to share its index, so an overlay that omitted or
75
- // reordered a section corrupted every section after it — `docs tokens --dense`
76
- // printed the colour table under a "Spacing" heading (#2182). An overlay may
77
- // now cover any subset of sections, in any order; sections it does not name
78
- // keep their base content.
79
- /** @type {Map<string, any>} */
80
- const bySection = new Map();
81
- for (const ts of translation.sections ?? []) {
82
- if (ts?.section != null) bySection.set(ts.section, ts);
71
+ /**
72
+ * One topic, lowered for `lang`: overlaid, extensions merged, keys stamped.
73
+ * Memoized per catalog, so a read that references a topic twice loads it once.
74
+ * Every read of the catalog shares the memoized node, so it is frozen; the
75
+ * lenses hand readers copies.
76
+ * @param {DocsCatalog} catalog
77
+ * @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
78
+ * @param {string | null} [lang]
79
+ * @returns {Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode>}
80
+ */
81
+ export function lowerTopic(catalog, entry, lang = null) {
82
+ const overlay = overlayLanguage(lang);
83
+ let cache = loweredByCatalog.get(catalog);
84
+ if (!cache) {
85
+ cache = new Map();
86
+ loweredByCatalog.set(catalog, cache);
83
87
  }
88
+ const key = `${entry.name.toLowerCase()}\u0000${overlay ?? ''}`;
89
+ let lowered = cache.get(key);
90
+ if (!lowered) {
91
+ lowered = loadTopicInput(entry, overlay).then(input =>
92
+ deepFreeze(lowerReferenceTopic(input)),
93
+ );
94
+ cache.set(key, lowered);
95
+ }
96
+ return lowered;
97
+ }
84
98
 
85
- return {
86
- ...docs,
87
- description: translation.description || docs.description,
88
- sections: docs.sections.map(
89
- (/** @type {import('@astryxdesign/cli/authoring').ReferenceSection} */ section) => {
90
- const ts = bySection.get(section.title);
91
- if (!ts) return section;
92
- return {
93
- ...section,
94
- title: ts.title || section.title,
95
- content: section.content.map(
96
- (
97
- /** @type {import('@astryxdesign/cli/authoring').ReferenceContentBlock} */ block,
98
- /** @type {number} */ bi,
99
- ) => {
100
- const tb = ts.content?.[bi];
101
- if (!tb) return block;
102
- if (tb.type === 'prose' && block.type === 'prose') return {...block, text: tb.text};
103
- if (tb.type === 'list' && block.type === 'list') return {...block, items: tb.items};
104
- return block;
105
- },
106
- ),
107
- };
108
- },
109
- ),
99
+ /**
100
+ * How a token reference finds its target: the topic it names in `catalog`,
101
+ * lowered for the same language.
102
+ * @param {DocsCatalog} catalog
103
+ * @param {string | null} lang
104
+ * @returns {(topic: string) => Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode | null>}
105
+ */
106
+ export function referenceTargets(catalog, lang) {
107
+ return async topic => {
108
+ const target = catalog.resolve(topic);
109
+ return target ? lowerTopic(catalog, target, lang) : null;
110
110
  };
111
111
  }
112
112
 
113
113
  /**
114
- * Load one catalog entry: its own doc, plus any extension an integration
115
- * merged onto it, in configuration order.
116
- *
117
- * A localization overlay applies to each file before the extensions are
118
- * merged, so an extension written in the base language stays readable under
119
- * `--dense`/`--zh` (it replaces its own sections and leaves the rest
120
- * translated) rather than being dropped.
121
- *
114
+ * One topic, compiled for `lang`: lowered, then every token reference linked.
115
+ * @param {DocsCatalog} catalog
122
116
  * @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
123
- * @param {{lang?: string|null}} [opts]
124
- * @returns {Promise<import('./docs.type.mjs').DocsDetailResponse['data']>}
117
+ * @param {string | null} [lang]
118
+ * @returns {Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode>}
125
119
  */
126
- export async function loadTopicDoc(entry, {lang} = {}) {
127
- let doc = await loadReferenceDocs(entry.path, {lang});
128
- for (const extension of entry.extensions) {
129
- doc = mergeTopic(doc, await loadReferenceDocs(extension.path, {lang}));
130
- }
131
- return doc;
120
+ export async function compileTopic(catalog, entry, lang = null) {
121
+ return linkReferenceTopic(
122
+ await lowerTopic(catalog, entry, lang),
123
+ referenceTargets(catalog, lang),
124
+ );
132
125
  }
133
126
 
134
127
  /**
135
128
  * Resolve `topic` against the project's catalog (throwing `ERR_UNKNOWN_TOPIC`
136
- * when unmatched), and load it with any --dense/--zh overlay and any
137
- * integration extension applied. Shared by the detail and section leaves so
138
- * topic normalization and unknown-topic handling live in exactly one place.
129
+ * when unmatched) and lower it with any --dense/--zh overlay and any
130
+ * integration extension applied. Shared by the leaves so topic normalization
131
+ * and unknown-topic handling live in exactly one place.
139
132
  *
140
133
  * @param {string} topic
141
134
  * @param {object} [options]
@@ -145,7 +138,8 @@ export async function loadTopicDoc(entry, {lang} = {}) {
145
138
  * @param {string} [options.cwd]
146
139
  * @returns {Promise<{
147
140
  * catalog: DocsCatalog,
148
- * docsData: import('./docs.type.mjs').DocsDetailResponse['data'],
141
+ * node: import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode,
142
+ * lang: string | null,
149
143
  * }>}
150
144
  */
151
145
  export async function resolveTopicDocs(topic, options = {}) {
@@ -165,6 +159,6 @@ export async function resolveTopicDocs(topic, options = {}) {
165
159
  );
166
160
  }
167
161
 
168
- const docsData = await loadTopicDoc(entry, {lang: effectiveLang});
169
- return {catalog, docsData};
162
+ const node = await lowerTopic(catalog, entry, effectiveLang);
163
+ return {catalog, node, lang: effectiveLang};
170
164
  }
@@ -0,0 +1,78 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Every shipped topic compiles to a plain-JSON node that answers every
5
+ * docs read exactly as the live one does, and no read can change another read
6
+ * of the same catalog.
7
+ */
8
+
9
+ import {describe, expect, it} from 'vitest';
10
+ import {parseCompiledReferenceNode} from '../../foundation/doc-compiler/ir.mjs';
11
+ import {detailView, indexView} from '../../foundation/doc-compiler/lenses.mjs';
12
+ import {
13
+ compileTopic,
14
+ loadDocsCatalog,
15
+ lowerTopic,
16
+ overlayLanguages,
17
+ } from './_adapter.mjs';
18
+
19
+ const SLOW = 60_000;
20
+
21
+ describe('every shipped topic compiles to plain JSON', () => {
22
+ it(
23
+ 'survives a JSON round trip with identical responses in every language',
24
+ async () => {
25
+ const catalog = await loadDocsCatalog();
26
+ let compiled = 0;
27
+ for (const entry of catalog.entries()) {
28
+ for (const lang of [null, ...overlayLanguages(entry)]) {
29
+ const lowered = await lowerTopic(catalog, entry, lang);
30
+ expect(parseCompiledReferenceNode(lowered)).toBe(lowered);
31
+ const node = await compileTopic(catalog, entry, lang);
32
+ expect(parseCompiledReferenceNode(node)).toBe(node);
33
+ const copy = parseCompiledReferenceNode(
34
+ JSON.parse(JSON.stringify(node)),
35
+ );
36
+ expect(JSON.stringify(detailView(copy))).toBe(
37
+ JSON.stringify(detailView(node)),
38
+ );
39
+ expect(JSON.stringify(indexView(copy))).toBe(
40
+ JSON.stringify(indexView(node)),
41
+ );
42
+ compiled += 1;
43
+ }
44
+ }
45
+ expect(compiled).toBeGreaterThan(catalog.entries().length);
46
+ },
47
+ SLOW,
48
+ );
49
+ });
50
+
51
+ describe('reads that share a catalog', () => {
52
+ it(
53
+ 'never let one read change another',
54
+ async () => {
55
+ const catalog = await loadDocsCatalog();
56
+ const tokens = catalog.resolve('tokens');
57
+ const first = detailView(await compileTopic(catalog, tokens));
58
+ for (const section of first.sections) {
59
+ section.title = 'EDITED';
60
+ for (const block of section.content) {
61
+ if (typeof block.text === 'string') block.text = 'EDITED';
62
+ if (Array.isArray(block.rows)) block.rows.push(['EDITED']);
63
+ }
64
+ }
65
+ const again = detailView(await compileTopic(catalog, tokens));
66
+ const index = indexView(await lowerTopic(catalog, tokens));
67
+ const spacing = detailView(
68
+ await compileTopic(catalog, catalog.resolve('spacing')),
69
+ );
70
+ for (const read of [again, index, spacing]) {
71
+ expect(JSON.stringify(read)).not.toContain('EDITED');
72
+ }
73
+ const lowered = await lowerTopic(catalog, tokens);
74
+ expect(Object.isFrozen(lowered.doc.sections[0].content)).toBe(true);
75
+ },
76
+ SLOW,
77
+ );
78
+ });
@@ -3,69 +3,17 @@
3
3
  /**
4
4
  * @file docs.detail leaf — load one topic's full reference doc.
5
5
  *
6
- * @input A topic name plus optional {lang, zh, dense}. Resolves and loads the
7
- * topic via the shared adapter, then inlines any token-ref blocks.
6
+ * @input A topic name plus optional {lang, zh, dense, cwd}. Resolves the topic
7
+ * via the shared adapter and compiles it with its token references linked.
8
8
  * @output { type: 'docs.detail', data: ReferenceDoc } — the full doc with
9
- * token-refs resolved, matching `xds --json docs <topic>`.
10
- * @position Leaf under api/docs. Owns resolveTokenRefs (used only here); shares
11
- * discovery/loading/topic-resolution with the section leaf via _adapter.mjs.
9
+ * token-refs inlined, matching `astryx --json docs <topic>`.
10
+ * @position Leaf under api/docs. Reads the compiled node through the detail
11
+ * lens; resolution, overlays and extensions happen in the compiler.
12
12
  */
13
13
 
14
- import {loadTopicDoc, resolveTopicDocs} from '../_adapter.mjs';
15
-
16
- /**
17
- * Resolve token-ref blocks by inlining the referenced section's table.
18
- * This allows section docs to reference token tables without duplicating data.
19
- *
20
- * The reference is resolved through the catalog, so a topic may point at one
21
- * an integration contributed (or replaced) rather than only at a built-in.
22
- * @param {import('../docs.type.mjs').DocsDetailResponse['data']} docsData
23
- * @param {import('../../../foundation/discovery/docs-discovery.mjs').DocsCatalog} catalog
24
- * @returns {Promise<import('../docs.type.mjs').DocsDetailResponse['data']>}
25
- */
26
- async function resolveTokenRefs(docsData, catalog) {
27
- const resolved = {...docsData, sections: [...docsData.sections]};
28
- for (let si = 0; si < resolved.sections.length; si++) {
29
- const section = resolved.sections[si];
30
- /** @type {import('@astryxdesign/cli/authoring').ReferenceContentBlock[]} */
31
- const newContent = [];
32
- for (const block of section.content) {
33
- if (block.type === 'token-ref') {
34
- const refEntry = catalog.resolve(block.topic);
35
- if (!refEntry) {
36
- newContent.push({type: 'prose', text: `[token-ref: unknown topic "${block.topic}"]`});
37
- continue;
38
- }
39
- const refDocs = await loadTopicDoc(refEntry);
40
- const refSection = refDocs.sections.find(
41
- (/** @type {import('@astryxdesign/cli/authoring').ReferenceSection} */ s) =>
42
- s.title.toLowerCase() === block.section.toLowerCase(),
43
- );
44
- if (!refSection) {
45
- newContent.push({type: 'prose', text: `[token-ref: section "${block.section}" not found in "${block.topic}"]`});
46
- continue;
47
- }
48
- // Inline the referenced section's content blocks (tables, prose, etc.)
49
- // and carry over the previewType
50
- for (const refBlock of refSection.content) {
51
- newContent.push(refBlock);
52
- }
53
- // If the referenced section has a previewType, attach it to our section
54
- if (refSection.previewType && !section.previewType) {
55
- resolved.sections[si] = {...section, previewType: refSection.previewType, content: newContent};
56
- }
57
- } else {
58
- newContent.push(block);
59
- }
60
- }
61
- if (resolved.sections[si] === section) {
62
- resolved.sections[si] = {...section, content: newContent};
63
- } else {
64
- resolved.sections[si].content = newContent;
65
- }
66
- }
67
- return resolved;
68
- }
14
+ import {linkReferenceTopic} from '../../../foundation/doc-compiler/compile.mjs';
15
+ import {detailView} from '../../../foundation/doc-compiler/lenses.mjs';
16
+ import {referenceTargets, resolveTopicDocs} from '../_adapter.mjs';
69
17
 
70
18
  /**
71
19
  * @param {string} topic
@@ -77,7 +25,10 @@ async function resolveTokenRefs(docsData, catalog) {
77
25
  * @returns {Promise<import('../docs.type.mjs').DocsDetailResponse>}
78
26
  */
79
27
  export async function detail(topic, options = {}) {
80
- const {catalog, docsData} = await resolveTopicDocs(topic, options);
81
- const resolved = await resolveTokenRefs(docsData, catalog);
82
- return {type: 'docs.detail', data: resolved};
28
+ const {catalog, node, lang} = await resolveTopicDocs(topic, options);
29
+ const linked = await linkReferenceTopic(
30
+ node,
31
+ referenceTargets(catalog, lang),
32
+ );
33
+ return {type: 'docs.detail', data: detailView(linked)};
83
34
  }
@@ -3,7 +3,7 @@
3
3
 
4
4
  /**
5
5
  * @param {string} topic
6
- * @param {string} sectionName
6
+ * @param {string} sectionName a section key, or a title (or part of one)
7
7
  * @param {object} [options]
8
8
  * @param {string} [options.lang]
9
9
  * @param {boolean} [options.zh]
@@ -1,25 +1,36 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
3
  /**
4
- * @file docs.detail.section leaf — load a single named section of a topic.
4
+ * @file docs.detail.section leaf — load a single section of a topic.
5
5
  *
6
6
  * @input A topic name, a section query, and optional {lang, zh, dense}. Resolves
7
- * and loads the topic via the shared adapter, then finds the first section
8
- * whose title contains the (case-insensitive) query.
9
- * @output { type: 'docs.detail.section', data: ReferenceSection } — matching
10
- * `xds --json docs <topic> <section>`. Throws ERR_UNKNOWN_SECTION when no
11
- * section title matches.
12
- * @position Leaf nested under api/docs/detail. Shares discovery/loading/
13
- * topic-resolution with the detail leaf via _adapter.mjs.
7
+ * the topic via the shared adapter, finds the section in its lowered compiled
8
+ * node by its stable key, then by exact title, then by a title that contains
9
+ * the query, and links only that section.
10
+ * @output { type: 'docs.detail.section', data: ReferenceSection } with any
11
+ * token-ref blocks inlined — matching `astryx --json docs <topic> <section>`.
12
+ * Throws ERR_UNKNOWN_SECTION when nothing matches, or when the query matches
13
+ * more than one section (the candidates come back as suggestions).
14
+ * @position Leaf nested under api/docs/detail. Shares topic resolution with the
15
+ * detail leaf via _adapter.mjs and reads through the compiler's lenses.
14
16
  */
15
17
 
16
18
  import {AstryxError} from '../../../error.mjs';
17
19
  import {ERROR_CODES} from '../../../../foundation/response/error-codes.mjs';
18
- import {resolveTopicDocs} from '../../_adapter.mjs';
20
+ import {
21
+ findDocSection,
22
+ sectionKey,
23
+ } from '../../../../foundation/discovery/docs-section-key.mjs';
24
+ import {linkReferenceSection} from '../../../../foundation/doc-compiler/compile.mjs';
25
+ import {
26
+ readerSections,
27
+ sectionView,
28
+ } from '../../../../foundation/doc-compiler/lenses.mjs';
29
+ import {referenceTargets, resolveTopicDocs} from '../../_adapter.mjs';
19
30
 
20
31
  /**
21
32
  * @param {string} topic
22
- * @param {string} sectionName
33
+ * @param {string} sectionName a section key, or a title (or part of one)
23
34
  * @param {object} [options]
24
35
  * @param {string} [options.lang]
25
36
  * @param {boolean} [options.zh]
@@ -28,10 +39,9 @@ import {resolveTopicDocs} from '../../_adapter.mjs';
28
39
  * @returns {Promise<import('../../docs.type.mjs').DocsDetailSectionResponse>}
29
40
  */
30
41
  export async function section(topic, sectionName, options = {}) {
31
- // An empty section name must error, not resolve to the first section via
32
- // `.includes('')`. The docs() dispatcher routes a falsy section to detail, but
33
- // the leaf must be safe on its own. A non-string would also throw a raw
34
- // TypeError below (`.toLowerCase()`) → downgrades to ERR_UNKNOWN.
42
+ // An empty section name must error, not resolve to the first section. The
43
+ // docs() dispatcher routes a falsy section to the topic, but the leaf must be
44
+ // safe on its own; a non-string would otherwise throw a raw TypeError.
35
45
  if (typeof sectionName !== 'string' || !sectionName.trim()) {
36
46
  throw new AstryxError(
37
47
  'A section name is required',
@@ -39,16 +49,30 @@ export async function section(topic, sectionName, options = {}) {
39
49
  ERROR_CODES.ERR_UNKNOWN_SECTION,
40
50
  );
41
51
  }
42
- const {docsData} = await resolveTopicDocs(topic, options);
43
52
 
44
- const normalizedSection = sectionName.toLowerCase();
45
- const match = docsData.sections.find(s => s.title.toLowerCase().includes(normalizedSection));
53
+ const {catalog, node, lang} = await resolveTopicDocs(topic, options);
54
+ const sections = readerSections(node);
55
+ const {section: match, candidates} = findDocSection(sections, sectionName);
46
56
  if (!match) {
57
+ const ambiguous = candidates.length > 1;
47
58
  throw new AstryxError(
48
- `Section "${sectionName}" not found in "${topic}"`,
49
- docsData.sections.map(s => ({name: s.title, reason: 'available section'})),
59
+ ambiguous
60
+ ? `Section "${sectionName}" matches ${candidates.length} sections in "${topic}". Read one by its key.`
61
+ : `Section "${sectionName}" not found in "${topic}"`,
62
+ (ambiguous ? candidates : sections).map(s => ({
63
+ name: sectionKey(s),
64
+ reason: s.title,
65
+ })),
50
66
  ERROR_CODES.ERR_UNKNOWN_SECTION,
51
67
  );
52
68
  }
53
- return {type: 'docs.detail.section', data: match};
69
+
70
+ // A section read on its own inlines its token refs, as the whole topic does;
71
+ // otherwise a section that is only a token-ref prints blank. Only this
72
+ // section is linked, so a broken reference elsewhere cannot fail the read.
73
+ const linked = await linkReferenceSection(
74
+ match,
75
+ referenceTargets(catalog, lang),
76
+ );
77
+ return {type: 'docs.detail.section', data: sectionView(node, linked)};
54
78
  }