@astryxdesign/cli 0.6.3-canary.ebaebc4 → 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 (390) hide show
  1. package/README.md +106 -73
  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 +35 -1
  6. package/api/build/build.type.mjs +24 -3
  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 +16 -5
  13. package/api/component/component.type.mjs +13 -5
  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/docs/_adapter.d.mts +3 -8
  20. package/api/docs/_adapter.mjs +13 -105
  21. package/api/docs/docs.doc.mjs +1 -0
  22. package/api/docs/list/list.mjs +3 -7
  23. package/api/doctor/doctor.d.mts +25 -3
  24. package/api/doctor/doctor.doc.mjs +1 -0
  25. package/api/doctor/doctor.mjs +185 -13
  26. package/api/doctor/doctor.test.mjs +326 -1
  27. package/api/gap-report/gap-report.doc.mjs +8 -4
  28. package/api/hook/_adapter.mjs +19 -5
  29. package/api/hook/hook.doc.mjs +1 -0
  30. package/api/hook/list/list.d.mts +1 -1
  31. package/api/hook/list/list.mjs +69 -17
  32. package/api/init/init.doc.mjs +5 -0
  33. package/api/init/init.test.mjs +41 -1
  34. package/api/init/remove/remove.mjs +1 -1
  35. package/api/init/run/run.mjs +20 -10
  36. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  37. package/api/integration/add-contribution.mjs +18 -7
  38. package/api/integration/add-contribution.test.mjs +117 -3
  39. package/api/integration/add-theme.mjs +34 -64
  40. package/api/integration/add-theme.test.mjs +105 -21
  41. package/api/integration/authoring-checks.test.mjs +8 -4
  42. package/api/integration/integration-block-exports.test.mjs +10 -6
  43. package/api/integration/integrationAdd.doc.mjs +8 -4
  44. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  45. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  46. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  47. package/api/integration/integrationAddDoc.doc.mjs +1 -0
  48. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  49. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  50. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  51. package/api/integration/integrationDocConflicts.doc.mjs +1 -0
  52. package/api/integration/integrationPackCheck.doc.mjs +1 -0
  53. package/api/integration/integrationTemplateConflicts.doc.mjs +1 -0
  54. package/api/integration/pack-check.test.mjs +17 -47
  55. package/api/integration/summarizeIssues.doc.mjs +1 -0
  56. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  57. package/api/integration/validate-integration.mjs +52 -102
  58. package/api/integration/validate-integration.test.mjs +176 -23
  59. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  60. package/api/integration/validateIntegration.doc.mjs +2 -1
  61. package/api/json/assertResponse.doc.mjs +1 -0
  62. package/api/json/envelope-types.test.mjs +76 -0
  63. package/api/json/isError.doc.mjs +1 -0
  64. package/api/json/parseResponse.doc.mjs +3 -2
  65. package/api/layout/expand/expand.mjs +7 -5
  66. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  67. package/api/layout/grammar/grammar.mjs +2 -1
  68. package/api/layout/layoutCheck.doc.mjs +1 -0
  69. package/api/layout/layoutExpand.doc.mjs +2 -1
  70. package/api/layout/layoutGrammar.doc.mjs +1 -0
  71. package/api/search/search-return-type.test.mjs +54 -0
  72. package/api/search/search.d.mts +2 -9
  73. package/api/search/search.doc.mjs +6 -1
  74. package/api/search/search.mjs +26 -9
  75. package/api/search/search.test.mjs +34 -0
  76. package/api/swizzle/copy/copy.mjs +28 -11
  77. package/api/swizzle/swizzle.doc.mjs +2 -1
  78. package/api/template/copy/copy.mjs +17 -23
  79. package/api/template/copy/copy.test.mjs +17 -0
  80. package/api/template/template-suffix.test.mjs +41 -21
  81. package/api/template/template.doc.mjs +3 -1
  82. package/api/theme/_adapter.d.mts +2 -3
  83. package/api/theme/_adapter.mjs +4 -5
  84. package/api/theme/add/add.binary.test.mjs +84 -0
  85. package/api/theme/add/add.mjs +20 -3
  86. package/api/theme/add/add.staging.test.mjs +66 -0
  87. package/api/theme/add/add.test.mjs +14 -1
  88. package/api/theme/build/build.mjs +114 -37
  89. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  90. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  91. package/api/theme/build/font-warning.mjs +3 -3
  92. package/api/theme/build/font-warning.test.mjs +5 -2
  93. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  94. package/api/theme/integration-themes.test.mjs +39 -28
  95. package/api/theme/list/list.test.mjs +19 -20
  96. package/api/theme/listThemes.doc.mjs +6 -5
  97. package/api/theme/palette/generate/generate.mjs +7 -2
  98. package/api/theme/palette/generate/generate.test.mjs +96 -0
  99. package/api/theme/palette/generate/generator.mjs +8 -1
  100. package/api/theme/palette/generate/generator.test.mjs +10 -0
  101. package/api/theme/template/template.mjs +11 -2
  102. package/api/theme/template/template.test.mjs +15 -0
  103. package/api/theme/themeAdd.doc.mjs +4 -3
  104. package/api/theme/themeBuild.doc.mjs +8 -4
  105. package/api/theme/themeList.doc.mjs +6 -3
  106. package/api/theme/themeListAvailable.doc.mjs +5 -3
  107. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  108. package/api/theme/themeTargets.doc.mjs +1 -0
  109. package/api/theme/themeTemplate.doc.mjs +5 -1
  110. package/api/upgrade/_adapter.d.mts +12 -3
  111. package/api/upgrade/_adapter.mjs +108 -70
  112. package/api/upgrade/list/list.mjs +2 -1
  113. package/api/upgrade/list/list.test.mjs +73 -0
  114. package/api/upgrade/provider-agreement.test.mjs +152 -0
  115. package/api/upgrade/run/run.mjs +1 -0
  116. package/api/upgrade/status/status.mjs +2 -2
  117. package/api/upgrade/upgrade.doc.mjs +3 -1
  118. package/api/upgrade/upgrade.type.d.mts +4 -0
  119. package/api/upgrade/upgrade.type.mjs +1 -0
  120. package/assets/codemods/integration-discovery.mjs +8 -2
  121. package/assets/codemods/integration-discovery.test.mjs +15 -0
  122. package/assets/codemods/runner.mjs +115 -5
  123. package/assets/codemods/term-log.mjs +32 -8
  124. package/assets/codemods/term-log.test.mjs +19 -1
  125. package/assets/codemods/transform-prop.mjs +109 -0
  126. package/assets/codemods/transform-prop.test.mjs +95 -0
  127. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +216 -0
  128. package/assets/codemods/transforms/next/index.mjs +11 -1
  129. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  130. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  131. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  132. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  133. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  134. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  135. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  136. package/assets/docs/cli-integrations.doc.mjs +17 -30
  137. package/assets/docs/cli.doc.mjs +15 -0
  138. package/assets/docs/theme.doc.mjs +1 -1
  139. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  140. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  141. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  142. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  143. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  144. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  145. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  146. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  147. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  148. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  149. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  150. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  151. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  152. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  153. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  154. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  155. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  156. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  157. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  158. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  159. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  160. package/authoring/codemod/codemod.doc.mjs +1 -1
  161. package/authoring/config/config.doc.mjs +2 -2
  162. package/authoring/config/debug-composition.test.mjs +92 -0
  163. package/authoring/config/type.ts +15 -3
  164. package/authoring/debug/debug.doc.d.mts +11 -0
  165. package/authoring/debug/debug.doc.mjs +182 -0
  166. package/authoring/doctypes/base/graph-fields.doc.mjs +1 -1
  167. package/authoring/doctypes/command/command.doc.mjs +1 -1
  168. package/authoring/doctypes/command/type.ts +1 -1
  169. package/authoring/doctypes/component/type.ts +2 -2
  170. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  171. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  172. package/authoring/doctypes/enum/type.ts +1 -1
  173. package/authoring/doctypes/function/function.doc.mjs +1 -1
  174. package/authoring/doctypes/function/type.ts +1 -1
  175. package/authoring/doctypes/hook/type.ts +2 -2
  176. package/authoring/doctypes/load-contract.test.mjs +2 -1
  177. package/authoring/doctypes/parse.d.mts +4 -2
  178. package/authoring/doctypes/parse.mjs +7 -3
  179. package/authoring/doctypes/reference/reference.doc.mjs +1 -1
  180. package/authoring/doctypes/reference/type.ts +2 -2
  181. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  182. package/authoring/doctypes/schema/type.ts +1 -2
  183. package/authoring/doctypes/template/template.doc.mjs +3 -3
  184. package/authoring/doctypes/theme/parse.d.mts +35 -0
  185. package/authoring/doctypes/theme/parse.mjs +76 -0
  186. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  187. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  188. package/authoring/doctypes/theme/type.ts +42 -0
  189. package/authoring/doctypes/types.ts +2 -1
  190. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  191. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  192. package/authoring/index.d.mts +1 -0
  193. package/authoring/index.d.ts +6 -4
  194. package/authoring/index.mjs +2 -1
  195. package/authoring/integration/integration.doc.mjs +2 -2
  196. package/authoring/integration/type.ts +3 -9
  197. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  198. package/clients/cli/command-load-failure.test.mjs +83 -0
  199. package/clients/cli/commands/blog.doc.mjs +1 -1
  200. package/clients/cli/commands/blog.mjs +23 -8
  201. package/clients/cli/commands/blog.test.mjs +42 -1
  202. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  203. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  204. package/clients/cli/commands/build-theme.mjs +5 -5
  205. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  206. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  207. package/clients/cli/commands/build.doc.mjs +5 -2
  208. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  209. package/clients/cli/commands/build.mjs +32 -47
  210. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  211. package/clients/cli/commands/build.text-fields.test.mjs +40 -0
  212. package/clients/cli/commands/component/index.mjs +2 -7
  213. package/clients/cli/commands/component-package.test.mjs +46 -0
  214. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  215. package/clients/cli/commands/component.doc.mjs +1 -1
  216. package/clients/cli/commands/component.test.mjs +19 -0
  217. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  218. package/clients/cli/commands/discover.broken-integration.test.mjs +48 -0
  219. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  220. package/clients/cli/commands/discover.doc.mjs +5 -3
  221. package/clients/cli/commands/discover.mjs +3 -3
  222. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  223. package/clients/cli/commands/docs.doc.mjs +1 -1
  224. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  225. package/clients/cli/commands/doctor-integration-docs.doc.mjs +1 -1
  226. package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -1
  227. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  228. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  229. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  230. package/clients/cli/commands/doctor-integration.test.mjs +15 -7
  231. package/clients/cli/commands/doctor.doc.mjs +1 -1
  232. package/clients/cli/commands/doctor.mjs +6 -16
  233. package/clients/cli/commands/doctor.test.mjs +42 -0
  234. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  235. package/clients/cli/commands/gap-report.test.mjs +72 -0
  236. package/clients/cli/commands/hook/index.mjs +7 -17
  237. package/clients/cli/commands/hook.doc.mjs +1 -1
  238. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  239. package/clients/cli/commands/init.doc.mjs +20 -9
  240. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  241. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  242. package/clients/cli/commands/integration-add.doc.mjs +22 -6
  243. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  244. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  245. package/clients/cli/commands/integration.doc.mjs +1 -1
  246. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  247. package/clients/cli/commands/json-contract.test.mjs +33 -0
  248. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  249. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  250. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  251. package/clients/cli/commands/layout.doc.mjs +3 -3
  252. package/clients/cli/commands/layout.mjs +21 -9
  253. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  254. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  255. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  256. package/clients/cli/commands/manifest.doc.mjs +1 -1
  257. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  258. package/clients/cli/commands/search.doc.mjs +7 -4
  259. package/clients/cli/commands/search.mjs +17 -7
  260. package/clients/cli/commands/search.test.mjs +75 -0
  261. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  262. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  263. package/clients/cli/commands/template.doc.mjs +29 -7
  264. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  265. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  266. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  267. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  268. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  269. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
  270. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  271. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  272. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  273. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  274. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  275. package/clients/cli/commands/theme.doc.mjs +1 -1
  276. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  277. package/clients/cli/commands/upgrade.doc.mjs +18 -7
  278. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  279. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  280. package/clients/cli/index.mjs +13 -30
  281. package/clients/cli/latest-version-env.test.mjs +50 -0
  282. package/clients/cli/lib/cli-error.test.mjs +7 -0
  283. package/clients/cli/lib/component-format.mjs +9 -9
  284. package/clients/cli/lib/component-format.test.mjs +1 -1
  285. package/clients/cli/lib/define-command.mjs +32 -6
  286. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  287. package/clients/cli/lib/exit-codes.test.mjs +97 -0
  288. package/clients/cli/lib/hook-format.mjs +19 -10
  289. package/clients/cli/lib/json-shim.mjs +38 -2
  290. package/clients/cli/lib/json-shim.test.mjs +83 -0
  291. package/clients/cli/lib/manifest.d.ts +2 -0
  292. package/clients/cli/lib/manifest.mjs +22 -0
  293. package/clients/cli/lib/manifest.test.mjs +17 -0
  294. package/foundation/agent-docs/agent-docs.d.mts +4 -0
  295. package/foundation/agent-docs/agent-docs.mjs +69 -3
  296. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  297. package/foundation/config/integration-debug.test.mjs +28 -3
  298. package/foundation/config/project-themes.test.mjs +11 -19
  299. package/foundation/config/project.d.mts +8 -0
  300. package/foundation/config/project.mjs +173 -30
  301. package/foundation/config/project.test.mjs +129 -16
  302. package/foundation/discovery/authoring-self-docs.d.mts +6 -0
  303. package/foundation/discovery/authoring-self-docs.mjs +17 -7
  304. package/foundation/discovery/authoring-surface.d.mts +74 -0
  305. package/foundation/discovery/authoring-surface.mjs +525 -0
  306. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  307. package/foundation/discovery/cli-self-docs.d.mts +113 -0
  308. package/foundation/discovery/cli-self-docs.mjs +514 -0
  309. package/foundation/discovery/cli-self-docs.test.mjs +437 -0
  310. package/foundation/discovery/component-loader.d.mts +35 -38
  311. package/foundation/discovery/component-loader.mjs +53 -222
  312. package/foundation/discovery/docs-discovery.d.mts +3 -2
  313. package/foundation/discovery/docs-discovery.mjs +8 -12
  314. package/foundation/discovery/docs-discovery.test.mjs +8 -5
  315. package/foundation/discovery/template-adapter.d.mts +21 -5
  316. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  317. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  318. package/foundation/discovery/template-adapter.mjs +319 -65
  319. package/foundation/discovery/template-adapter.test.mjs +15 -0
  320. package/foundation/discovery/theme-discovery.d.mts +67 -7
  321. package/foundation/discovery/theme-discovery.mjs +916 -186
  322. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  323. package/foundation/doc-compiler/bundle.d.mts +47 -0
  324. package/foundation/doc-compiler/bundle.mjs +218 -0
  325. package/foundation/doc-compiler/bundle.test.mjs +255 -0
  326. package/foundation/doc-compiler/compile.d.mts +200 -0
  327. package/foundation/doc-compiler/compile.mjs +254 -5
  328. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  329. package/foundation/doc-compiler/diagnostics.mjs +277 -0
  330. package/foundation/doc-compiler/doc-compiler.test.mjs +28 -1
  331. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  332. package/foundation/doc-compiler/import.d.mts +24 -0
  333. package/foundation/doc-compiler/import.mjs +59 -0
  334. package/foundation/doc-compiler/inputs.d.mts +102 -0
  335. package/foundation/doc-compiler/inputs.mjs +286 -0
  336. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  337. package/foundation/doc-compiler/ir.d.mts +13 -0
  338. package/foundation/doc-compiler/ir.mjs +189 -12
  339. package/foundation/doc-compiler/lower-doc.test.mjs +492 -0
  340. package/foundation/doc-compiler/overlays.d.mts +37 -0
  341. package/foundation/doc-compiler/overlays.mjs +206 -0
  342. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  343. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  344. package/foundation/doc-compiler/read.d.mts +126 -0
  345. package/foundation/doc-compiler/read.mjs +320 -0
  346. package/foundation/doc-compiler/read.test.mjs +313 -0
  347. package/foundation/doc-compiler/source.d.mts +33 -0
  348. package/foundation/doc-compiler/source.mjs +128 -0
  349. package/foundation/fs/module-loader.d.mts +1 -0
  350. package/foundation/fs/module-loader.mjs +50 -1
  351. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  352. package/foundation/fs/path-safety.d.mts +3 -2
  353. package/foundation/fs/path-safety.mjs +49 -19
  354. package/foundation/fs/path-safety.test.mjs +50 -0
  355. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  356. package/foundation/integrations/autolink.d.mts +58 -1
  357. package/foundation/integrations/autolink.mjs +143 -52
  358. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  359. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  360. package/foundation/integrations/contribution-inventory.d.mts +1 -1
  361. package/foundation/integrations/contribution-inventory.mjs +17 -20
  362. package/foundation/integrations/contribution-inventory.test.mjs +67 -27
  363. package/foundation/integrations/integrations.d.mts +3 -0
  364. package/foundation/integrations/integrations.mjs +11 -97
  365. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  366. package/foundation/integrations/provider-resolution.d.mts +152 -0
  367. package/foundation/integrations/provider-resolution.mjs +576 -0
  368. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  369. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  370. package/foundation/integrations/theme-descriptor.mjs +44 -0
  371. package/foundation/integrations/validate-contributions.mjs +104 -10
  372. package/foundation/response/base.d.ts +8 -4
  373. package/foundation/response/error-codes.doc.mjs +3 -4
  374. package/foundation/response/error-codes.mjs +2 -2
  375. package/foundation/response/error-codes.test.mjs +83 -0
  376. package/foundation/response/json-contract.test.mjs +11 -0
  377. package/foundation/response/json.d.mts +4 -2
  378. package/foundation/response/json.mjs +8 -10
  379. package/foundation/response/response-types.doc.mjs +11 -11
  380. package/foundation/response/response-types.doc.test.mjs +158 -0
  381. package/foundation/response/response.doc.mjs +1 -1
  382. package/foundation/text/string-utils.mjs +22 -10
  383. package/foundation/xle/expand.d.mts +2 -0
  384. package/foundation/xle/expand.mjs +3 -2
  385. package/foundation/xle/expand.test.mjs +54 -0
  386. package/package.json +9 -9
  387. package/assets/templates/themes/manifest.json +0 -95
  388. package/clients/cli/lib/update-check.mjs +0 -83
  389. package/clients/cli/lib/update-check.test.mjs +0 -137
  390. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -12,6 +12,7 @@ export const doc = {
12
12
  type: 'function',
13
13
  kind: 'api',
14
14
  name: 'component',
15
+ namespace: 'cli/api',
15
16
  displayName: 'component()',
16
17
  summary:
17
18
  'Resolve a component by name, or list the catalog, with optional focused slices (props, source, showcase, blocks).',
@@ -91,7 +92,8 @@ export const doc = {
91
92
  {
92
93
  name: 'options.lang',
93
94
  type: 'string',
94
- description: 'Language code for localized doc content.',
95
+ description:
96
+ "Language code for localized doc content: 'en', 'zh', or 'dense'.",
95
97
  },
96
98
  {
97
99
  name: 'options.zh',
@@ -108,12 +110,12 @@ export const doc = {
108
110
  {
109
111
  type: 'component.list',
110
112
  description:
111
- "The catalog grouped by category. data.detail is the level ('names' | 'compact' | 'full') and data.components is the grouped map: names entries with name, package, and an optional canonical import for integrations; brief entries; or full ComponentDoc entries.",
113
+ "The catalog grouped by category. data.detail is the level ('names' | 'compact' | 'full') and data.components is the grouped map: names entries with name, package, and an optional canonical import for integration and legacy package components; brief entries; or full ComponentDoc entries.",
112
114
  },
113
115
  {
114
116
  type: 'component.detail',
115
117
  description:
116
- "One component's authored ComponentDoc plus ownership metadata (owner package, import specifier, whether source is available).",
118
+ "One component's authored ComponentDoc plus ownership metadata (owner package, import specifier, whether source is available). When the name is a sub-component documented in a parent's doc, the payload is scoped to it and parentDoc names that parent.",
117
119
  },
118
120
  {
119
121
  type: 'component.detail.props',
@@ -135,6 +137,14 @@ export const doc = {
135
137
  },
136
138
  ],
137
139
  throws: [
140
+ {
141
+ code: 'ERR_INVALID_DETAIL',
142
+ when: "options.detail is not 'full', 'compact', or 'brief'",
143
+ },
144
+ {
145
+ code: 'ERR_INVALID_LANG',
146
+ when: "options.lang is set to anything other than 'en', 'zh', or 'dense'",
147
+ },
138
148
  {
139
149
  code: 'ERR_CORE_NOT_FOUND',
140
150
  when: '@astryxdesign/core cannot be resolved from cwd',
@@ -34,6 +34,11 @@ import {componentDetailSource} from './detail/source/source.mjs';
34
34
  import {componentDetailShowcase} from './detail/showcase/showcase.mjs';
35
35
  import {componentDetailBlocks} from './detail/blocks/blocks.mjs';
36
36
 
37
+ /** @type {ReadonlyArray<string>} */
38
+ const DETAIL_LEVELS = ['full', 'compact', 'brief'];
39
+ /** @type {ReadonlyArray<string>} */
40
+ const LANGS = ['en', 'zh', 'dense'];
41
+
37
42
  /**
38
43
  * @param {string} [name]
39
44
  * @param {object} [options]
@@ -81,6 +86,23 @@ export async function component(name, options = {}) {
81
86
  const isListView = list || category != null || !name;
82
87
  const detail = detailOption ?? (isListView ? 'brief' : 'full');
83
88
 
89
+ // Same accepted values and codes as the CLI's --detail and --lang, checked
90
+ // first as the CLI parser does.
91
+ if (!DETAIL_LEVELS.includes(detail)) {
92
+ throw new AstryxError(
93
+ `Invalid detail "${String(detail)}". Valid levels: ${DETAIL_LEVELS.join(', ')}`,
94
+ undefined,
95
+ ERROR_CODES.ERR_INVALID_DETAIL,
96
+ );
97
+ }
98
+ if (lang != null && !LANGS.includes(lang)) {
99
+ throw new AstryxError(
100
+ `Invalid lang "${String(lang)}". Valid values: ${LANGS.join(', ')}`,
101
+ undefined,
102
+ ERROR_CODES.ERR_INVALID_LANG,
103
+ );
104
+ }
105
+
84
106
  const coreDir = requireCoreDir(cwd);
85
107
 
86
108
  // A public API caller could pass a non-string category; the list leaf does
@@ -143,7 +165,7 @@ export async function component(name, options = {}) {
143
165
  : componentDetailShowcase(dirName, {cwd, name, resolve: false});
144
166
  }
145
167
  if (blocks) {
146
- return componentDetailBlocks(dirName);
168
+ return componentDetailBlocks(dirName, cwd);
147
169
  }
148
170
  const docs = await loadComponentDoc(owner.docPath, docOpts);
149
171
  if (props) return componentDetailProps(docs);
@@ -156,6 +178,13 @@ export async function component(name, options = {}) {
156
178
  }
157
179
  const extDocPath = resolveLegacyExternalDoc(scoped.ext, dirName);
158
180
  if (extDocPath) {
181
+ // Legacy packages ship docs, never source.
182
+ if (source) {
183
+ return componentDetailSource(dirName, null, {name, notFoundInPackage: packageScope});
184
+ }
185
+ if (blocks) {
186
+ return componentDetailBlocks(dirName, cwd);
187
+ }
159
188
  const docs = await loadComponentDoc(extDocPath, docOpts);
160
189
  if (props) return componentDetailProps(docs);
161
190
  return componentDetail(docs, {package: scoped.ext.name, sourcePath: null}, dirName, coreDir);
@@ -195,7 +224,7 @@ export async function component(name, options = {}) {
195
224
 
196
225
  // ── Blocks mode ──────────────────────────────────────────────
197
226
  if (blocks) {
198
- return componentDetailBlocks(dirName);
227
+ return componentDetailBlocks(dirName, cwd);
199
228
  }
200
229
 
201
230
  // ── Sub-component scoping ────────────────────────────────────
@@ -14,6 +14,7 @@ import * as path from 'node:path';
14
14
  import {fileURLToPath} from 'node:url';
15
15
  import {component} from './component.mjs';
16
16
  import {AstryxError} from '../error.mjs';
17
+ import {runCli} from '../../test-utils/run-cli.mjs';
17
18
 
18
19
  // api/component/ -> up 4 = repo root (has packages/core, which findCoreDir walks to).
19
20
  const REPO = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../..');
@@ -161,3 +162,40 @@ describe('component dispatcher — category guard', () => {
161
162
  }
162
163
  }, SLOW);
163
164
  });
165
+
166
+ describe('component dispatcher — detail and lang guards', () => {
167
+ // `detail` and `lang` are the same controls as the CLI's --detail and --lang:
168
+ // same accepted values, same error codes.
169
+ it('rejects a detail level the CLI rejects, with the same code', async () => {
170
+ const cliRun = await runCli(['--json', 'component', '--list', '--detail', 'bogus'], cwd);
171
+ expect(cliRun.code).toBe(1);
172
+ expect(JSON.parse(cliRun.stdout).code).toBe('ERR_INVALID_DETAIL');
173
+
174
+ const bogus = /** @type {any} */ ('bogus');
175
+ for (const call of [
176
+ () => component(undefined, {cwd, list: true, detail: bogus}),
177
+ () => component('Button', {cwd, detail: bogus}),
178
+ ]) {
179
+ const err = await call().catch(e => e);
180
+ expect(err).toBeInstanceOf(AstryxError);
181
+ expect(err.code).toBe('ERR_INVALID_DETAIL');
182
+ }
183
+ }, SLOW);
184
+
185
+ it('rejects a lang the CLI rejects, with the same code', async () => {
186
+ const cliRun = await runCli(['--json', 'component', 'Button', '--lang', 'fr'], cwd);
187
+ expect(cliRun.code).toBe(1);
188
+ expect(JSON.parse(cliRun.stdout).code).toBe('ERR_INVALID_LANG');
189
+
190
+ for (const call of [
191
+ () => component('Button', {cwd, lang: 'fr'}),
192
+ () => component(undefined, {cwd, list: true, detail: 'compact', lang: 'fr'}),
193
+ ]) {
194
+ const err = await call().catch(e => e);
195
+ expect(err).toBeInstanceOf(AstryxError);
196
+ expect(err.code).toBe('ERR_INVALID_LANG');
197
+ }
198
+ const zh = await component('Button', {cwd, lang: 'zh'});
199
+ expect(zh.type).toBe('component.detail');
200
+ }, SLOW);
201
+ });
@@ -31,9 +31,10 @@ export type ComponentListData = ({
31
31
  /**
32
32
  * A single entry in a `component.list` group at `detail: 'names'`. Pre-1.0 the
33
33
  * list moved from bare strings to package-qualified objects so consumers can
34
- * disambiguate ownership (core vs. an integration package). Integration entries
35
- * carry `import` — the package-authored specifier; core entries omit it (the
36
- * specifier is derived from the component name by the renderer).
34
+ * disambiguate ownership (core vs. an integration package). Integration and
35
+ * legacy `astryx.docs` package entries carry `import` — the same specifier their
36
+ * `component.detail` reports; core entries omit it (the specifier is derived
37
+ * from the component name by the renderer).
37
38
  */
38
39
  export type ComponentListEntry = {
39
40
  name: string;
@@ -42,7 +43,7 @@ export type ComponentListEntry = {
42
43
  */
43
44
  package: string;
44
45
  /**
45
- * - Import specifier; present for integration components, absent for core.
46
+ * - Import specifier; present for integration and legacy package components, absent for core.
46
47
  */
47
48
  import?: string | undefined;
48
49
  };
@@ -59,7 +60,17 @@ export type ComponentBriefEntry = {
59
60
  */
60
61
  export type ComponentDetailResponse = {
61
62
  type: "component.detail";
62
- data: import("@astryxdesign/cli/authoring").ComponentDoc & ComponentOwnership;
63
+ data: import("@astryxdesign/cli/authoring").ComponentDoc & ComponentOwnership & ComponentDetailScope;
64
+ };
65
+ /**
66
+ * Present only when the requested name is a sub-component documented inside a
67
+ * parent's doc (e.g. `HStack` in the `Stack` doc); the payload is scoped to it.
68
+ */
69
+ export type ComponentDetailScope = {
70
+ /**
71
+ * - Name of the parent doc the payload was scoped from, e.g. 'Stack'.
72
+ */
73
+ parentDoc?: string | undefined;
63
74
  };
64
75
  /**
65
76
  * Ownership metadata attached to every `component.detail` payload. Exposes the
@@ -52,13 +52,14 @@
52
52
  /**
53
53
  * A single entry in a `component.list` group at `detail: 'names'`. Pre-1.0 the
54
54
  * list moved from bare strings to package-qualified objects so consumers can
55
- * disambiguate ownership (core vs. an integration package). Integration entries
56
- * carry `import` — the package-authored specifier; core entries omit it (the
57
- * specifier is derived from the component name by the renderer).
55
+ * disambiguate ownership (core vs. an integration package). Integration and
56
+ * legacy `astryx.docs` package entries carry `import` — the same specifier their
57
+ * `component.detail` reports; core entries omit it (the specifier is derived
58
+ * from the component name by the renderer).
58
59
  * @typedef {object} ComponentListEntry
59
60
  * @property {string} name
60
61
  * @property {string} package - Owner package, e.g. '@astryxdesign/core' or '@acme/astryx-meta'.
61
- * @property {string} [import] - Import specifier; present for integration components, absent for core.
62
+ * @property {string} [import] - Import specifier; present for integration and legacy package components, absent for core.
62
63
  */
63
64
 
64
65
  /**
@@ -73,7 +74,14 @@
73
74
  * astryx --json component <name>
74
75
  * @typedef {object} ComponentDetailResponse
75
76
  * @property {'component.detail'} type
76
- * @property {import('@astryxdesign/cli/authoring').ComponentDoc & ComponentOwnership} data
77
+ * @property {import('@astryxdesign/cli/authoring').ComponentDoc & ComponentOwnership & ComponentDetailScope} data
78
+ */
79
+
80
+ /**
81
+ * Present only when the requested name is a sub-component documented inside a
82
+ * parent's doc (e.g. `HStack` in the `Stack` doc); the payload is scoped to it.
83
+ * @typedef {object} ComponentDetailScope
84
+ * @property {string} [parentDoc] - Name of the parent doc the payload was scoped from, e.g. 'Stack'.
77
85
  */
78
86
 
79
87
  /**
@@ -6,6 +6,7 @@
6
6
  * envelope, splitting them into the hero showcase, component-specific examples,
7
7
  * and broader related blocks.
8
8
  * @param {string} componentName
9
+ * @param {string} cwd - project to discover blocks from; never the process cwd
9
10
  * @returns {Promise<import('../../component.type.mjs').ComponentDetailBlocksResponse>}
10
11
  */
11
- export function componentDetailBlocks(componentName: string): Promise<import("../../component.type.mjs").ComponentDetailBlocksResponse>;
12
+ export function componentDetailBlocks(componentName: string, cwd: string): Promise<import("../../component.type.mjs").ComponentDetailBlocksResponse>;
@@ -3,7 +3,7 @@
3
3
  /**
4
4
  * @file `component.detail.blocks` leaf — a component's example/related blocks.
5
5
  *
6
- * @input a component name
6
+ * @input a component name + the project cwd
7
7
  * @output the `component.detail.blocks` envelope (showcase, examples, related)
8
8
  * @position api/component/detail/blocks (projection leaf; routed by component.mjs)
9
9
  */
@@ -16,10 +16,11 @@ import {findRelatedBlocks} from '../../../template/template.mjs';
16
16
  * envelope, splitting them into the hero showcase, component-specific examples,
17
17
  * and broader related blocks.
18
18
  * @param {string} componentName
19
+ * @param {string} cwd - project to discover blocks from; never the process cwd
19
20
  * @returns {Promise<import('../../component.type.mjs').ComponentDetailBlocksResponse>}
20
21
  */
21
- export async function componentDetailBlocks(componentName) {
22
- const allBlocks = await findRelatedBlocks(componentName);
22
+ export async function componentDetailBlocks(componentName, cwd) {
23
+ const allBlocks = await findRelatedBlocks(componentName, cwd);
23
24
  const toEntry = (/** @type {any} */ b) => ({
24
25
  name: b.dirName,
25
26
  displayName: b.name,
@@ -1,11 +1,6 @@
1
1
  // @generated by scripts/sync-api-types.mjs from the JSDoc in api/**/*.mjs.
2
2
  // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
3
 
4
- /**
5
- * @typedef {import('../component.type.mjs').ComponentListResponse} ComponentListResponse
6
- * @typedef {import('../component.type.mjs').ComponentListEntry} ComponentListEntry
7
- * @typedef {import('../component.type.mjs').ComponentBriefEntry} ComponentBriefEntry
8
- */
9
4
  /**
10
5
  * Build the `component.list` envelope. The list taxonomy is collapsed: all
11
6
  * three detail levels emit ONE `component.list` type; the depth rides in
@@ -17,13 +17,14 @@ import {
17
17
  discoverExternalComponentsGrouped,
18
18
  discoverIntegrationComponents,
19
19
  findComponentReadme,
20
+ findExternalComponentDoc,
20
21
  resolveImportPath,
21
22
  resolveIntegrationImportPath,
22
23
  } from '../../../foundation/discovery/component-discovery.mjs';
23
24
  import {discoverExternalPackages} from '../../../foundation/fs/paths.mjs';
24
25
  import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
25
26
  import {AstryxError} from '../../error.mjs';
26
- import {loadComponentDoc, loadIntegrationsSafely} from '../_adapter.mjs';
27
+ import {loadComponentDoc, loadIntegrationsSafely, withOwnership} from '../_adapter.mjs';
27
28
 
28
29
  /**
29
30
  * @typedef {import('../component.type.mjs').ComponentListResponse} ComponentListResponse
@@ -31,6 +32,29 @@ import {loadComponentDoc, loadIntegrationsSafely} from '../_adapter.mjs';
31
32
  * @typedef {import('../component.type.mjs').ComponentBriefEntry} ComponentBriefEntry
32
33
  */
33
34
 
35
+ /**
36
+ * The import a legacy `pkg.astryx.docs` component's detail reports, derived the
37
+ * same way (`withOwnership`) so list and detail agree.
38
+ * @param {{name: string, docsDir: string}} ext
39
+ * @param {string} name
40
+ * @param {string} coreDir
41
+ * @param {{zh: boolean, lang: string|null}} docOpts
42
+ * @returns {Promise<string>}
43
+ */
44
+ async function legacyImport(ext, name, coreDir, docOpts) {
45
+ const docPath = findExternalComponentDoc(ext.docsDir, name);
46
+ /** @type {import('../_adapter.mjs').LoadedComponentDoc} */
47
+ let docs = {};
48
+ if (docPath && docPath.endsWith('.doc.mjs')) {
49
+ try {
50
+ docs = await loadComponentDoc(docPath, docOpts);
51
+ } catch {
52
+ // Keep list resilient; validation owns malformed docs.
53
+ }
54
+ }
55
+ return withOwnership(docs, {package: ext.name, sourcePath: null}, name, coreDir).import;
56
+ }
57
+
34
58
  /**
35
59
  * Build the `component.list` envelope. The list taxonomy is collapsed: all
36
60
  * three detail levels emit ONE `component.list` type; the depth rides in
@@ -267,20 +291,24 @@ export async function componentList(
267
291
  k => grouped[k].length > 1 || grouped[k][0] !== k,
268
292
  );
269
293
 
270
- if (hasGroups) {
271
- for (const [group, members] of Object.entries(grouped)) {
272
- listData[`${group} (${ext.name})`] = members.map(n => ({
294
+ /** @param {string[]} names */
295
+ const entriesFor = names =>
296
+ Promise.all(
297
+ names.map(async n => ({
273
298
  name: n,
274
299
  package: ext.name,
275
- }));
300
+ import: await legacyImport(ext, n, coreDir, {zh, lang}),
301
+ })),
302
+ );
303
+
304
+ if (hasGroups) {
305
+ for (const [group, members] of Object.entries(grouped)) {
306
+ listData[`${group} (${ext.name})`] = await entriesFor(members);
276
307
  }
277
308
  } else {
278
309
  const allComps = Object.values(grouped).flat().sort();
279
310
  if (allComps.length > 0) {
280
- listData[`${ext.category} (${ext.name})`] = allComps.map(n => ({
281
- name: n,
282
- package: ext.name,
283
- }));
311
+ listData[`${ext.category} (${ext.name})`] = await entriesFor(allComps);
284
312
  }
285
313
  }
286
314
  }
@@ -11,6 +11,7 @@ export const doc = {
11
11
  type: 'function',
12
12
  kind: 'api',
13
13
  name: 'discover',
14
+ namespace: 'cli/api',
14
15
  displayName: 'discover()',
15
16
  summary: 'Browse and search components from configured external packages.',
16
17
  description:
@@ -41,7 +42,7 @@ export const doc = {
41
42
  name: 'options.components',
42
43
  type: 'boolean',
43
44
  description:
44
- 'List components only. A CLI display flag consumed by the renderer; the programmatic response shape is unchanged.',
45
+ 'In the CLI package list, print every component of each package instead of the first 10. A display flag for the CLI renderer; the programmatic response is unchanged.',
45
46
  },
46
47
  {
47
48
  name: 'options.lang',
@@ -15,12 +15,6 @@
15
15
  * @returns {Promise<DocsCatalog>}
16
16
  */
17
17
  export function loadDocsCatalog(cwd?: string): Promise<DocsCatalog>;
18
- /**
19
- * The overlay languages a topic ships for its own file or any extension.
20
- * @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
21
- * @returns {string[]}
22
- */
23
- export function overlayLanguages(entry: import("../../foundation/discovery/docs-discovery.mjs").DocsTopicEntry): string[];
24
18
  /**
25
19
  * One topic, lowered for `lang`: overlaid, extensions merged, keys stamped.
26
20
  * Memoized per catalog, so a read that references a topic twice loads it once.
@@ -76,6 +70,7 @@ export function resolveTopicDocs(topic: string, options?: {
76
70
  node: import("../../foundation/doc-compiler/compile.mjs").CompiledReferenceNode;
77
71
  lang: string | null;
78
72
  }>;
79
- /** The localized overlays a docs read can apply. */
80
- export const OVERLAY_LANGUAGES: string[];
81
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 };
@@ -10,24 +10,29 @@
10
10
  * @output Catalog access, the compiler input for a topic, and the compiled
11
11
  * node for it: lowered (overlaid, extensions merged, keys stamped) or linked
12
12
  * (token references resolved too), memoized per catalog.
13
- * @position Sits beside docs.mjs (api/docs/). Loads authored files and hands
14
- * them to foundation/doc-compiler, so no leaf, doctor check or search loads,
15
- * merges, or resolves docs on its own. Discovery itself lives in
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
16
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';
23
21
  import {DocsCatalog} from '../../foundation/discovery/docs-discovery.mjs';
24
22
  import {
25
23
  linkReferenceTopic,
26
24
  lowerReferenceTopic,
27
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';
28
32
  import {AstryxError} from '../error.mjs';
29
33
  import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
30
- import {parseDoc} from '../../authoring/doctypes/parse.mjs';
34
+
35
+ export {OVERLAY_LANGUAGES, overlayLanguages};
31
36
 
32
37
  /**
33
38
  * The project's topics: the built-in ones plus whatever the configured
@@ -51,34 +56,6 @@ export async function loadDocsCatalog(cwd = process.cwd()) {
51
56
  }
52
57
  }
53
58
 
54
- /** The localized overlays a docs read can apply. */
55
- export const OVERLAY_LANGUAGES = ['zh', 'dense'];
56
-
57
- /**
58
- * Where the `lang` overlay of a doc file lives: `{topic}.doc.{lang}.mjs`.
59
- * @param {string} docPath
60
- * @param {string} lang
61
- * @returns {string}
62
- */
63
- function overlayPath(docPath, lang) {
64
- return path.join(
65
- path.dirname(docPath),
66
- `${path.basename(docPath, '.doc.mjs')}.doc.${lang}.mjs`,
67
- );
68
- }
69
-
70
- /**
71
- * The overlay languages a topic ships for its own file or any extension.
72
- * @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
73
- * @returns {string[]}
74
- */
75
- export function overlayLanguages(entry) {
76
- const files = [entry.path, ...entry.extensions.map(ext => ext.path)];
77
- return OVERLAY_LANGUAGES.filter(lang =>
78
- files.some(file => fs.existsSync(overlayPath(file, lang))),
79
- );
80
- }
81
-
82
59
  /**
83
60
  * The overlay a read applies: none for the authored language.
84
61
  * @param {string | null | undefined} lang
@@ -88,61 +65,6 @@ function overlayLanguage(lang) {
88
65
  return lang && lang !== 'en' ? lang : null;
89
66
  }
90
67
 
91
- /**
92
- * Load one authored file and the overlay for `lang`. A failure is recorded on
93
- * the result, not thrown, so the compiler reports it in reading order.
94
- * @param {string} docPath
95
- * @param {string | null} lang
96
- * @returns {Promise<import('../../foundation/doc-compiler/compile.mjs').AuthoredFile>}
97
- */
98
- async function loadAuthoredFile(docPath, lang) {
99
- const file = path.basename(docPath);
100
- let doc;
101
- try {
102
- const mod = await import(pathToFileURL(docPath).href);
103
- doc = parseDoc(mod.docs ?? mod.default, file);
104
- } catch (error) {
105
- return {file, error};
106
- }
107
- if (!lang) return {file, doc};
108
- const translationPath = overlayPath(docPath, lang);
109
- if (!fs.existsSync(translationPath)) return {file, doc};
110
- try {
111
- const translationMod = await import(pathToFileURL(translationPath).href);
112
- return {
113
- file,
114
- doc,
115
- overlay: translationMod.docsZh || translationMod.docsDense || null,
116
- };
117
- } catch (overlayError) {
118
- return {file, doc, overlayError};
119
- }
120
- }
121
-
122
- /**
123
- * Everything the compiler needs for one topic, read from disk.
124
- * @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
125
- * @param {string | null} lang
126
- * @returns {Promise<import('../../foundation/doc-compiler/compile.mjs').ReferenceTopicInput>}
127
- */
128
- async function loadCompilerInput(entry, lang) {
129
- const extensions = [];
130
- for (const extension of entry.extensions) {
131
- extensions.push({
132
- ...(await loadAuthoredFile(extension.path, lang)),
133
- provider: extension.package,
134
- });
135
- }
136
- return {
137
- id: entry.name,
138
- provider: entry.package,
139
- replaces: entry.replaces ?? null,
140
- lang,
141
- base: await loadAuthoredFile(entry.path, lang),
142
- extensions,
143
- };
144
- }
145
-
146
68
  /** @type {WeakMap<DocsCatalog, Map<string, Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode>>>} */
147
69
  const loweredByCatalog = new WeakMap();
148
70
 
@@ -166,7 +88,7 @@ export function lowerTopic(catalog, entry, lang = null) {
166
88
  const key = `${entry.name.toLowerCase()}\u0000${overlay ?? ''}`;
167
89
  let lowered = cache.get(key);
168
90
  if (!lowered) {
169
- lowered = loadCompilerInput(entry, overlay).then(input =>
91
+ lowered = loadTopicInput(entry, overlay).then(input =>
170
92
  deepFreeze(lowerReferenceTopic(input)),
171
93
  );
172
94
  cache.set(key, lowered);
@@ -174,20 +96,6 @@ export function lowerTopic(catalog, entry, lang = null) {
174
96
  return lowered;
175
97
  }
176
98
 
177
- /**
178
- * Freeze a value and everything in it.
179
- * @template T
180
- * @param {T} value
181
- * @returns {T}
182
- */
183
- function deepFreeze(value) {
184
- if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {
185
- Object.freeze(value);
186
- for (const child of Object.values(value)) deepFreeze(child);
187
- }
188
- return value;
189
- }
190
-
191
99
  /**
192
100
  * How a token reference finds its target: the topic it names in `catalog`,
193
101
  * lowered for the same language.
@@ -11,6 +11,7 @@ export const doc = {
11
11
  type: 'function',
12
12
  kind: 'api',
13
13
  name: 'docs',
14
+ namespace: 'cli/api',
14
15
  displayName: 'docs()',
15
16
  summary:
16
17
  'Read the reference docs: list every topic, one topic\'s sections, one section, or a whole topic.',
@@ -14,7 +14,7 @@
14
14
  * @position Leaf under api/docs. Sibling of detail; both share _adapter.mjs.
15
15
  */
16
16
 
17
- import {pathToFileURL} from 'node:url';
17
+ import {loadTopicFile} from '../../../foundation/doc-compiler/read.mjs';
18
18
  import {loadDocsCatalog} from '../_adapter.mjs';
19
19
 
20
20
  /**
@@ -29,12 +29,8 @@ export async function list({cwd} = {}) {
29
29
  for (const entry of catalog.entries()) {
30
30
  let description = entry.description ?? '';
31
31
  if (entry.description == null) {
32
- try {
33
- const mod = await import(pathToFileURL(entry.path).href);
34
- description = (mod.docs ?? mod.default)?.description ?? '';
35
- } catch {
36
- description = '';
37
- }
32
+ const file = await loadTopicFile(entry.path, null);
33
+ description = file.doc?.description ?? '';
38
34
  }
39
35
  /** @type {import('../docs.type.mjs').DocsListEntry} */
40
36
  const listed = {
@@ -100,12 +100,34 @@ export function checkPackageManager(ctx: DoctorContext): DoctorCheck;
100
100
  export function checkProviderIdentity(ctx: DoctorContext): DoctorCheck;
101
101
  /**
102
102
  * Every authoring self-doc is reachable from `astryx docs authoring`, loads,
103
- * and fits in one read. The audit is imported here, inside the try, so a
104
- * malformed self-doc is reported rather than taking Doctor down.
103
+ * and fits in one read, and every type `@astryxdesign/cli/authoring` exports
104
+ * has its doc there: the self-doc beside the module that declares it. The
105
+ * audits are imported here, inside the try, so a malformed self-doc is
106
+ * reported rather than taking Doctor down.
105
107
  * @param {DoctorContext} [_ctx]
108
+ * @param {{root?: string, sources?: string[], topicKeys?: Set<string> | null}} [options]
109
+ * Another authoring tree, list, or topic index to audit (for tests).
106
110
  * @returns {Promise<DoctorCheck>}
107
111
  */
108
- export function checkAuthoringDocs(_ctx?: DoctorContext): Promise<DoctorCheck>;
112
+ export function checkAuthoringDocs(_ctx?: DoctorContext, options?: {
113
+ root?: string;
114
+ sources?: string[];
115
+ topicKeys?: Set<string> | null;
116
+ }): Promise<DoctorCheck>;
117
+ /**
118
+ * Every command, API function, schema, and enum doc the CLI ships declares a
119
+ * namespace, and the topic that namespace names reads it: `astryx docs cli`
120
+ * for `cli/commands` and `cli/api`, `astryx docs authoring` for `authoring`.
121
+ * @param {DoctorContext | Partial<DoctorContext>} _ctx
122
+ * @param {{root?: string, sources?: string[], authoringSources?: string[]}} [options]
123
+ * test seams: the CLI root, the docs to audit, and the authoring topic's list
124
+ * @returns {Promise<DoctorCheck>}
125
+ */
126
+ export function checkCliDocs(_ctx: DoctorContext | Partial<DoctorContext>, options?: {
127
+ root?: string;
128
+ sources?: string[];
129
+ authoringSources?: string[];
130
+ }): Promise<DoctorCheck>;
109
131
  /**
110
132
  * Every topic reads progressively, in every language it ships: it loads, its
111
133
  * section index and each of its sections fit in one read, and no contributed
@@ -11,6 +11,7 @@ export const doc = {
11
11
  type: 'function',
12
12
  kind: 'api',
13
13
  name: 'doctor',
14
+ namespace: 'cli/api',
14
15
  displayName: 'doctor()',
15
16
  summary: 'Read-only project + environment health check.',
16
17
  description: