@astryxdesign/cli 0.6.3-canary.98a2e4e → 0.6.3-canary.9dbb6c1

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 (466) 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 +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 +28 -30
  22. package/api/docs/_adapter.mjs +73 -135
  23. package/api/docs/compiled-topics.test.mjs +78 -0
  24. package/api/docs/detail/detail.d.mts +0 -15
  25. package/api/docs/detail/detail.mjs +14 -78
  26. package/api/docs/detail/section/section.mjs +22 -18
  27. package/api/docs/detail/section/section.test.mjs +4 -3
  28. package/api/docs/docs.doc.mjs +1 -0
  29. package/api/docs/docs.type.d.mts +4 -4
  30. package/api/docs/docs.type.mjs +10 -10
  31. package/api/docs/index/index.mjs +6 -5
  32. package/api/docs/list/list.mjs +3 -7
  33. package/api/doctor/doctor.d.mts +25 -3
  34. package/api/doctor/doctor.doc.mjs +1 -0
  35. package/api/doctor/doctor.mjs +186 -18
  36. package/api/doctor/doctor.test.mjs +326 -1
  37. package/api/gap-report/gap-report.doc.mjs +8 -4
  38. package/api/hook/_adapter.mjs +19 -5
  39. package/api/hook/hook.doc.mjs +1 -0
  40. package/api/hook/hook.type.d.mts +3 -3
  41. package/api/hook/hook.type.mjs +11 -11
  42. package/api/hook/list/list.d.mts +1 -1
  43. package/api/hook/list/list.mjs +69 -17
  44. package/api/init/init.doc.mjs +5 -0
  45. package/api/init/init.test.mjs +41 -1
  46. package/api/init/remove/remove.mjs +1 -1
  47. package/api/init/run/run.mjs +20 -10
  48. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  49. package/api/integration/add-contribution.mjs +23 -10
  50. package/api/integration/add-contribution.test.mjs +121 -7
  51. package/api/integration/add-theme.mjs +34 -64
  52. package/api/integration/add-theme.test.mjs +105 -21
  53. package/api/integration/authoring-checks.test.mjs +8 -4
  54. package/api/integration/integration-block-exports.test.mjs +10 -6
  55. package/api/integration/integrationAdd.doc.mjs +8 -4
  56. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  57. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  58. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  59. package/api/integration/integrationAddDoc.doc.mjs +1 -0
  60. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  61. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  62. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  63. package/api/integration/integrationDocConflicts.doc.mjs +1 -0
  64. package/api/integration/integrationPackCheck.doc.mjs +1 -0
  65. package/api/integration/integrationTemplateConflicts.doc.mjs +1 -0
  66. package/api/integration/pack-check.mjs +49 -7
  67. package/api/integration/pack-check.test.mjs +266 -47
  68. package/api/integration/summarizeIssues.doc.mjs +1 -0
  69. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  70. package/api/integration/validate-integration.mjs +52 -102
  71. package/api/integration/validate-integration.test.mjs +176 -23
  72. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  73. package/api/integration/validateIntegration.doc.mjs +2 -1
  74. package/api/json/assertResponse.doc.mjs +1 -0
  75. package/api/json/envelope-types.test.mjs +76 -0
  76. package/api/json/isError.doc.mjs +1 -0
  77. package/api/json/parseResponse.doc.mjs +3 -2
  78. package/api/layout/expand/expand.mjs +7 -5
  79. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  80. package/api/layout/grammar/grammar.mjs +2 -1
  81. package/api/layout/layoutCheck.doc.mjs +1 -0
  82. package/api/layout/layoutExpand.doc.mjs +2 -1
  83. package/api/layout/layoutGrammar.doc.mjs +1 -0
  84. package/api/search/search-return-type.test.mjs +54 -0
  85. package/api/search/search.d.mts +2 -9
  86. package/api/search/search.doc.mjs +6 -1
  87. package/api/search/search.mjs +31 -14
  88. package/api/search/search.test.mjs +34 -0
  89. package/api/search/search.type.d.mts +1 -1
  90. package/api/search/search.type.mjs +1 -1
  91. package/api/swizzle/copy/copy.mjs +28 -11
  92. package/api/swizzle/swizzle.doc.mjs +2 -1
  93. package/api/swizzle/swizzle.type.d.mts +2 -2
  94. package/api/swizzle/swizzle.type.mjs +2 -2
  95. package/api/template/copy/copy.mjs +17 -23
  96. package/api/template/copy/copy.test.mjs +17 -0
  97. package/api/template/template-suffix.test.mjs +41 -21
  98. package/api/template/template.doc.mjs +3 -1
  99. package/api/template/template.type.d.mts +5 -5
  100. package/api/template/template.type.mjs +12 -12
  101. package/api/theme/_adapter.d.mts +2 -3
  102. package/api/theme/_adapter.mjs +4 -5
  103. package/api/theme/add/add.binary.test.mjs +84 -0
  104. package/api/theme/add/add.mjs +20 -3
  105. package/api/theme/add/add.staging.test.mjs +66 -0
  106. package/api/theme/add/add.test.mjs +14 -1
  107. package/api/theme/build/build.mjs +133 -42
  108. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  109. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  110. package/api/theme/build/build.test.mjs +127 -0
  111. package/api/theme/build/font-warning.mjs +3 -3
  112. package/api/theme/build/font-warning.test.mjs +5 -2
  113. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  114. package/api/theme/integration-themes.test.mjs +39 -28
  115. package/api/theme/list/list.test.mjs +19 -20
  116. package/api/theme/listThemes.doc.mjs +6 -5
  117. package/api/theme/palette/generate/generate.mjs +8 -3
  118. package/api/theme/palette/generate/generate.test.mjs +96 -0
  119. package/api/theme/palette/generate/generator.d.mts +10 -13
  120. package/api/theme/palette/generate/generator.mjs +15 -4
  121. package/api/theme/palette/generate/generator.test.mjs +10 -0
  122. package/api/theme/template/template.mjs +11 -2
  123. package/api/theme/template/template.test.mjs +15 -0
  124. package/api/theme/theme.type.d.mts +170 -11
  125. package/api/theme/theme.type.mjs +94 -27
  126. package/api/theme/themeAdd.doc.mjs +4 -3
  127. package/api/theme/themeBuild.doc.mjs +8 -4
  128. package/api/theme/themeList.doc.mjs +6 -3
  129. package/api/theme/themeListAvailable.doc.mjs +5 -3
  130. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  131. package/api/theme/themeTargets.doc.mjs +1 -0
  132. package/api/theme/themeTemplate.doc.mjs +5 -1
  133. package/api/upgrade/_adapter.d.mts +12 -3
  134. package/api/upgrade/_adapter.mjs +108 -70
  135. package/api/upgrade/list/list.mjs +2 -1
  136. package/api/upgrade/list/list.test.mjs +73 -0
  137. package/api/upgrade/provider-agreement.test.mjs +152 -0
  138. package/api/upgrade/run/run.mjs +1 -0
  139. package/api/upgrade/status/status.mjs +2 -2
  140. package/api/upgrade/upgrade.doc.mjs +3 -1
  141. package/api/upgrade/upgrade.type.d.mts +8 -4
  142. package/api/upgrade/upgrade.type.mjs +11 -10
  143. package/assets/codemods/integration-discovery.mjs +48 -4
  144. package/assets/codemods/integration-discovery.test.mjs +73 -0
  145. package/assets/codemods/runner.mjs +115 -5
  146. package/assets/codemods/term-log.mjs +32 -8
  147. package/assets/codemods/term-log.test.mjs +19 -1
  148. package/assets/codemods/transform-prop.mjs +109 -0
  149. package/assets/codemods/transform-prop.test.mjs +95 -0
  150. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +216 -0
  151. package/assets/codemods/transforms/next/index.mjs +11 -1
  152. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  153. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  154. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  155. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  156. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  157. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  158. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  159. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  160. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  161. package/assets/docs/cli-integrations.doc.mjs +26 -30
  162. package/assets/docs/cli.doc.mjs +15 -0
  163. package/assets/docs/styling-libraries.doc.mjs +1 -1
  164. package/assets/docs/theme.doc.mjs +1 -1
  165. package/assets/docs/working-with-ai.doc.mjs +1 -1
  166. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  167. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  168. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  169. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  170. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  171. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  172. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  173. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  174. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  175. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  176. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  177. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  178. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  179. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  180. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  181. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  182. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  183. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  184. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  185. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  186. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  187. package/authoring/_shared/contract.ts +22 -0
  188. package/authoring/codemod/codemod.doc.mjs +7 -2
  189. package/authoring/codemod/parse.d.mts +8 -8
  190. package/authoring/codemod/parse.mjs +8 -6
  191. package/authoring/config/config.doc.mjs +2 -2
  192. package/authoring/config/debug-composition.test.mjs +92 -0
  193. package/authoring/config/parse.d.mts +13 -13
  194. package/authoring/config/parse.mjs +8 -8
  195. package/authoring/config/type.ts +18 -6
  196. package/authoring/debug/debug.doc.d.mts +11 -0
  197. package/authoring/debug/debug.doc.mjs +182 -0
  198. package/authoring/debug/parse.d.mts +4 -4
  199. package/authoring/debug/parse.mjs +3 -3
  200. package/authoring/doctypes/_schema.d.mts +121 -11
  201. package/authoring/doctypes/_schema.mjs +144 -13
  202. package/authoring/doctypes/base/graph-fields.doc.mjs +11 -4
  203. package/authoring/doctypes/base/type.ts +8 -4
  204. package/authoring/doctypes/command/command.doc.mjs +4 -3
  205. package/authoring/doctypes/command/parse.d.mts +2 -2
  206. package/authoring/doctypes/command/parse.mjs +1 -1
  207. package/authoring/doctypes/command/type.ts +3 -3
  208. package/authoring/doctypes/component/component.doc.mjs +5 -2
  209. package/authoring/doctypes/component/parse.d.mts +2 -2
  210. package/authoring/doctypes/component/parse.mjs +1 -1
  211. package/authoring/doctypes/component/type.ts +3 -3
  212. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  213. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  214. package/authoring/doctypes/enum/parse.d.mts +2 -2
  215. package/authoring/doctypes/enum/parse.mjs +1 -1
  216. package/authoring/doctypes/enum/type.ts +2 -2
  217. package/authoring/doctypes/function/function.doc.mjs +5 -1
  218. package/authoring/doctypes/function/parse.d.mts +2 -2
  219. package/authoring/doctypes/function/parse.mjs +1 -1
  220. package/authoring/doctypes/function/type.ts +2 -2
  221. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  222. package/authoring/doctypes/hook/parse.d.mts +2 -2
  223. package/authoring/doctypes/hook/parse.mjs +1 -1
  224. package/authoring/doctypes/hook/type.ts +3 -3
  225. package/authoring/doctypes/legacy.d.mts +6 -6
  226. package/authoring/doctypes/legacy.mjs +3 -3
  227. package/authoring/doctypes/load-contract.test.mjs +208 -0
  228. package/authoring/doctypes/namespace/namespace.doc.mjs +7 -3
  229. package/authoring/doctypes/namespace/parse.d.mts +2 -2
  230. package/authoring/doctypes/namespace/parse.mjs +1 -1
  231. package/authoring/doctypes/namespace/type.ts +2 -2
  232. package/authoring/doctypes/parse.d.mts +22 -20
  233. package/authoring/doctypes/parse.mjs +16 -12
  234. package/authoring/doctypes/reference/parse.d.mts +2 -2
  235. package/authoring/doctypes/reference/parse.mjs +1 -1
  236. package/authoring/doctypes/reference/reference.doc.mjs +7 -3
  237. package/authoring/doctypes/reference/type.ts +3 -3
  238. package/authoring/doctypes/schema/parse.d.mts +2 -2
  239. package/authoring/doctypes/schema/parse.mjs +1 -1
  240. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  241. package/authoring/doctypes/schema/type.ts +3 -4
  242. package/authoring/doctypes/template/parse.d.mts +92 -1
  243. package/authoring/doctypes/template/parse.mjs +33 -1
  244. package/authoring/doctypes/template/template.doc.mjs +7 -3
  245. package/authoring/doctypes/template/type.ts +4 -1
  246. package/authoring/doctypes/theme/parse.d.mts +35 -0
  247. package/authoring/doctypes/theme/parse.mjs +76 -0
  248. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  249. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  250. package/authoring/doctypes/theme/type.ts +42 -0
  251. package/authoring/doctypes/types.ts +12 -11
  252. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  253. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  254. package/authoring/gap-report/parse.d.mts +9 -9
  255. package/authoring/gap-report/parse.mjs +6 -6
  256. package/authoring/gap-report/type.ts +1 -1
  257. package/authoring/identity/identity.doc.mjs +3 -2
  258. package/authoring/identity/type.ts +10 -10
  259. package/authoring/index.d.mts +1 -0
  260. package/authoring/index.d.ts +21 -19
  261. package/authoring/index.mjs +2 -1
  262. package/authoring/integration/integration.doc.mjs +2 -2
  263. package/authoring/integration/parse.d.mts +2 -2
  264. package/authoring/integration/parse.mjs +1 -1
  265. package/authoring/integration/schema.d.mts +4 -4
  266. package/authoring/integration/schema.mjs +3 -3
  267. package/authoring/integration/type.ts +4 -10
  268. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  269. package/clients/cli/command-load-failure.test.mjs +83 -0
  270. package/clients/cli/commands/blog.doc.mjs +1 -1
  271. package/clients/cli/commands/blog.mjs +23 -8
  272. package/clients/cli/commands/blog.test.mjs +42 -1
  273. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  274. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  275. package/clients/cli/commands/build-theme.mjs +5 -5
  276. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  277. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  278. package/clients/cli/commands/build.doc.mjs +5 -2
  279. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  280. package/clients/cli/commands/build.mjs +32 -47
  281. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  282. package/clients/cli/commands/build.text-fields.test.mjs +40 -0
  283. package/clients/cli/commands/component/index.mjs +2 -7
  284. package/clients/cli/commands/component-package.test.mjs +46 -0
  285. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  286. package/clients/cli/commands/component.doc.mjs +1 -1
  287. package/clients/cli/commands/component.test.mjs +19 -0
  288. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  289. package/clients/cli/commands/discover.broken-integration.test.mjs +48 -0
  290. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  291. package/clients/cli/commands/discover.doc.mjs +5 -3
  292. package/clients/cli/commands/discover.mjs +3 -3
  293. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  294. package/clients/cli/commands/docs.doc.mjs +1 -1
  295. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  296. package/clients/cli/commands/doctor-integration-docs.doc.mjs +1 -1
  297. package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -1
  298. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  299. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  300. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  301. package/clients/cli/commands/doctor-integration.test.mjs +15 -7
  302. package/clients/cli/commands/doctor.doc.mjs +1 -1
  303. package/clients/cli/commands/doctor.mjs +6 -16
  304. package/clients/cli/commands/doctor.test.mjs +42 -0
  305. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  306. package/clients/cli/commands/gap-report.test.mjs +72 -0
  307. package/clients/cli/commands/hook/index.mjs +7 -17
  308. package/clients/cli/commands/hook.doc.mjs +1 -1
  309. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  310. package/clients/cli/commands/init.doc.mjs +20 -9
  311. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  312. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  313. package/clients/cli/commands/integration-add.doc.mjs +22 -6
  314. package/clients/cli/commands/integration-authoring.test.mjs +13 -9
  315. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  316. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  317. package/clients/cli/commands/integration.doc.mjs +1 -1
  318. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  319. package/clients/cli/commands/json-contract.test.mjs +33 -0
  320. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  321. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  322. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  323. package/clients/cli/commands/layout.doc.mjs +3 -3
  324. package/clients/cli/commands/layout.mjs +21 -9
  325. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  326. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  327. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  328. package/clients/cli/commands/manifest.doc.mjs +1 -1
  329. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  330. package/clients/cli/commands/search.doc.mjs +7 -4
  331. package/clients/cli/commands/search.mjs +17 -7
  332. package/clients/cli/commands/search.test.mjs +75 -0
  333. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  334. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  335. package/clients/cli/commands/template.doc.mjs +29 -7
  336. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  337. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  338. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  339. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  340. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  341. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
  342. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  343. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  344. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  345. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  346. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  347. package/clients/cli/commands/theme.doc.mjs +1 -1
  348. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  349. package/clients/cli/commands/upgrade.doc.mjs +18 -7
  350. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  351. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  352. package/clients/cli/index.mjs +13 -30
  353. package/clients/cli/latest-version-env.test.mjs +50 -0
  354. package/clients/cli/lib/cli-error.test.mjs +7 -0
  355. package/clients/cli/lib/component-format.mjs +9 -9
  356. package/clients/cli/lib/component-format.test.mjs +1 -1
  357. package/clients/cli/lib/define-command.mjs +32 -6
  358. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  359. package/clients/cli/lib/exit-codes.test.mjs +97 -0
  360. package/clients/cli/lib/hook-format.mjs +19 -10
  361. package/clients/cli/lib/json-shim.mjs +38 -2
  362. package/clients/cli/lib/json-shim.test.mjs +83 -0
  363. package/clients/cli/lib/manifest.d.ts +2 -0
  364. package/clients/cli/lib/manifest.mjs +22 -0
  365. package/clients/cli/lib/manifest.test.mjs +17 -0
  366. package/foundation/agent-docs/agent-docs.d.mts +4 -0
  367. package/foundation/agent-docs/agent-docs.mjs +69 -3
  368. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  369. package/foundation/config/integration-debug.test.mjs +28 -3
  370. package/foundation/config/project-themes.test.mjs +11 -19
  371. package/foundation/config/project.d.mts +8 -0
  372. package/foundation/config/project.mjs +173 -30
  373. package/foundation/config/project.test.mjs +129 -16
  374. package/foundation/discovery/authoring-self-docs.d.mts +6 -0
  375. package/foundation/discovery/authoring-self-docs.mjs +17 -7
  376. package/foundation/discovery/authoring-self-docs.test.mjs +71 -12
  377. package/foundation/discovery/authoring-surface.d.mts +74 -0
  378. package/foundation/discovery/authoring-surface.mjs +525 -0
  379. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  380. package/foundation/discovery/cli-self-docs.d.mts +113 -0
  381. package/foundation/discovery/cli-self-docs.mjs +514 -0
  382. package/foundation/discovery/cli-self-docs.test.mjs +437 -0
  383. package/foundation/discovery/component-loader.d.mts +35 -38
  384. package/foundation/discovery/component-loader.mjs +53 -222
  385. package/foundation/discovery/docs-discovery.d.mts +7 -2
  386. package/foundation/discovery/docs-discovery.mjs +24 -14
  387. package/foundation/discovery/docs-discovery.test.mjs +55 -16
  388. package/foundation/discovery/template-adapter.d.mts +21 -5
  389. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  390. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  391. package/foundation/discovery/template-adapter.mjs +319 -65
  392. package/foundation/discovery/template-adapter.test.mjs +15 -0
  393. package/foundation/discovery/theme-discovery.d.mts +67 -7
  394. package/foundation/discovery/theme-discovery.mjs +916 -186
  395. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  396. package/foundation/discovery/theming-targets.test.mjs +4 -0
  397. package/foundation/doc-compiler/bundle.d.mts +47 -0
  398. package/foundation/doc-compiler/bundle.mjs +218 -0
  399. package/foundation/doc-compiler/bundle.test.mjs +255 -0
  400. package/foundation/doc-compiler/compile.d.mts +362 -0
  401. package/foundation/doc-compiler/compile.mjs +511 -0
  402. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  403. package/foundation/doc-compiler/diagnostics.mjs +277 -0
  404. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  405. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  406. package/foundation/doc-compiler/import.d.mts +24 -0
  407. package/foundation/doc-compiler/import.mjs +59 -0
  408. package/foundation/doc-compiler/inputs.d.mts +102 -0
  409. package/foundation/doc-compiler/inputs.mjs +286 -0
  410. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  411. package/foundation/doc-compiler/ir.d.mts +22 -0
  412. package/foundation/doc-compiler/ir.mjs +464 -0
  413. package/foundation/doc-compiler/lenses.d.mts +33 -0
  414. package/foundation/doc-compiler/lenses.mjs +127 -0
  415. package/foundation/doc-compiler/lower-doc.test.mjs +492 -0
  416. package/foundation/doc-compiler/overlays.d.mts +37 -0
  417. package/foundation/doc-compiler/overlays.mjs +206 -0
  418. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  419. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  420. package/foundation/doc-compiler/read.d.mts +126 -0
  421. package/foundation/doc-compiler/read.mjs +320 -0
  422. package/foundation/doc-compiler/read.test.mjs +313 -0
  423. package/foundation/doc-compiler/source.d.mts +33 -0
  424. package/foundation/doc-compiler/source.mjs +128 -0
  425. package/foundation/fs/module-loader.d.mts +1 -0
  426. package/foundation/fs/module-loader.mjs +50 -1
  427. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  428. package/foundation/fs/path-safety.d.mts +3 -2
  429. package/foundation/fs/path-safety.mjs +49 -19
  430. package/foundation/fs/path-safety.test.mjs +50 -0
  431. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  432. package/foundation/integrations/autolink.d.mts +58 -1
  433. package/foundation/integrations/autolink.mjs +143 -52
  434. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  435. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  436. package/foundation/integrations/contribution-inventory.d.mts +1 -1
  437. package/foundation/integrations/contribution-inventory.mjs +17 -20
  438. package/foundation/integrations/contribution-inventory.test.mjs +67 -27
  439. package/foundation/integrations/integrations.d.mts +3 -0
  440. package/foundation/integrations/integrations.mjs +11 -97
  441. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  442. package/foundation/integrations/provider-resolution.d.mts +152 -0
  443. package/foundation/integrations/provider-resolution.mjs +576 -0
  444. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  445. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  446. package/foundation/integrations/theme-descriptor.mjs +44 -0
  447. package/foundation/integrations/validate-contributions.mjs +104 -10
  448. package/foundation/response/base.d.ts +8 -4
  449. package/foundation/response/error-codes.doc.mjs +3 -4
  450. package/foundation/response/error-codes.mjs +2 -2
  451. package/foundation/response/error-codes.test.mjs +83 -0
  452. package/foundation/response/json-contract.test.mjs +11 -0
  453. package/foundation/response/json.d.mts +4 -2
  454. package/foundation/response/json.mjs +8 -10
  455. package/foundation/response/response-types.doc.mjs +11 -11
  456. package/foundation/response/response-types.doc.test.mjs +158 -0
  457. package/foundation/response/response.doc.mjs +1 -1
  458. package/foundation/text/string-utils.mjs +22 -10
  459. package/foundation/xle/expand.d.mts +2 -0
  460. package/foundation/xle/expand.mjs +3 -2
  461. package/foundation/xle/expand.test.mjs +54 -0
  462. package/package.json +9 -11
  463. package/assets/templates/themes/manifest.json +0 -95
  464. package/clients/cli/lib/update-check.mjs +0 -83
  465. package/clients/cli/lib/update-check.test.mjs +0 -137
  466. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -0,0 +1,103 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file `astryx discover` text output projects every field of its JSON entry.
5
+ *
6
+ * The text views of `discover.list` and `discover.detail` are renderings of the
7
+ * same entries `--json` returns, so each entry key must appear as a `key:` line
8
+ * carrying the same value.
9
+ */
10
+
11
+ import {describe, it, expect, beforeEach, afterEach} from 'vitest';
12
+ import * as fs from 'node:fs';
13
+ import * as path from 'node:path';
14
+ import * as os from 'node:os';
15
+ import {runCli} from '../../../test-utils/run-cli.mjs';
16
+
17
+ let tmpDir;
18
+ let project;
19
+
20
+ beforeEach(() => {
21
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-discover-text-'));
22
+ project = path.join(tmpDir, 'project');
23
+ const pkgDir = path.join(project, 'node_modules', '@test', 'kit');
24
+ fs.mkdirSync(path.join(pkgDir, 'components'), {recursive: true});
25
+ fs.writeFileSync(
26
+ path.join(project, 'package.json'),
27
+ JSON.stringify({name: 'proj', version: '1.0.0'}),
28
+ );
29
+ fs.writeFileSync(
30
+ path.join(project, 'astryx.config.mjs'),
31
+ `export default {integrations: ['@test/kit']};\n`,
32
+ );
33
+ fs.writeFileSync(
34
+ path.join(pkgDir, 'package.json'),
35
+ JSON.stringify({name: '@test/kit', version: '3.1.4'}),
36
+ );
37
+ fs.writeFileSync(
38
+ path.join(pkgDir, 'astryx.integration.mjs'),
39
+ `export default {components: './components'};\n`,
40
+ );
41
+ for (const name of ['Dial', 'Gauge']) {
42
+ fs.writeFileSync(
43
+ path.join(pkgDir, 'components', `${name}.doc.mjs`),
44
+ `export const docs = {name: '${name}', usage: {description: 'A ${name}.'}};\n`,
45
+ );
46
+ fs.writeFileSync(
47
+ path.join(pkgDir, 'components', `${name}.tsx`),
48
+ `export function ${name}() { return null; }\n`,
49
+ );
50
+ }
51
+ });
52
+
53
+ afterEach(() => {
54
+ fs.rmSync(tmpDir, {recursive: true, force: true});
55
+ });
56
+
57
+ /**
58
+ * @param {Record<string, unknown>} entry
59
+ * @param {string} text
60
+ */
61
+ function expectEveryField(entry, text) {
62
+ const lines = text.split('\n');
63
+ for (const [key, value] of Object.entries(entry)) {
64
+ const rendered = Array.isArray(value) ? value.join(', ') : String(value);
65
+ expect(lines).toContainEqual(
66
+ expect.stringMatching(new RegExp(`^${key}:\\s+${escape(rendered)}$`)),
67
+ );
68
+ }
69
+ }
70
+
71
+ /** @param {string} s */
72
+ function escape(s) {
73
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
74
+ }
75
+
76
+ describe('astryx discover text output', () => {
77
+ it('lists every field of each discover.list entry', async () => {
78
+ const asJson = await runCli(['discover', '--json'], {cwd: project});
79
+ const [entry] = JSON.parse(asJson.stdout).data;
80
+ expect(Object.keys(entry)).toEqual(
81
+ expect.arrayContaining(['name', 'category', 'components', 'version']),
82
+ );
83
+
84
+ const {status, stdout} = await runCli(['discover'], {cwd: project});
85
+
86
+ expect(status).toBe(0);
87
+ expectEveryField(entry, stdout);
88
+ });
89
+
90
+ it('shows every field of the discover.detail entry', async () => {
91
+ const asJson = await runCli(['discover', '@test/kit', '--json'], {
92
+ cwd: project,
93
+ });
94
+ const {data} = JSON.parse(asJson.stdout);
95
+
96
+ const {status, stdout} = await runCli(['discover', '@test/kit'], {
97
+ cwd: project,
98
+ });
99
+
100
+ expect(status).toBe(0);
101
+ expectEveryField(data, stdout);
102
+ });
103
+ });
@@ -12,7 +12,7 @@ export const doc = {
12
12
  type: 'command',
13
13
  name: 'docs',
14
14
  displayName: 'astryx docs',
15
- namespace: 'cli',
15
+ namespace: 'cli/commands',
16
16
  summary: 'Print reference docs',
17
17
  description:
18
18
  'Reads the reference docs: with no topic it lists every topic; a topic prints that ' +
@@ -7,7 +7,7 @@ export const doc = {
7
7
  type: 'command',
8
8
  name: 'doctor integration components',
9
9
  displayName: 'astryx doctor integration components',
10
- namespace: 'cli',
10
+ namespace: 'cli/commands',
11
11
  summary: 'Warn when integration component names conflict with Core',
12
12
  description:
13
13
  'Compares one local or installed integration with Core component names. A ' +
@@ -7,7 +7,7 @@ export const doc = {
7
7
  type: 'command',
8
8
  name: 'doctor integration docs',
9
9
  displayName: 'astryx doctor integration docs',
10
- namespace: 'cli',
10
+ namespace: 'cli/commands',
11
11
  summary: 'Classify integration doc overlaps with Core topics',
12
12
  description:
13
13
  'Reports intentional Core topic replacements and extensions as information. ' +
@@ -9,7 +9,7 @@ export const doc = {
9
9
  type: 'command',
10
10
  name: 'doctor integration templates',
11
11
  displayName: 'astryx doctor integration templates',
12
- namespace: 'cli',
12
+ namespace: 'cli/commands',
13
13
  summary: 'Warn when integration template ids conflict with Core',
14
14
  description:
15
15
  'Compares one local or installed integration with the built-in Core page and ' +
@@ -9,7 +9,7 @@ export const doc = {
9
9
  type: 'command',
10
10
  name: 'doctor integration validate',
11
11
  displayName: 'astryx doctor integration validate',
12
- namespace: 'cli',
12
+ namespace: 'cli/commands',
13
13
  summary: 'Validate an integration manifest and its contributions',
14
14
  description:
15
15
  'Validates one integration at a time: the local package rooted at cwd, or an ' +
@@ -9,7 +9,7 @@ export const doc = {
9
9
  type: 'command',
10
10
  name: 'doctor integration',
11
11
  displayName: 'astryx doctor integration',
12
- namespace: 'cli',
12
+ namespace: 'cli/commands',
13
13
  summary: 'Check an integration package while authoring it',
14
14
  description:
15
15
  'The integration-authoring diagnostics group. Validate a manifest and all ' +
@@ -0,0 +1,53 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ import {afterEach, beforeEach, describe, expect, it} from 'vitest';
4
+ import * as fs from 'node:fs';
5
+ import * as path from 'node:path';
6
+ import {runCli} from '../../../test-utils/run-cli.mjs';
7
+ import {validateIntegration} from '../../../api/integration/validate-integration.mjs';
8
+
9
+ const NO_MANIFEST = 'No astryx.integration.* found next to package.json.';
10
+
11
+ let tmpDir;
12
+
13
+ beforeEach(() => {
14
+ tmpDir = fs.mkdtempSync(path.join(process.cwd(), '.astryx-doctor-pkgjson-'));
15
+ fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name": "@acme/widgets",}\n');
16
+ fs.writeFileSync(
17
+ path.join(tmpDir, 'astryx.integration.mjs'),
18
+ "export default {\n templates: './templates',\n};\n",
19
+ );
20
+ });
21
+
22
+ afterEach(() => {
23
+ fs.rmSync(tmpDir, {recursive: true, force: true});
24
+ });
25
+
26
+ describe('doctor integration with a malformed package.json', () => {
27
+ it('keeps a null name for the no-manifest case only', async () => {
28
+ const result = await validateIntegration(undefined, {cwd: tmpDir});
29
+
30
+ expect(result.data.name).toBe('(local package)');
31
+ expect(result.data.issues.map(issue => issue.code)).toEqual([
32
+ 'invalid_package_json',
33
+ ]);
34
+ });
35
+
36
+ for (const leaf of ['validate', 'templates', 'components', 'docs']) {
37
+ it(`${leaf} prints the package.json error instead of "no manifest"`, async () => {
38
+ const text = await runCli(['doctor', 'integration', leaf], tmpDir);
39
+ const json = await runCli(
40
+ ['doctor', 'integration', leaf, '--json'],
41
+ tmpDir,
42
+ );
43
+
44
+ expect(text.status).toBe(1);
45
+ expect(json.status).toBe(1);
46
+ expect(text.stdout).not.toContain(NO_MANIFEST);
47
+ expect(text.stdout).toContain('invalid_package_json');
48
+ expect(JSON.parse(json.stdout).data.issues).toContainEqual(
49
+ expect.objectContaining({code: 'invalid_package_json'}),
50
+ );
51
+ });
52
+ }
53
+ });
@@ -44,7 +44,7 @@ function writeIntegration({
44
44
  const stem = path.join(tmpDir, 'templates', id);
45
45
  fs.mkdirSync(path.dirname(stem), {recursive: true});
46
46
  fs.writeFileSync(
47
- `${stem}.template.mjs`,
47
+ `${stem}.doc.mjs`,
48
48
  `export default {type: 'page', name: ${JSON.stringify(name)}, description: 'fixture'};\n`,
49
49
  );
50
50
  fs.writeFileSync(
@@ -124,7 +124,12 @@ describe('doctor integration — command', () => {
124
124
  return true;
125
125
  });
126
126
 
127
- await createProgram().parseAsync(['node', 'astryx', 'doctor', 'integration']);
127
+ await createProgram().parseAsync([
128
+ 'node',
129
+ 'astryx',
130
+ 'doctor',
131
+ 'integration',
132
+ ]);
128
133
 
129
134
  const output = writes.join('');
130
135
  expect(output).toContain('validate [package]');
@@ -136,7 +141,9 @@ describe('doctor integration — command', () => {
136
141
 
137
142
  it('explains the optional package argument in every leaf help', () => {
138
143
  const program = createProgram();
139
- const doctor = program.commands.find(command => command.name() === 'doctor');
144
+ const doctor = program.commands.find(
145
+ command => command.name() === 'doctor',
146
+ );
140
147
  const integration = doctor?.commands.find(
141
148
  command => command.name() === 'integration',
142
149
  );
@@ -152,7 +159,10 @@ describe('doctor integration — command', () => {
152
159
  });
153
160
 
154
161
  it('templates explains how to check an installed package when no local manifest exists', async () => {
155
- fs.writeFileSync(path.join(tmpDir, 'package.json'), JSON.stringify({name: 'plain'}));
162
+ fs.writeFileSync(
163
+ path.join(tmpDir, 'package.json'),
164
+ JSON.stringify({name: 'plain'}),
165
+ );
156
166
  process.chdir(tmpDir);
157
167
 
158
168
  await createProgram().parseAsync([
@@ -278,9 +288,7 @@ describe('doctor integration — command', () => {
278
288
  const output = logCalls.join('\n');
279
289
  expect(output).toContain('[warn]');
280
290
  expect(output).toContain(core.name);
281
- expect(output).toContain(
282
- `component ${core.name} --package @acme/widgets`,
283
- );
291
+ expect(output).toContain(`component ${core.name} --package @acme/widgets`);
284
292
  expect(process.exitCode).toBeUndefined();
285
293
  });
286
294
 
@@ -12,7 +12,7 @@ export const doc = {
12
12
  type: 'command',
13
13
  name: 'doctor',
14
14
  displayName: 'astryx doctor',
15
- namespace: 'cli',
15
+ namespace: 'cli/commands',
16
16
  summary: 'Diagnose Astryx projects and integration packages',
17
17
  description:
18
18
  'Runs read-only project health diagnostics by default: Node version, @astryxdesign/core ' +
@@ -17,7 +17,7 @@ import {
17
17
  validateIntegration,
18
18
  } from '../../../api/integration/validate-integration.mjs';
19
19
  import {jsonOut} from '../../../foundation/response/json.mjs';
20
- import {emit, section, records, text} from '../formatters/index.mjs';
20
+ import {emit, section, record, records, text} from '../formatters/index.mjs';
21
21
  import {defineCommand} from '../lib/define-command.mjs';
22
22
  import {doc as doctorCommand} from './doctor.doc.mjs';
23
23
  import {doc as doctorIntegrationGroup} from './doctor-integration.doc.mjs';
@@ -55,7 +55,7 @@ function integrationLabel(data) {
55
55
  * @param {import('../../../api/doctor/doctor.mjs').DoctorReport} report
56
56
  */
57
57
  function printHuman(report) {
58
- const {pass, warn, fail, info} = report.summary;
58
+ const {warn, fail} = report.summary;
59
59
  const closing =
60
60
  fail > 0
61
61
  ? 'Some checks failed. Address the items marked [fail] above.'
@@ -63,18 +63,15 @@ function printHuman(report) {
63
63
  ? 'No failures — but review the [warn] warnings above when you can.'
64
64
  : 'All checks passed. Your Astryx setup looks healthy.';
65
65
 
66
+ // Field names are the JSON keys, so text and --json map one to one.
66
67
  emit(
67
68
  section('astryx doctor — diagnosing your setup'),
68
69
  records(report.checks, {
69
- fields: ['status', 'label', 'message', 'fix'],
70
- labels: {label: 'check'},
70
+ fields: ['id', 'status', 'label', 'message', 'fix'],
71
71
  format: {status: statusToken},
72
72
  }),
73
- text(
74
- `Summary: ${pass} passed, ${warn} warning${warn === 1 ? '' : 's'}, ` +
75
- `${fail} failure${fail === 1 ? '' : 's'}` +
76
- (info ? `, ${info} info` : ''),
77
- ),
73
+ section('summary'),
74
+ record(report.summary, {fields: ['pass', 'warn', 'fail', 'info']}),
78
75
  text(closing),
79
76
  );
80
77
  }
@@ -290,13 +287,6 @@ export function registerDoctor(program) {
290
287
  fn: doctorFn,
291
288
  action: async () => runProjectDoctor(program),
292
289
  });
293
- doctorCmd.addHelpText(
294
- 'after',
295
- '\nExit code:\n' +
296
- ' 0 no failures (warnings are allowed) — safe as a CI gate\n' +
297
- ' 1 one or more checks failed\n',
298
- );
299
-
300
290
  /** @type {import('commander').Command} */
301
291
  let integrationCmd;
302
292
  integrationCmd = defineCommand(doctorCmd, doctorIntegrationGroup, {
@@ -354,3 +354,45 @@ describe('doctor — command', () => {
354
354
  }
355
355
  });
356
356
  });
357
+
358
+ describe('doctor — text output mirrors the JSON', () => {
359
+ /** @param {string} line */
360
+ const field = line => /^(\w+):\s+(.*)$/.exec(line)?.slice(1) ?? [line, ''];
361
+
362
+ it('prints every check and summary field under its JSON key', async () => {
363
+ const prevCwd = process.cwd();
364
+ const prevExit = process.exitCode;
365
+ process.chdir(tmpDir);
366
+ try {
367
+ await createProgram().parseAsync(['node', 'astryx', '--json', 'doctor']);
368
+ const {checks, summary} = JSON.parse(logCalls.join('\n')).data;
369
+ logCalls = [];
370
+ await createProgram().parseAsync(['node', 'astryx', 'doctor']);
371
+ const blocks = logCalls
372
+ .join('\n')
373
+ .split(/\n{2,}/)
374
+ .map(block => block.split('\n').map(field));
375
+
376
+ for (const check of checks) {
377
+ const block = blocks.find(fields =>
378
+ fields.some(([key, value]) => key === 'id' && value === check.id),
379
+ );
380
+ expect(block, `no text record for check ${check.id}`).toBeDefined();
381
+ expect(
382
+ /** @type {string[][]} */ (block).map(([key]) => key).sort(),
383
+ ).toEqual(Object.keys(check).sort());
384
+ }
385
+
386
+ const heading = blocks.findIndex(
387
+ fields => fields.length === 1 && fields[0][0] === 'summary',
388
+ );
389
+ expect(heading, 'no summary section').toBeGreaterThan(-1);
390
+ expect(blocks[heading + 1]).toEqual(
391
+ Object.entries(summary).map(([key, count]) => [key, String(count)]),
392
+ );
393
+ } finally {
394
+ process.chdir(prevCwd);
395
+ process.exitCode = prevExit;
396
+ }
397
+ }, 60_000);
398
+ });
@@ -10,27 +10,37 @@ export const doc = {
10
10
  type: 'command',
11
11
  name: 'gap-report',
12
12
  displayName: 'astryx gap-report',
13
- namespace: 'cli',
13
+ namespace: 'cli/commands',
14
14
  summary: 'Route a design-system gap to its owning package',
15
15
  description:
16
16
  'Reports a missing component, variant, layout, styling, accessibility, API, or documentation capability. The command selects an explicit package first, then a unique component owner, then Core. The report fans out to every effective handler: project config first, then each loaded integration in config order. Public handlers require --confirm-public per handler; internal handlers always run. A handler failure is isolated and does not prevent later handlers.',
17
17
  fn: 'gapReport',
18
- args: [{name: 'component', param: 'component', required: false}],
18
+ args: [
19
+ {
20
+ name: 'component',
21
+ param: 'component',
22
+ required: false,
23
+ description:
24
+ 'Component or design-system area the gap is about, up to 120 characters. Required unless --list-categories is set.',
25
+ },
26
+ ],
19
27
  options: [
20
28
  {
21
29
  flag: '--category <category>',
22
30
  param: 'options.category',
23
- description: 'Gap category (run --list-categories for values)',
31
+ description:
32
+ 'Gap category (run --list-categories for values). Required unless --list-categories is set.',
24
33
  },
25
34
  {
26
35
  flag: '--reason <reason>',
27
36
  param: 'options.reason',
28
- description: 'What capability was missing or difficult',
37
+ description:
38
+ 'What capability was missing or difficult, up to 2000 characters. Required unless --list-categories is set.',
29
39
  },
30
40
  {
31
41
  flag: '--additional-context <text>',
32
42
  param: 'options.detail',
33
- description: 'Optional additional context',
43
+ description: 'Optional additional context, up to 8000 characters',
34
44
  },
35
45
  {
36
46
  flag: '--package <pkg>',
@@ -45,7 +55,8 @@ export const doc = {
45
55
  {
46
56
  flag: '--list-categories',
47
57
  param: 'options.listCategories',
48
- description: 'List valid report categories without filing',
58
+ description:
59
+ 'List valid report categories without filing; the component and the other gap-report options are ignored',
49
60
  },
50
61
  ],
51
62
  examples: [
@@ -196,3 +196,75 @@ export default {};\n`,
196
196
  });
197
197
  });
198
198
  });
199
+
200
+ describe('gap-report control docs', () => {
201
+ const REQUIRED = 'Required unless --list-categories is set.';
202
+
203
+ it('help and manifest say which inputs are required and how long they may be', async () => {
204
+ const help = await runCli(['gap-report', '--help']);
205
+ expect(help.status).toBe(0);
206
+ const manifest = JSON.parse((await runCli(['manifest', '--json'])).stdout);
207
+ const entry = manifest.data.commands.find(
208
+ (/** @type {{name: string}} */ command) => command.name === 'gap-report',
209
+ );
210
+ /** @param {string} flag @returns {string} */
211
+ const option = flag =>
212
+ entry.options.find(
213
+ (/** @type {{flag: string}} */ item) => item.flag.split(' ')[0] === flag,
214
+ )?.description ?? '';
215
+ const component = entry.arguments[0].description;
216
+
217
+ for (const text of [component, option('--category'), option('--reason')]) {
218
+ expect(text).toContain(REQUIRED);
219
+ expect(help.stdout).toContain(text);
220
+ }
221
+ expect(option('--list-categories')).toContain(
222
+ 'the component and the other gap-report options are ignored',
223
+ );
224
+
225
+ const cwd = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-gap-limits-'));
226
+ try {
227
+ fs.writeFileSync(
228
+ path.join(cwd, 'package.json'),
229
+ JSON.stringify({name: 'fixture-app'}),
230
+ );
231
+ const base = {cwd, category: /** @type {const} */ ('docs_gap'), reason: 'x'};
232
+ /** @type {Array<[string, (value: string) => Promise<unknown>]>} */
233
+ const limits = [
234
+ [component, value => gapReport(value, base)],
235
+ [option('--reason'), value => gapReport('Button', {...base, reason: value})],
236
+ [
237
+ option('--additional-context'),
238
+ value => gapReport('Button', {...base, detail: value}),
239
+ ],
240
+ ];
241
+ for (const [text, call] of limits) {
242
+ const limit = Number(/up to (\d+) characters/.exec(text)?.[1]);
243
+ expect(limit, text).toBeGreaterThan(0);
244
+ await expect(call('x'.repeat(limit))).resolves.toMatchObject({
245
+ type: 'gap-report.file',
246
+ });
247
+ await expect(call('x'.repeat(limit + 1))).rejects.toMatchObject({
248
+ code: 'ERR_INVALID_ARGUMENT',
249
+ });
250
+ }
251
+ } finally {
252
+ fs.rmSync(cwd, {recursive: true, force: true});
253
+ }
254
+ });
255
+
256
+ it('enforces the documented requirement', async () => {
257
+ for (const [component, options] of [
258
+ [undefined, {category: 'docs_gap', reason: 'x'}],
259
+ ['Button', {reason: 'x'}],
260
+ ['Button', {category: 'docs_gap'}],
261
+ ]) {
262
+ await expect(gapReport(component, options)).rejects.toMatchObject({
263
+ code: 'ERR_MISSING_ARGUMENT',
264
+ });
265
+ }
266
+ await expect(
267
+ gapReport(undefined, {listCategories: true, category: 'not_real', package: 'nope'}),
268
+ ).resolves.toMatchObject({type: 'gap-report.categories'});
269
+ });
270
+ });
@@ -20,7 +20,6 @@ import {defineCommand} from '../../lib/define-command.mjs';
20
20
  import {resultSet} from '../../../../foundation/debug/index.mjs';
21
21
  import {ERROR_CODES} from '../../../../foundation/response/error-codes.mjs';
22
22
  import {hook as hookApi} from '../../../../api/hook/hook.mjs';
23
- import {findRelatedBlocks} from '../../../../api/template/template.mjs';
24
23
  import {doc as hookCommand} from '../hook.doc.mjs';
25
24
  import {doc as hookFn} from '../../../../api/hook/hook.doc.mjs';
26
25
 
@@ -169,24 +168,15 @@ export function registerHook(program) {
169
168
  )
170
169
  : formatHookFull(result.data);
171
170
 
172
- // Show related block templates from relatedComponents
173
- const relatedComps = result.data.relatedComponents || [];
174
- /** @type {import('../../../../api/template/template.mjs').DiscoveredTemplate[]} */
175
- const allBlocks = [];
176
- for (const comp of relatedComps) {
177
- const blocks = await findRelatedBlocks(comp);
178
- for (const b of blocks) {
179
- if (!allBlocks.some(existing => existing.dirName === b.dirName)) {
180
- allBlocks.push(b);
181
- }
182
- }
183
- }
184
-
171
+ // Text projects the envelope only. Block templates are JSON-backed
172
+ // under `component <name> --blocks`.
173
+ const related = result.data.relatedComponents ?? [];
185
174
  emit(
186
175
  code(doc),
187
- allBlocks.length > 0 && section('Related block templates'),
188
- allBlocks.length > 0 &&
189
- records(allBlocks, {fields: ['dirName', 'description']}),
176
+ related.length > 0 &&
177
+ text(
178
+ `Block templates: ${run} component <name> --blocks for ${related.join(', ')}`,
179
+ ),
190
180
  );
191
181
  break;
192
182
  }
@@ -12,7 +12,7 @@ export const doc = {
12
12
  type: 'command',
13
13
  name: 'hook',
14
14
  displayName: 'astryx hook',
15
- namespace: 'cli',
15
+ namespace: 'cli/commands',
16
16
  summary: 'List hooks or print hook docs',
17
17
  description:
18
18
  'Resolves a hook by name and prints its authored doc, or lists the catalog grouped ' +
@@ -0,0 +1,45 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file `astryx hook <name>` text is a projection of `hook.detail`: it shows
5
+ * nothing the JSON envelope does not carry.
6
+ */
7
+
8
+ import {describe, it, expect} from 'vitest';
9
+ import {runCli} from '../../../test-utils/run-cli.mjs';
10
+ import {findRelatedBlocks} from '../../../api/template/template.mjs';
11
+
12
+ const HOOK = 'useAnnounce';
13
+
14
+ describe('hook detail text projection', () => {
15
+ it('prints no block templates that the JSON envelope lacks', async () => {
16
+ const json = await runCli(['--json', 'hook', HOOK]);
17
+ expect(json.status).toBe(0);
18
+ const envelope = JSON.parse(json.stdout);
19
+ expect(envelope.type).toBe('hook.detail');
20
+ const related = envelope.data.relatedComponents;
21
+ expect(related.length).toBeGreaterThan(0);
22
+
23
+ const blockNames = [];
24
+ for (const component of related) {
25
+ for (const block of await findRelatedBlocks(component)) {
26
+ blockNames.push(block.dirName);
27
+ }
28
+ }
29
+ expect(blockNames.length).toBeGreaterThan(0);
30
+
31
+ const text = await runCli(['hook', HOOK]);
32
+ expect(text.status).toBe(0);
33
+ const shownButNotInJson = blockNames.filter(
34
+ name => text.stdout.includes(name) && !json.stdout.includes(name),
35
+ );
36
+ expect(shownButNotInJson).toEqual([]);
37
+ });
38
+
39
+ it('points at the JSON-backed block lookup for each related component', async () => {
40
+ const text = await runCli(['hook', HOOK]);
41
+ expect(text.stdout).toMatch(/component <name> --blocks/);
42
+ expect(text.stdout).toContain('VisuallyHidden');
43
+ expect(text.stdout).toContain('Toast');
44
+ });
45
+ });