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

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 (612) hide show
  1. package/README.md +117 -79
  2. package/api/blog/blog.doc.mjs +1 -0
  3. package/api/build/_adapter.d.mts +50 -0
  4. package/api/build/_adapter.mjs +60 -0
  5. package/api/build/build.doc.mjs +16 -9
  6. package/api/build/build.test.mjs +197 -8
  7. package/api/build/build.type.d.mts +91 -2
  8. package/api/build/build.type.mjs +52 -8
  9. package/api/build/help/help.d.mts +12 -5
  10. package/api/build/help/help.mjs +69 -6
  11. package/api/build/kit/kit.d.mts +4 -1
  12. package/api/build/kit/kit.mjs +165 -49
  13. package/api/build/kit/rank.d.mts +44 -0
  14. package/api/build/kit/rank.mjs +432 -0
  15. package/api/build/kit/rank.test.mjs +196 -0
  16. package/api/component/_adapter.d.mts +6 -12
  17. package/api/component/_adapter.mjs +20 -10
  18. package/api/component/component.doc.mjs +13 -3
  19. package/api/component/component.mjs +91 -14
  20. package/api/component/component.test.mjs +38 -0
  21. package/api/component/component.type.d.mts +22 -11
  22. package/api/component/component.type.mjs +32 -24
  23. package/api/component/detail/blocks/blocks.d.mts +2 -1
  24. package/api/component/detail/blocks/blocks.mjs +4 -3
  25. package/api/component/list/list.d.mts +0 -5
  26. package/api/component/list/list.mjs +40 -11
  27. package/api/discover/_adapter.d.mts +114 -6
  28. package/api/discover/_adapter.mjs +372 -17
  29. package/api/discover/_adapter.test.mjs +215 -0
  30. package/api/discover/_catalog-view.d.mts +115 -0
  31. package/api/discover/_catalog-view.mjs +203 -0
  32. package/api/discover/_catalog-view.test.mjs +128 -0
  33. package/api/discover/detail/detail.d.mts +18 -6
  34. package/api/discover/detail/detail.mjs +67 -13
  35. package/api/discover/detail/detail.test.mjs +85 -0
  36. package/api/discover/detail/item/item.d.mts +26 -0
  37. package/api/discover/detail/item/item.mjs +78 -0
  38. package/api/discover/detail/item/item.test.mjs +73 -0
  39. package/api/discover/discover.d.mts +3 -9
  40. package/api/discover/discover.doc.mjs +62 -18
  41. package/api/discover/discover.mjs +220 -36
  42. package/api/discover/discover.test.mjs +11 -2
  43. package/api/discover/discover.type.d.mts +150 -11
  44. package/api/discover/discover.type.mjs +107 -17
  45. package/api/discover/list/list.d.mts +20 -6
  46. package/api/discover/list/list.mjs +45 -12
  47. package/api/discover/list/list.test.mjs +46 -0
  48. package/api/discover/search/search.d.mts +18 -16
  49. package/api/discover/search/search.mjs +102 -56
  50. package/api/discover/search/search.test.mjs +144 -10
  51. package/api/docs/_adapter.d.mts +268 -47
  52. package/api/docs/_adapter.mjs +970 -149
  53. package/api/docs/compiled-topics.test.mjs +78 -0
  54. package/api/docs/detail/detail.d.mts +0 -15
  55. package/api/docs/detail/detail.mjs +22 -78
  56. package/api/docs/detail/section/section.mjs +39 -24
  57. package/api/docs/detail/section/section.test.mjs +19 -9
  58. package/api/docs/docs.d.mts +5 -3
  59. package/api/docs/docs.doc.mjs +39 -17
  60. package/api/docs/docs.mjs +44 -8
  61. package/api/docs/docs.test.mjs +158 -4
  62. package/api/docs/docs.type.d.mts +185 -6
  63. package/api/docs/docs.type.mjs +127 -13
  64. package/api/docs/index/index.mjs +15 -6
  65. package/api/docs/index/index.test.mjs +1 -1
  66. package/api/docs/integration-tree.test.mjs +555 -0
  67. package/api/docs/integrationDocs.test.mjs +14 -14
  68. package/api/docs/list/list.mjs +28 -12
  69. package/api/docs/node/node.d.mts +43 -0
  70. package/api/docs/node/node.mjs +192 -0
  71. package/api/docs/reference-blocks.test.mjs +406 -0
  72. package/api/doctor/doctor.d.mts +54 -4
  73. package/api/doctor/doctor.doc.mjs +1 -0
  74. package/api/doctor/doctor.mjs +332 -21
  75. package/api/doctor/doctor.test.mjs +420 -7
  76. package/api/gap-report/gap-report.doc.mjs +8 -4
  77. package/api/hook/_adapter.mjs +19 -5
  78. package/api/hook/hook.doc.mjs +1 -0
  79. package/api/hook/hook.type.d.mts +3 -3
  80. package/api/hook/hook.type.mjs +11 -11
  81. package/api/hook/list/list.d.mts +1 -1
  82. package/api/hook/list/list.mjs +69 -17
  83. package/api/index.d.mts +1 -1
  84. package/api/index.mjs +1 -0
  85. package/api/init/init.doc.mjs +6 -1
  86. package/api/init/init.test.mjs +41 -1
  87. package/api/init/remove/remove.mjs +1 -1
  88. package/api/init/run/run.mjs +20 -10
  89. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  90. package/api/integration/add-contribution.d.mts +2 -1
  91. package/api/integration/add-contribution.mjs +130 -15
  92. package/api/integration/add-contribution.test.mjs +258 -7
  93. package/api/integration/add-helpers.d.mts +5 -2
  94. package/api/integration/add-helpers.mjs +36 -9
  95. package/api/integration/add-theme.mjs +34 -64
  96. package/api/integration/add-theme.test.mjs +105 -21
  97. package/api/integration/authoring-checks.mjs +138 -28
  98. package/api/integration/authoring-checks.test.mjs +179 -7
  99. package/api/integration/authoring-checks.type.mjs +6 -1
  100. package/api/integration/integration-authoring.type.d.mts +2 -0
  101. package/api/integration/integration-authoring.type.mjs +2 -0
  102. package/api/integration/integration-block-exports.test.mjs +10 -6
  103. package/api/integration/integrationAdd.doc.mjs +14 -4
  104. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  105. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  106. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  107. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  108. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  109. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  110. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  111. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  112. package/api/integration/integrationPackCheck.doc.mjs +2 -1
  113. package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
  114. package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
  115. package/api/integration/pack-check.mjs +83 -7
  116. package/api/integration/pack-check.test.mjs +387 -47
  117. package/api/integration/pack-check.type.d.mts +26 -2
  118. package/api/integration/pack-check.type.mjs +14 -1
  119. package/api/integration/summarizeIssues.doc.mjs +1 -0
  120. package/api/integration/template-conflict-compatibility.test.mjs +73 -0
  121. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  122. package/api/integration/validate-integration.mjs +52 -102
  123. package/api/integration/validate-integration.test.mjs +179 -26
  124. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  125. package/api/integration/validateIntegration.doc.mjs +3 -2
  126. package/api/json/assertResponse.doc.mjs +1 -0
  127. package/api/json/envelope-types.test.mjs +76 -0
  128. package/api/json/index.ts +2 -0
  129. package/api/json/isError.doc.mjs +1 -0
  130. package/api/json/parseResponse.doc.mjs +3 -2
  131. package/api/layout/_adapter.mjs +20 -5
  132. package/api/layout/expand/expand.mjs +7 -5
  133. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  134. package/api/layout/grammar/grammar.mjs +2 -1
  135. package/api/layout/layoutCheck.doc.mjs +1 -0
  136. package/api/layout/layoutExpand.doc.mjs +2 -1
  137. package/api/layout/layoutGrammar.doc.mjs +1 -0
  138. package/api/search/search-return-type.test.mjs +54 -0
  139. package/api/search/search.d.mts +61 -10
  140. package/api/search/search.doc.mjs +8 -2
  141. package/api/search/search.mjs +471 -83
  142. package/api/search/search.test.mjs +124 -1
  143. package/api/search/search.type.d.mts +14 -2
  144. package/api/search/search.type.mjs +5 -2
  145. package/api/swizzle/copy/copy.mjs +28 -11
  146. package/api/swizzle/swizzle.doc.mjs +2 -1
  147. package/api/swizzle/swizzle.type.d.mts +2 -2
  148. package/api/swizzle/swizzle.type.mjs +2 -2
  149. package/api/template/copy/copy.mjs +17 -23
  150. package/api/template/copy/copy.test.mjs +17 -0
  151. package/api/template/list/list.mjs +1 -0
  152. package/api/template/table-floating-bulk-actions.test.mjs +66 -0
  153. package/api/template/template-integration.test.mjs +1072 -3
  154. package/api/template/template-suffix.test.mjs +41 -21
  155. package/api/template/template.doc.mjs +30 -8
  156. package/api/template/template.mjs +45 -8
  157. package/api/template/template.type.d.mts +11 -13
  158. package/api/template/template.type.mjs +15 -14
  159. package/api/theme/_adapter.d.mts +2 -3
  160. package/api/theme/_adapter.mjs +4 -5
  161. package/api/theme/add/add.binary.test.mjs +84 -0
  162. package/api/theme/add/add.mjs +31 -22
  163. package/api/theme/add/add.rollback.test.mjs +158 -0
  164. package/api/theme/add/add.staging.test.mjs +83 -0
  165. package/api/theme/add/add.test.mjs +14 -1
  166. package/api/theme/build/build.family.test.mjs +7 -12
  167. package/api/theme/build/build.mjs +140 -59
  168. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  169. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  170. package/api/theme/build/build.rollback.test.mjs +148 -0
  171. package/api/theme/build/build.test.mjs +127 -0
  172. package/api/theme/build/font-warning.mjs +3 -3
  173. package/api/theme/build/font-warning.test.mjs +5 -2
  174. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  175. package/api/theme/integration-themes.test.mjs +39 -28
  176. package/api/theme/list/list.test.mjs +19 -20
  177. package/api/theme/listThemes.doc.mjs +6 -5
  178. package/api/theme/palette/generate/generate.mjs +8 -3
  179. package/api/theme/palette/generate/generate.test.mjs +96 -0
  180. package/api/theme/palette/generate/generator.d.mts +10 -13
  181. package/api/theme/palette/generate/generator.mjs +15 -4
  182. package/api/theme/palette/generate/generator.test.mjs +10 -0
  183. package/api/theme/template/template.mjs +11 -2
  184. package/api/theme/template/template.test.mjs +20 -0
  185. package/api/theme/theme.type.d.mts +170 -11
  186. package/api/theme/theme.type.mjs +94 -27
  187. package/api/theme/themeAdd.doc.mjs +4 -3
  188. package/api/theme/themeBuild.doc.mjs +8 -4
  189. package/api/theme/themeList.doc.mjs +6 -3
  190. package/api/theme/themeListAvailable.doc.mjs +5 -3
  191. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  192. package/api/theme/themeTargets.doc.mjs +1 -0
  193. package/api/theme/themeTemplate.doc.mjs +6 -2
  194. package/api/upgrade/_adapter.d.mts +32 -5
  195. package/api/upgrade/_adapter.mjs +124 -73
  196. package/api/upgrade/list/list.mjs +2 -1
  197. package/api/upgrade/list/list.test.mjs +73 -0
  198. package/api/upgrade/provider-agreement.test.mjs +152 -0
  199. package/api/upgrade/run/run.mjs +356 -59
  200. package/api/upgrade/status/status.mjs +2 -2
  201. package/api/upgrade/upgrade.doc.mjs +8 -2
  202. package/api/upgrade/upgrade.type.d.mts +42 -4
  203. package/api/upgrade/upgrade.type.mjs +26 -10
  204. package/assets/codemods/__tests__/runner.test.mjs +330 -8
  205. package/assets/codemods/integration-discovery.mjs +48 -4
  206. package/assets/codemods/integration-discovery.test.mjs +73 -0
  207. package/assets/codemods/integration-runner.mjs +56 -4
  208. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  209. package/assets/codemods/run-codemod.mjs +177 -34
  210. package/assets/codemods/runner.mjs +350 -102
  211. package/assets/codemods/term-log.mjs +32 -8
  212. package/assets/codemods/term-log.test.mjs +19 -1
  213. package/assets/codemods/transform-prop.mjs +109 -0
  214. package/assets/codemods/transform-prop.test.mjs +95 -0
  215. package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  216. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  217. package/assets/codemods/transforms/next/index.mjs +19 -1
  218. package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
  219. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  220. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  221. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  222. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  223. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  224. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  225. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  226. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  227. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  228. package/assets/docs/getting-started.doc.mjs +2 -2
  229. package/assets/docs/internationalization.doc.mjs +7 -5
  230. package/assets/docs/layout.doc.dense.mjs +2 -2
  231. package/assets/docs/layout.doc.mjs +1 -1
  232. package/assets/docs/principles.doc.mjs +6 -6
  233. package/assets/docs/styling-libraries.doc.mjs +4 -4
  234. package/assets/docs/styling.doc.mjs +4 -4
  235. package/assets/docs/theme.doc.mjs +5 -5
  236. package/assets/docs/tokens.doc.mjs +1 -1
  237. package/assets/docs/tree/api.doc.mjs +30 -0
  238. package/assets/docs/tree/cli.doc.mjs +23 -0
  239. package/assets/docs/tree/commands.doc.mjs +25 -0
  240. package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +95 -39
  241. package/assets/docs/tree/integrations.test.mjs +62 -0
  242. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  243. package/assets/docs/working-with-ai.doc.mjs +4 -4
  244. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
  245. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
  246. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  247. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  248. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  249. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  250. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  251. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  252. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  253. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  254. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  255. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  256. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  257. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  258. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  259. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  260. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  261. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  262. package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
  263. package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
  264. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
  265. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
  266. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  267. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  268. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  269. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  270. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  271. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  272. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  273. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  274. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  275. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  276. package/authoring/_shared/contract.ts +22 -0
  277. package/authoring/codemod/codemod.doc.mjs +7 -2
  278. package/authoring/codemod/parse.d.mts +8 -8
  279. package/authoring/codemod/parse.mjs +8 -6
  280. package/authoring/codemod/type.ts +12 -0
  281. package/authoring/config/config.doc.mjs +10 -2
  282. package/authoring/config/debug-composition.test.mjs +92 -0
  283. package/authoring/config/parse.d.mts +15 -13
  284. package/authoring/config/parse.mjs +27 -8
  285. package/authoring/config/parse.test.mjs +8 -0
  286. package/authoring/config/type.ts +29 -6
  287. package/authoring/debug/debug.doc.d.mts +11 -0
  288. package/authoring/debug/debug.doc.mjs +182 -0
  289. package/authoring/debug/parse.d.mts +7 -7
  290. package/authoring/debug/parse.mjs +3 -3
  291. package/authoring/discover/discover.doc.d.mts +13 -0
  292. package/authoring/discover/discover.doc.mjs +138 -0
  293. package/authoring/discover/parse.d.mts +24 -0
  294. package/authoring/discover/parse.mjs +128 -0
  295. package/authoring/discover/parse.test.mjs +124 -0
  296. package/authoring/discover/type.ts +87 -0
  297. package/authoring/doctypes/_schema.d.mts +240 -128
  298. package/authoring/doctypes/_schema.mjs +198 -16
  299. package/authoring/doctypes/base/graph-fields.doc.mjs +15 -6
  300. package/authoring/doctypes/base/type.ts +9 -4
  301. package/authoring/doctypes/command/command.doc.mjs +4 -3
  302. package/authoring/doctypes/command/parse.d.mts +2 -2
  303. package/authoring/doctypes/command/parse.mjs +1 -1
  304. package/authoring/doctypes/command/type.ts +4 -4
  305. package/authoring/doctypes/component/component.doc.mjs +5 -2
  306. package/authoring/doctypes/component/parse.d.mts +2 -2
  307. package/authoring/doctypes/component/parse.mjs +1 -1
  308. package/authoring/doctypes/component/type.ts +3 -3
  309. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  310. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  311. package/authoring/doctypes/enum/parse.d.mts +2 -2
  312. package/authoring/doctypes/enum/parse.mjs +1 -1
  313. package/authoring/doctypes/enum/type.ts +2 -2
  314. package/authoring/doctypes/function/function.doc.mjs +7 -2
  315. package/authoring/doctypes/function/parse.d.mts +2 -2
  316. package/authoring/doctypes/function/parse.mjs +1 -1
  317. package/authoring/doctypes/function/type.ts +4 -3
  318. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  319. package/authoring/doctypes/hook/parse.d.mts +2 -2
  320. package/authoring/doctypes/hook/parse.mjs +1 -1
  321. package/authoring/doctypes/hook/type.ts +3 -3
  322. package/authoring/doctypes/legacy.d.mts +6 -6
  323. package/authoring/doctypes/legacy.mjs +3 -3
  324. package/authoring/doctypes/load-contract.test.mjs +233 -0
  325. package/authoring/doctypes/namespace/namespace.doc.mjs +9 -9
  326. package/authoring/doctypes/namespace/parse.d.mts +2 -2
  327. package/authoring/doctypes/namespace/parse.mjs +1 -1
  328. package/authoring/doctypes/namespace/parse.test.mjs +23 -25
  329. package/authoring/doctypes/namespace/type.ts +6 -3
  330. package/authoring/doctypes/parse.d.mts +22 -20
  331. package/authoring/doctypes/parse.mjs +19 -14
  332. package/authoring/doctypes/reference/parse.d.mts +2 -2
  333. package/authoring/doctypes/reference/parse.mjs +1 -1
  334. package/authoring/doctypes/reference/reference.doc.mjs +39 -6
  335. package/authoring/doctypes/reference/type.ts +31 -14
  336. package/authoring/doctypes/schema/parse.d.mts +2 -2
  337. package/authoring/doctypes/schema/parse.mjs +1 -1
  338. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  339. package/authoring/doctypes/schema/type.ts +3 -4
  340. package/authoring/doctypes/template/parse.d.mts +94 -1
  341. package/authoring/doctypes/template/parse.mjs +37 -1
  342. package/authoring/doctypes/template/parse.test.mjs +18 -0
  343. package/authoring/doctypes/template/template.doc.mjs +13 -3
  344. package/authoring/doctypes/template/type.ts +12 -1
  345. package/authoring/doctypes/theme/parse.d.mts +35 -0
  346. package/authoring/doctypes/theme/parse.mjs +76 -0
  347. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  348. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  349. package/authoring/doctypes/theme/type.ts +42 -0
  350. package/authoring/doctypes/types.ts +12 -11
  351. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  352. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  353. package/authoring/gap-report/parse.d.mts +9 -9
  354. package/authoring/gap-report/parse.mjs +6 -6
  355. package/authoring/gap-report/type.ts +1 -1
  356. package/authoring/identity/identity.doc.mjs +3 -2
  357. package/authoring/identity/type.ts +10 -10
  358. package/authoring/index.d.mts +2 -0
  359. package/authoring/index.d.ts +32 -19
  360. package/authoring/index.mjs +3 -1
  361. package/authoring/integration/integration.doc.mjs +2 -2
  362. package/authoring/integration/parse.d.mts +2 -2
  363. package/authoring/integration/parse.mjs +1 -1
  364. package/authoring/integration/schema.d.mts +4 -4
  365. package/authoring/integration/schema.mjs +3 -3
  366. package/authoring/integration/type.ts +5 -11
  367. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  368. package/clients/cli/command-load-failure.test.mjs +83 -0
  369. package/clients/cli/commands/blog.doc.mjs +1 -1
  370. package/clients/cli/commands/blog.mjs +23 -8
  371. package/clients/cli/commands/blog.test.mjs +42 -1
  372. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  373. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  374. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  375. package/clients/cli/commands/build-theme.mjs +16 -50
  376. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  377. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  378. package/clients/cli/commands/build.doc.mjs +16 -8
  379. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  380. package/clients/cli/commands/build.mjs +137 -114
  381. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  382. package/clients/cli/commands/build.text-fields.test.mjs +81 -0
  383. package/clients/cli/commands/component/index.mjs +3 -8
  384. package/clients/cli/commands/component-ownership.test.mjs +3 -3
  385. package/clients/cli/commands/component-package.test.mjs +46 -0
  386. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  387. package/clients/cli/commands/component.doc.mjs +1 -1
  388. package/clients/cli/commands/component.test.mjs +19 -0
  389. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  390. package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
  391. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  392. package/clients/cli/commands/discover.doc.mjs +55 -9
  393. package/clients/cli/commands/discover.mjs +393 -118
  394. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  395. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  396. package/clients/cli/commands/docs.doc.mjs +21 -9
  397. package/clients/cli/commands/docs.mjs +184 -70
  398. package/clients/cli/commands/docs.test.mjs +120 -16
  399. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  400. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
  401. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  402. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  403. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  404. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  405. package/clients/cli/commands/doctor-integration.test.mjs +90 -8
  406. package/clients/cli/commands/doctor.doc.mjs +1 -1
  407. package/clients/cli/commands/doctor.mjs +59 -32
  408. package/clients/cli/commands/doctor.test.mjs +42 -0
  409. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  410. package/clients/cli/commands/gap-report.test.mjs +72 -0
  411. package/clients/cli/commands/hook/index.mjs +7 -17
  412. package/clients/cli/commands/hook.doc.mjs +1 -1
  413. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  414. package/clients/cli/commands/init.doc.mjs +20 -9
  415. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  416. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  417. package/clients/cli/commands/integration-add.doc.mjs +32 -6
  418. package/clients/cli/commands/integration-authoring.test.mjs +13 -9
  419. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  420. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  421. package/clients/cli/commands/integration.doc.mjs +1 -1
  422. package/clients/cli/commands/integration.mjs +1 -0
  423. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  424. package/clients/cli/commands/json-contract.test.mjs +33 -0
  425. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  426. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  427. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  428. package/clients/cli/commands/layout.doc.mjs +3 -3
  429. package/clients/cli/commands/layout.mjs +21 -9
  430. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  431. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  432. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  433. package/clients/cli/commands/manifest.doc.mjs +1 -1
  434. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  435. package/clients/cli/commands/search.doc.mjs +7 -4
  436. package/clients/cli/commands/search.mjs +28 -9
  437. package/clients/cli/commands/search.test.mjs +75 -0
  438. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  439. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  440. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  441. package/clients/cli/commands/template.doc.mjs +52 -13
  442. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  443. package/clients/cli/commands/template.mjs +4 -91
  444. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  445. package/clients/cli/commands/text-json-parity.test.mjs +719 -0
  446. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  447. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  448. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  449. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
  450. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  451. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  452. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  453. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  454. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  455. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  456. package/clients/cli/commands/theme.doc.mjs +1 -1
  457. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  458. package/clients/cli/commands/upgrade.doc.mjs +20 -8
  459. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  460. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  461. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  462. package/clients/cli/commands/upgrade.mjs +29 -7
  463. package/clients/cli/formatters/index.mjs +2 -0
  464. package/clients/cli/formatters/index.test.mjs +6 -0
  465. package/clients/cli/index.mjs +21 -30
  466. package/clients/cli/latest-version-env.test.mjs +50 -0
  467. package/clients/cli/lib/cli-error.test.mjs +7 -0
  468. package/clients/cli/lib/component-format.mjs +9 -9
  469. package/clients/cli/lib/component-format.test.mjs +1 -1
  470. package/clients/cli/lib/define-command.mjs +32 -6
  471. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  472. package/clients/cli/lib/exit-codes.test.mjs +97 -0
  473. package/clients/cli/lib/hook-format.mjs +19 -10
  474. package/clients/cli/lib/json-shim.mjs +38 -2
  475. package/clients/cli/lib/json-shim.test.mjs +83 -0
  476. package/clients/cli/lib/manifest.d.ts +2 -0
  477. package/clients/cli/lib/manifest.mjs +32 -2
  478. package/clients/cli/lib/manifest.test.mjs +17 -0
  479. package/foundation/agent-docs/agent-docs.d.mts +7 -2
  480. package/foundation/agent-docs/agent-docs.mjs +82 -12
  481. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  482. package/foundation/agent-docs/agent-docs.test.mjs +19 -1
  483. package/foundation/config/integration-debug.test.mjs +28 -3
  484. package/foundation/config/project-themes.test.mjs +11 -19
  485. package/foundation/config/project.d.mts +20 -11
  486. package/foundation/config/project.mjs +246 -89
  487. package/foundation/config/project.test.mjs +270 -21
  488. package/foundation/discovery/authoring-self-docs.d.mts +18 -0
  489. package/foundation/discovery/authoring-self-docs.mjs +38 -15
  490. package/foundation/discovery/authoring-self-docs.test.mjs +87 -12
  491. package/foundation/discovery/authoring-surface.d.mts +74 -0
  492. package/foundation/discovery/authoring-surface.mjs +525 -0
  493. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  494. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  495. package/foundation/discovery/cli-self-docs.mjs +490 -0
  496. package/foundation/discovery/cli-self-docs.test.mjs +375 -0
  497. package/foundation/discovery/component-discovery.d.mts +38 -0
  498. package/foundation/discovery/component-discovery.mjs +48 -0
  499. package/foundation/discovery/component-loader.d.mts +35 -38
  500. package/foundation/discovery/component-loader.mjs +53 -222
  501. package/foundation/discovery/docs-discovery.d.mts +114 -9
  502. package/foundation/discovery/docs-discovery.mjs +239 -30
  503. package/foundation/discovery/docs-discovery.test.mjs +150 -35
  504. package/foundation/discovery/docs-output-budget.d.mts +2 -2
  505. package/foundation/discovery/docs-output-budget.mjs +1 -1
  506. package/foundation/discovery/docs-section-key.d.mts +28 -10
  507. package/foundation/discovery/docs-section-key.mjs +134 -33
  508. package/foundation/discovery/docs-section-key.test.mjs +41 -19
  509. package/foundation/discovery/template-adapter.d.mts +113 -11
  510. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  511. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  512. package/foundation/discovery/template-adapter.mjs +772 -82
  513. package/foundation/discovery/template-adapter.test.mjs +57 -0
  514. package/foundation/discovery/template-conflict-release.d.mts +13 -0
  515. package/foundation/discovery/template-conflict-release.mjs +40 -0
  516. package/foundation/discovery/template-conflict-release.test.mjs +40 -0
  517. package/foundation/discovery/theme-discovery.d.mts +67 -7
  518. package/foundation/discovery/theme-discovery.mjs +916 -186
  519. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  520. package/foundation/discovery/theming-targets.test.mjs +4 -0
  521. package/foundation/doc-compiler/bundle.d.mts +47 -0
  522. package/foundation/doc-compiler/bundle.mjs +278 -0
  523. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  524. package/foundation/doc-compiler/compile.d.mts +343 -0
  525. package/foundation/doc-compiler/compile.mjs +558 -0
  526. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  527. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  528. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  529. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  530. package/foundation/doc-compiler/import.d.mts +24 -0
  531. package/foundation/doc-compiler/import.mjs +59 -0
  532. package/foundation/doc-compiler/inputs.d.mts +102 -0
  533. package/foundation/doc-compiler/inputs.mjs +291 -0
  534. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  535. package/foundation/doc-compiler/ir.d.mts +22 -0
  536. package/foundation/doc-compiler/ir.mjs +471 -0
  537. package/foundation/doc-compiler/lenses.d.mts +36 -0
  538. package/foundation/doc-compiler/lenses.mjs +173 -0
  539. package/foundation/doc-compiler/links.d.mts +162 -0
  540. package/foundation/doc-compiler/links.mjs +294 -0
  541. package/foundation/doc-compiler/links.test.mjs +192 -0
  542. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  543. package/foundation/doc-compiler/overlays.d.mts +37 -0
  544. package/foundation/doc-compiler/overlays.mjs +206 -0
  545. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  546. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  547. package/foundation/doc-compiler/read.d.mts +127 -0
  548. package/foundation/doc-compiler/read.mjs +325 -0
  549. package/foundation/doc-compiler/read.test.mjs +313 -0
  550. package/foundation/doc-compiler/source.d.mts +33 -0
  551. package/foundation/doc-compiler/source.mjs +128 -0
  552. package/foundation/doc-compiler/tree.d.mts +288 -0
  553. package/foundation/doc-compiler/tree.mjs +876 -0
  554. package/foundation/doc-compiler/tree.test.mjs +598 -0
  555. package/foundation/fs/file-protection.d.mts +33 -0
  556. package/foundation/fs/file-protection.mjs +825 -0
  557. package/foundation/fs/file-protection.test.mjs +250 -0
  558. package/foundation/fs/module-loader.d.mts +1 -0
  559. package/foundation/fs/module-loader.mjs +50 -1
  560. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  561. package/foundation/fs/path-safety.d.mts +3 -2
  562. package/foundation/fs/path-safety.mjs +49 -19
  563. package/foundation/fs/path-safety.test.mjs +50 -0
  564. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  565. package/foundation/integrations/autolink.d.mts +58 -1
  566. package/foundation/integrations/autolink.mjs +143 -52
  567. package/foundation/integrations/autolink.test.mjs +1 -1
  568. package/foundation/integrations/cli-requirement.d.mts +45 -0
  569. package/foundation/integrations/cli-requirement.mjs +154 -0
  570. package/foundation/integrations/cli-requirement.test.mjs +84 -0
  571. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  572. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  573. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  574. package/foundation/integrations/contribution-inventory.mjs +27 -24
  575. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  576. package/foundation/integrations/integration-warnings.d.mts +9 -2
  577. package/foundation/integrations/integration-warnings.mjs +51 -26
  578. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  579. package/foundation/integrations/integrations.d.mts +17 -1
  580. package/foundation/integrations/integrations.mjs +52 -98
  581. package/foundation/integrations/integrations.test.mjs +31 -0
  582. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  583. package/foundation/integrations/provider-resolution.d.mts +152 -0
  584. package/foundation/integrations/provider-resolution.mjs +576 -0
  585. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  586. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  587. package/foundation/integrations/theme-descriptor.mjs +44 -0
  588. package/foundation/integrations/validate-contributions.mjs +121 -29
  589. package/foundation/response/base.d.ts +8 -4
  590. package/foundation/response/error-codes.d.mts +3 -1
  591. package/foundation/response/error-codes.d.ts +2 -0
  592. package/foundation/response/error-codes.doc.mjs +13 -4
  593. package/foundation/response/error-codes.mjs +8 -2
  594. package/foundation/response/error-codes.test.mjs +137 -10
  595. package/foundation/response/json-contract.test.mjs +11 -0
  596. package/foundation/response/json.d.mts +4 -2
  597. package/foundation/response/json.mjs +8 -10
  598. package/foundation/response/response-types.doc.d.mts +5 -1
  599. package/foundation/response/response-types.doc.mjs +37 -22
  600. package/foundation/response/response-types.doc.test.mjs +158 -0
  601. package/foundation/response/response.doc.mjs +1 -1
  602. package/foundation/text/string-utils.d.mts +8 -0
  603. package/foundation/text/string-utils.mjs +40 -10
  604. package/foundation/xle/expand.d.mts +2 -0
  605. package/foundation/xle/expand.mjs +4 -3
  606. package/foundation/xle/expand.test.mjs +54 -0
  607. package/foundation/xle/xle.test.mjs +13 -0
  608. package/package.json +10 -11
  609. package/assets/templates/themes/manifest.json +0 -95
  610. package/clients/cli/lib/update-check.mjs +0 -83
  611. package/clients/cli/lib/update-check.test.mjs +0 -137
  612. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -0,0 +1,161 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Human output of the `theme` command group stays plain ASCII.
5
+ *
6
+ * Covers every theme-build line family that carried a glyph or typographic
7
+ * punctuation: success, warning, error, notice, and font-help lines of a
8
+ * standalone build; `--check` in both states; a batch build and check; a
9
+ * family build and check; the quoted-glob suggestion; and a palette preview.
10
+ * Each case also asserts its ASCII marker, so a line that stops printing
11
+ * cannot pass the ASCII check vacuously.
12
+ */
13
+
14
+ import {describe, it, expect, beforeAll, beforeEach, afterEach} from 'vitest';
15
+ import * as fs from 'node:fs';
16
+ import * as path from 'node:path';
17
+ import {ensureCoreBuilt} from './ensure-core-built.mjs';
18
+ import {runCli} from '../../../test-utils/run-cli.mjs';
19
+
20
+ // Under the CLI package so fixtures resolve `@astryxdesign/core/theme`.
21
+ const CLI_ROOT = path.resolve(import.meta.dirname, '../../..');
22
+
23
+ const OCEAN = `import {defineTheme} from '@astryxdesign/core/theme';
24
+ export const oceanTheme = defineTheme({
25
+ name: 'ocean',
26
+ typography: {body: {family: 'Inter'}},
27
+ tokens: {'--color-background-body': '#ffffff'},
28
+ components: {
29
+ progressbar: {base: {color: 'red'}},
30
+ button: {base: {'--_button-radius': '2px'}},
31
+ },
32
+ });
33
+ `;
34
+ const CALM = `import {defineTheme} from '@astryxdesign/core/theme';
35
+ import {oceanTheme} from './ocean.mjs';
36
+ export const oceanCalmTheme = defineTheme({
37
+ name: 'ocean-calm',
38
+ extends: oceanTheme,
39
+ tokens: {'--color-background-body': '#eeeeee'},
40
+ });
41
+ `;
42
+
43
+ /** @type {string} */
44
+ let dir;
45
+
46
+ beforeAll(() => {
47
+ ensureCoreBuilt();
48
+ }, 200_000);
49
+
50
+ beforeEach(() => {
51
+ dir = fs.mkdtempSync(path.join(CLI_ROOT, '.tmp-theme-ascii-'));
52
+ fs.writeFileSync(path.join(dir, 'package.json'), '{"type":"module"}\n');
53
+ fs.writeFileSync(path.join(dir, 'ocean.mjs'), OCEAN);
54
+ fs.writeFileSync(path.join(dir, 'ocean-calm.mjs'), CALM);
55
+ });
56
+
57
+ afterEach(() => {
58
+ fs.rmSync(dir, {recursive: true, force: true});
59
+ });
60
+
61
+ /** @param {{stdout: string, stderr: string}} result */
62
+ function nonAscii(result) {
63
+ return [
64
+ ...new Set(`${result.stdout}${result.stderr}`.match(/[\u0080-\uffff]/g)),
65
+ ];
66
+ }
67
+
68
+ /** @param {string[]} args */
69
+ function run(args) {
70
+ return runCli(['theme', ...args], dir);
71
+ }
72
+
73
+ describe('theme command human output is plain ASCII', () => {
74
+ it('a standalone build: ok, warning, error, notice, and font help lines', async () => {
75
+ const result = await run(['build', 'ocean.mjs']);
76
+
77
+ expect(result.code).toBe(0);
78
+ expect(result.stdout).toContain('[ok] ocean.css');
79
+ expect(result.stderr).toContain('[warn] Deprecated component target');
80
+ expect(result.stderr).toContain('[error] Component "button"');
81
+ expect(result.stdout).toContain('note: Font "Inter"');
82
+ expect(result.stdout).toContain('[note] Theme "ocean" names fonts');
83
+ expect(nonAscii(result)).toEqual([]);
84
+ });
85
+
86
+ it('--check, up to date and stale', async () => {
87
+ await run(['build', 'ocean.mjs']);
88
+ const upToDate = await run(['build', 'ocean.mjs', '--check']);
89
+ expect(upToDate.code).toBe(0);
90
+ expect(upToDate.stdout).toContain('[ok] Theme outputs are up to date');
91
+ expect(nonAscii(upToDate)).toEqual([]);
92
+
93
+ fs.appendFileSync(path.join(dir, 'ocean.css'), '/* drift */\n');
94
+ const stale = await run(['build', 'ocean.mjs', '--check']);
95
+ expect(stale.code).toBe(1);
96
+ expect(stale.stderr).toContain('[fail] 1 theme output(s) are out of date');
97
+ expect(nonAscii(stale)).toEqual([]);
98
+ });
99
+
100
+ it('a batch build and check', async () => {
101
+ const built = await run(['build', 'ocean.mjs', 'ocean-calm.mjs']);
102
+ expect(built.code).toBe(0);
103
+ expect(built.stdout).toContain('[ok] Built 2 themes.');
104
+ expect(nonAscii(built)).toEqual([]);
105
+
106
+ const checked = await run([
107
+ 'build',
108
+ 'ocean.mjs',
109
+ 'ocean-calm.mjs',
110
+ '--check',
111
+ ]);
112
+ expect(checked.code).toBe(0);
113
+ expect(checked.stdout).toContain('[ok] Checked 2 themes.');
114
+ expect(nonAscii(checked)).toEqual([]);
115
+ });
116
+
117
+ it('a family build and a stale family check', async () => {
118
+ const familyArgs = [
119
+ 'build',
120
+ '--family',
121
+ 'ocean.mjs',
122
+ 'ocean-calm.mjs',
123
+ '--family-key',
124
+ 'ocean-family',
125
+ ];
126
+ const built = await run(familyArgs);
127
+ expect(built.code).toBe(0);
128
+ expect(built.stdout).toContain('[ok] ocean-family.css');
129
+ expect(nonAscii(built)).toEqual([]);
130
+
131
+ fs.rmSync(path.join(dir, 'ocean-family.js'));
132
+ const stale = await run([...familyArgs, '--check']);
133
+ expect(stale.code).toBe(1);
134
+ expect(stale.stderr).toContain('[fail] 1 theme family output(s)');
135
+ expect(nonAscii(stale)).toEqual([]);
136
+ });
137
+
138
+ it('the suggestion for a quoted glob', async () => {
139
+ const result = await run(['build', 'themes/*.mjs']);
140
+
141
+ expect(result.code).toBe(1);
142
+ expect(result.stderr).toContain('globs are expanded by your shell');
143
+ expect(nonAscii(result)).toEqual([]);
144
+ });
145
+
146
+ it('a palette candidate preview', async () => {
147
+ fs.writeFileSync(
148
+ path.join(dir, 'palette.config.json'),
149
+ JSON.stringify({
150
+ modeStrategy: 'dark-only',
151
+ stops: [10, 50, 90],
152
+ families: [{id: 'blue', seed: '#0074e2'}],
153
+ }),
154
+ );
155
+ const result = await run(['palette', 'generate', 'palette.config.json']);
156
+
157
+ expect(result.code).toBe(0);
158
+ expect(result.stdout).toContain('1 families, 3 stops, dark');
159
+ expect(nonAscii(result)).toEqual([]);
160
+ });
161
+ });
@@ -0,0 +1,110 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Every `theme build` flag interaction is discoverable.
5
+ *
6
+ * Each combination the command refuses is refused before any work, and the
7
+ * refusal is named in the machine-readable manifest's description of at least
8
+ * one of the flags involved. Flags that fill in a value when omitted state
9
+ * their default there too.
10
+ */
11
+
12
+ import {describe, it, expect, beforeAll, afterAll} from 'vitest';
13
+ import * as fs from 'node:fs';
14
+ import * as os from 'node:os';
15
+ import * as path from 'node:path';
16
+ import {runCli} from '../../../test-utils/run-cli.mjs';
17
+ import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
18
+
19
+ /** @type {string} */
20
+ let dir;
21
+ /** @type {Map<string, string>} flag token -> manifest description */
22
+ let descriptions;
23
+
24
+ beforeAll(async () => {
25
+ dir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-theme-flag-docs-'));
26
+ // Refusals happen before a theme loads; the files only need to exist.
27
+ for (const name of ['a.mjs', 'b.mjs']) {
28
+ fs.writeFileSync(path.join(dir, name), 'export default {};\n');
29
+ }
30
+
31
+ const manifest = JSON.parse(
32
+ (await runCli(['--json', 'manifest'], dir)).stdout,
33
+ ).data;
34
+ const theme = manifest.commands.find(command => command.name === 'theme');
35
+ const build = theme.subcommands.find(
36
+ command => command.name === 'theme build',
37
+ );
38
+ descriptions = new Map(
39
+ build.options.map(option => [
40
+ /** @type {string} */ (option.flag.match(/--[a-z-]+/)?.[0]),
41
+ option.description,
42
+ ]),
43
+ );
44
+ });
45
+
46
+ afterAll(() => {
47
+ fs.rmSync(dir, {recursive: true, force: true});
48
+ });
49
+
50
+ /** @param {string} flag */
51
+ function description(flag) {
52
+ const text = descriptions.get(flag);
53
+ expect(text, `manifest has no ${flag} option`).toBeDefined();
54
+ return /** @type {string} */ (text);
55
+ }
56
+
57
+ /**
58
+ * Whether `a`'s description names `b`, or `b`'s names `a`. `b` may also be a
59
+ * pattern for a condition that is not a flag.
60
+ * @param {string} a
61
+ * @param {string | RegExp} b
62
+ */
63
+ function documented(a, b) {
64
+ const partner = typeof b === 'string' ? new RegExp(`${b}\\b`) : b;
65
+ if (partner.test(description(a))) return true;
66
+ return (
67
+ typeof b === 'string' &&
68
+ descriptions.has(b) &&
69
+ new RegExp(`${a}\\b`).test(description(b))
70
+ );
71
+ }
72
+
73
+ const REFUSED = [
74
+ {
75
+ pair: ['--family', '--out'],
76
+ args: ['--family', 'a.mjs', 'b.mjs', '--family-key', 'k', '--out', 'x.css'],
77
+ },
78
+ {
79
+ pair: ['--family', '--watch'],
80
+ args: ['--family', 'a.mjs', 'b.mjs', '--family-key', 'k', '--watch'],
81
+ },
82
+ {pair: ['--family', '--family-key'], args: ['--family', 'a.mjs', 'b.mjs']},
83
+ {pair: ['--family-key', '--family'], args: ['a.mjs', '--family-key', 'k']},
84
+ {pair: ['--check', '--watch'], args: ['a.mjs', '--check', '--watch']},
85
+ {
86
+ pair: ['--out', /several|more than one|single theme|one theme/i],
87
+ args: ['a.mjs', 'b.mjs', '--out', 'x.css'],
88
+ },
89
+ {pair: ['--watch', '--json'], args: ['a.mjs', '--watch']},
90
+ ];
91
+
92
+ describe('theme build flag interactions are documented', () => {
93
+ for (const {pair, args} of REFUSED) {
94
+ const [a, b] = pair;
95
+ it(`${a} with ${String(b)} is refused and documented`, async () => {
96
+ const result = await runCli(['--json', 'theme', 'build', ...args], dir);
97
+
98
+ expect(result.code).toBe(1);
99
+ expect(JSON.parse(result.stdout).code).toBe(
100
+ ERROR_CODES.ERR_THEME_INVALID,
101
+ );
102
+ expect(documented(a, b)).toBe(true);
103
+ });
104
+ }
105
+
106
+ it('flags that fill in an omitted value state their default', () => {
107
+ expect(description('--out')).toMatch(/default/i);
108
+ expect(description('--icons-specifier')).toMatch(/default/i);
109
+ });
110
+ });
@@ -33,7 +33,7 @@ import {fileURLToPath} from 'node:url';
33
33
  import {spawn} from 'node:child_process';
34
34
  import {getCliInvocation} from '../../../foundation/env/package-manager.mjs';
35
35
  import {jsonOut} from '../../../foundation/response/json.mjs';
36
- import {emit, section, text, list, code} from '../formatters/index.mjs';
36
+ import {emit, section, text, list, records, code} from '../formatters/index.mjs';
37
37
  import {logger} from '../../../api/logger.mjs';
38
38
  import {cliError} from '../lib/cli-error.mjs';
39
39
  import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
@@ -196,7 +196,7 @@ async function warnOnThemeIntegrationIssues(json) {
196
196
  try {
197
197
  const project = await Project.load(process.cwd());
198
198
  await project.themes();
199
- await warnOnIntegrationIssues(project.loadedIntegrations, {json});
199
+ await warnOnIntegrationIssues(project, {json});
200
200
  } catch {
201
201
  // Never let the nudge break the command.
202
202
  }
@@ -229,47 +229,6 @@ function printThemeList(themes) {
229
229
  );
230
230
  }
231
231
 
232
- /**
233
- * Render the targets as one greppable line each, under an aligned header. A
234
- * `records()` block would be five lines per target — over a thousand for the
235
- * full surface, which is the view this command exists to make readable.
236
- * @param {import('../../../api/theme/theme.type.mjs').ThemeTargetEntry[]} targets
237
- * @returns {string}
238
- */
239
- function formatTargetsTable(targets) {
240
- const rows = targets.map(t => ({
241
- key: t.deprecatedFor
242
- ? `${t.key} [deprecated; use ${t.deprecatedFor}]`
243
- : t.key,
244
- component: t.component,
245
- props: t.props.join(', ') || '-',
246
- states: t.states.join(', ') || '-',
247
- }));
248
- const head = {
249
- key: 'key',
250
- component: 'component',
251
- props: 'props',
252
- states: 'states',
253
- };
254
- const width = (/** @type {'key'|'component'|'props'} */ field) =>
255
- [head, ...rows].reduce((max, r) => Math.max(max, r[field].length), 0);
256
- const w = {
257
- key: width('key'),
258
- component: width('component'),
259
- props: width('props'),
260
- };
261
- const line = (/** @type {typeof head} */ r) =>
262
- [
263
- r.key.padEnd(w.key),
264
- r.component.padEnd(w.component),
265
- r.props.padEnd(w.props),
266
- r.states,
267
- ]
268
- .join(' ')
269
- .trimEnd();
270
- return [line(head), ...rows.map(line)].join('\n');
271
- }
272
-
273
232
  /**
274
233
  * @param {import('commander').Command} program
275
234
  */
@@ -369,7 +328,7 @@ export function registerTheme(program) {
369
328
  emit(
370
329
  section(
371
330
  'Palette candidate',
372
- `${result.data.familyCount} families · ${result.data.stopCount} stops · ${result.data.modes.join(', ')}`,
331
+ `${result.data.familyCount} families, ${result.data.stopCount} stops, ${result.data.modes.join(', ')}`,
373
332
  ),
374
333
  code(serializePaletteCandidate(result.data.candidate).trimEnd()),
375
334
  );
@@ -426,7 +385,7 @@ export function registerTheme(program) {
426
385
  {
427
386
  name: `astryx theme build ${entry.file.replace(/['"]/g, '')}`,
428
387
  reason:
429
- 'globs are expanded by your shell — pass the pattern unquoted, or list the files',
388
+ 'globs are expanded by your shell; pass the pattern unquoted, or list the files',
430
389
  },
431
390
  ]
432
391
  : undefined,
@@ -491,7 +450,7 @@ export function registerTheme(program) {
491
450
  // Non-watch: delegate to the API compiler, once per theme, in argument
492
451
  // order. Enable human output unless in --json mode (log → stdout via
493
452
  // humanLog, warn/error → stderr). The "Building theme from" line, the
494
- // ✓/warning lines, and the install instructions are all emitted from
453
+ // [ok]/[warn] lines, and the install instructions are all emitted from
495
454
  // inside themeBuild via the shared logger.
496
455
  logger.setSilent(json);
497
456
 
@@ -574,8 +533,8 @@ export function registerTheme(program) {
574
533
  emit(
575
534
  text(
576
535
  options.check
577
- ? `\n${stale ? '✗' : '✓'} Checked ${entries.length} themes.`
578
- : `\n✓ Built ${entries.length} themes.`,
536
+ ? `\n${stale ? '[fail]' : '[ok]'} Checked ${entries.length} themes.`
537
+ : `\n[ok] Built ${entries.length} themes.`,
579
538
  ),
580
539
  );
581
540
  }
@@ -811,9 +770,16 @@ export function registerTheme(program) {
811
770
  emit(
812
771
  section(
813
772
  'Theming targets',
814
- `${targets.length} across ${componentCount} component${componentCount === 1 ? '' : 's'}`,
773
+ `${targets.length} across ${componentCount} component${componentCount === 1 ? '' : 's'}\n(key - component - props - states - className - deprecatedFor)`,
815
774
  ),
816
- text(formatTargetsTable(targets)),
775
+ records(targets, {
776
+ fields: ['key', 'component', 'props', 'states', 'className', 'deprecatedFor'],
777
+ layout: 'inline',
778
+ format: {
779
+ deprecatedFor: (/** @type {string|null} */ v) =>
780
+ v ? `deprecated; use ${v}` : '',
781
+ },
782
+ }),
817
783
  text(
818
784
  [
819
785
  `Each key goes under \`components\` in defineTheme; it paints \`.astryx-<key>\`.`,
@@ -7,15 +7,21 @@
7
7
  * - Theme name with `..` segments cannot escape the output directory.
8
8
  * - Theme name with `/` is rejected with a clear error (vs. ENOENT).
9
9
  * - Multi-file write is atomic: if one file fails, none are left behind.
10
+ * - An `--out` escape, or an output directory that cannot be created, fails
11
+ * with a registered error code.
10
12
  *
11
13
  * Runs the CLI in-process (shared runCli harness) against a tiny synthetic theme file.
12
14
  */
13
15
 
14
- import {describe, it, expect, beforeEach, afterEach} from 'vitest';
16
+ import {describe, it, expect, beforeAll, beforeEach, afterEach} from 'vitest';
15
17
  import * as fs from 'node:fs';
16
18
  import * as path from 'node:path';
17
19
  import * as os from 'node:os';
20
+ import {ensureCoreBuilt} from './ensure-core-built.mjs';
18
21
  import {runCli} from '../../../test-utils/run-cli.mjs';
22
+ import {themeBuild} from '../../../api/theme/build/build.mjs';
23
+ import {AstryxError} from '../../../api/error.mjs';
24
+ import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
19
25
 
20
26
  function writeTheme(dir, name) {
21
27
  fs.mkdirSync(dir, {recursive: true});
@@ -93,3 +99,82 @@ describe('theme build path safety', () => {
93
99
  expect(entries).toEqual(['theme.mjs']);
94
100
  });
95
101
  });
102
+
103
+ describe('theme build output-path failures carry registered codes', () => {
104
+ // These reach the output-path step, which runs after CSS generation.
105
+ beforeAll(() => {
106
+ ensureCoreBuilt();
107
+ }, 200_000);
108
+
109
+ const registered = new Set(Object.values(ERROR_CODES));
110
+
111
+ /** @param {string[]} args @param {string} cwd */
112
+ async function buildJson(args, cwd) {
113
+ const result = await runCli(['--json', 'theme', 'build', ...args], cwd);
114
+ return {result, envelope: JSON.parse(result.stdout)};
115
+ }
116
+
117
+ it('reports an --out path outside the project as ERR_PATH_TRAVERSAL', async () => {
118
+ const project = path.join(tmpDir, 'project');
119
+ const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
120
+
121
+ const {result, envelope} = await buildJson(
122
+ [path.relative(project, themeFile), '--out', '../escaped.css'],
123
+ project,
124
+ );
125
+
126
+ expect(result.code).toBe(1);
127
+ expect(envelope.code).toBe(ERROR_CODES.ERR_PATH_TRAVERSAL);
128
+ expect(registered.has(envelope.code)).toBe(true);
129
+ expect(fs.existsSync(path.join(tmpDir, 'escaped.css'))).toBe(false);
130
+ });
131
+
132
+ it('reports an --out path that escapes through a symlink as ERR_PATH_TRAVERSAL', async () => {
133
+ const project = path.join(tmpDir, 'project');
134
+ const outside = path.join(tmpDir, 'outside');
135
+ fs.mkdirSync(outside, {recursive: true});
136
+ const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
137
+ fs.symlinkSync(outside, path.join(project, 'link'), 'dir');
138
+
139
+ const {result, envelope} = await buildJson(
140
+ [path.relative(project, themeFile), '--out', 'link/escaped.css'],
141
+ project,
142
+ );
143
+
144
+ expect(result.code).toBe(1);
145
+ expect(envelope.code).toBe(ERROR_CODES.ERR_PATH_TRAVERSAL);
146
+ expect(fs.readdirSync(outside)).toEqual([]);
147
+ });
148
+
149
+ it('reports an output directory that cannot be created as ERR_WRITE_FAILED', async () => {
150
+ const project = path.join(tmpDir, 'project');
151
+ const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
152
+ // A regular file where the output directory would have to be created.
153
+ fs.writeFileSync(path.join(project, 'blocker'), '');
154
+
155
+ const {result, envelope} = await buildJson(
156
+ [path.relative(project, themeFile), '--out', 'blocker/ocean.css'],
157
+ project,
158
+ );
159
+
160
+ expect(result.code).toBe(1);
161
+ expect(envelope.code).toBe(ERROR_CODES.ERR_WRITE_FAILED);
162
+ expect(registered.has(envelope.code)).toBe(true);
163
+ });
164
+
165
+ it('themeBuild() rejects an escaping out path with an AstryxError', async () => {
166
+ const project = path.join(tmpDir, 'project');
167
+ const themeFile = writeTheme(path.join(project, 'themes'), 'ocean');
168
+
169
+ const build = themeBuild(
170
+ path.relative(project, themeFile),
171
+ {out: '../escaped.css'},
172
+ {cwd: project},
173
+ );
174
+
175
+ await expect(build).rejects.toBeInstanceOf(AstryxError);
176
+ await expect(build).rejects.toMatchObject({
177
+ code: ERROR_CODES.ERR_PATH_TRAVERSAL,
178
+ });
179
+ });
180
+ });
@@ -324,6 +324,82 @@ describe('theme build custom-variant augmentations', () => {
324
324
  );
325
325
  });
326
326
 
327
+ it('rejects a custom Heading type whose only declaration is blank', async () => {
328
+ const themeFile = writeTheme(
329
+ tmpDir,
330
+ `export default {
331
+ name: 'variants-theme',
332
+ tokens: { '--color-bg': '#fff' },
333
+ components: { heading: { 'type:hero': { fontSize: '' } } },
334
+ };\n`,
335
+ );
336
+
337
+ const result = await runCli(
338
+ ['theme', 'build', path.relative(tmpDir, themeFile)],
339
+ tmpDir,
340
+ );
341
+
342
+ expect(result.code).toBe(1);
343
+ expect(result.stderr).toContain(
344
+ 'Custom Heading type "hero" needs a non-empty standalone',
345
+ );
346
+ expect(fs.existsSync(path.join(tmpDir, 'variants-theme.css'))).toBe(false);
347
+ });
348
+
349
+ it('rejects a custom Heading type whose every declaration the compiler drops', async () => {
350
+ const themeFile = writeTheme(
351
+ tmpDir,
352
+ `export default {
353
+ name: 'variants-theme',
354
+ tokens: { '--color-bg': '#fff' },
355
+ components: {
356
+ heading: { 'type:hero': { color: 'red; } body { color: blue' } },
357
+ },
358
+ };\n`,
359
+ );
360
+
361
+ const result = await runCli(
362
+ ['--json', 'theme', 'build', path.relative(tmpDir, themeFile)],
363
+ tmpDir,
364
+ );
365
+
366
+ expect(result.code).toBe(1);
367
+ const envelope = JSON.parse(result.stdout);
368
+ expect(envelope.code).toBe('ERR_THEME_INVALID');
369
+ expect(envelope.error).toContain('Custom Heading type "hero"');
370
+ expect(fs.existsSync(path.join(tmpDir, 'variants-theme.css'))).toBe(false);
371
+ expect(
372
+ fs.existsSync(path.join(tmpDir, 'variants-theme.variants.d.ts')),
373
+ ).toBe(false);
374
+ });
375
+
376
+ it('builds a custom Heading type that keeps one valid declaration', async () => {
377
+ const themeFile = writeTheme(
378
+ tmpDir,
379
+ `export default {
380
+ name: 'variants-theme',
381
+ tokens: { '--color-bg': '#fff' },
382
+ components: {
383
+ heading: {
384
+ 'type:hero': { fontSize: '80px', color: 'red; } body { color: blue' },
385
+ },
386
+ },
387
+ };\n`,
388
+ );
389
+
390
+ const result = await runCli(
391
+ ['--json', 'theme', 'build', path.relative(tmpDir, themeFile)],
392
+ tmpDir,
393
+ );
394
+
395
+ expect(result.code).toBe(0);
396
+ const envelope = JSON.parse(result.stdout);
397
+ expect(envelope.data.outputs.variantsDts).toBe(
398
+ 'variants-theme.variants.d.ts',
399
+ );
400
+ expect(envelope.data.warnings.join('\n')).toContain('Declaration dropped');
401
+ });
402
+
327
403
  it('makes generated custom component prop values type-check through public subpaths', async () => {
328
404
  const themeFile = writeTheme(
329
405
  tmpDir,
@@ -12,13 +12,14 @@ export const doc = {
12
12
  type: 'command',
13
13
  name: 'build',
14
14
  displayName: 'astryx build',
15
- namespace: 'cli',
15
+ namespace: 'cli/commands',
16
16
  summary:
17
- 'Build a page: composition kit for an idea, or the workflow playbook (no args)',
17
+ 'Build a page: the template to start from, or the workflow playbook (no query)',
18
18
  description:
19
- 'The assemble-a-page entry point. With no query it returns the how-to-build-a-page ' +
20
- 'playbook; with a query it groups the unified search hits into a composition kit: ' +
21
- 'the closest templates, drop-in blocks, and idea-specific components and hooks.',
19
+ 'The build-a-page entry point. With no query it returns the how-to-build-a-page ' +
20
+ 'playbook; with a query it names the page template to start from (always one: the ' +
21
+ 'closest page template, or the app shell when none matches), the next two templates, and the ' +
22
+ 'drop-in blocks and idea-specific components and hooks around it.',
22
23
  fn: 'build',
23
24
  args: [{name: 'query', param: 'query', required: false}],
24
25
  options: [
@@ -35,16 +36,23 @@ export const doc = {
35
36
  },
36
37
  {
37
38
  flag: '--verbose',
38
- description: 'Verbose output (include import paths and match reason)',
39
+ description:
40
+ 'Verbose output (every block and component, full descriptions, import paths and match reason)',
39
41
  },
40
42
  ],
41
43
  examples: [
42
44
  {label: 'Get the playbook', cli: 'astryx build'},
43
- {label: 'Compose a page', cli: 'astryx build "analytics dashboard" --json'},
45
+ {
46
+ label: 'Find the template to start from',
47
+ cli: 'astryx build "analytics dashboard" --json',
48
+ },
44
49
  ],
45
50
  exitCodes: [
46
51
  {code: 0, when: 'success (including zero matches)'},
47
- {code: 1, when: 'invalid --type or a non-positive --limit'},
52
+ {
53
+ code: 1,
54
+ when: 'invalid --type, a non-positive --limit, or a query when @astryxdesign/core cannot be found (the playbook needs no core)',
55
+ },
48
56
  ],
49
57
  related: ['search', 'template', 'component', 'hook', 'init'],
50
58
  };
@@ -0,0 +1,50 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file `astryx build` documents that a query needs @astryxdesign/core while
5
+ * the playbook does not, and exits as documented without it.
6
+ */
7
+
8
+ import {describe, it, expect, beforeEach, afterEach} from 'vitest';
9
+ import * as fs from 'node:fs';
10
+ import * as os from 'node:os';
11
+ import * as path from 'node:path';
12
+ import {runCli} from '../../../test-utils/run-cli.mjs';
13
+ import {doc as buildDoc} from './build.doc.mjs';
14
+
15
+ const SLOW = 30_000;
16
+
17
+ /** @type {string} */
18
+ let tmpDir;
19
+
20
+ beforeEach(() => {
21
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-build-no-core-'));
22
+ fs.writeFileSync(path.join(tmpDir, 'package.json'), JSON.stringify({name: 'consumer'}));
23
+ });
24
+
25
+ afterEach(() => {
26
+ fs.rmSync(tmpDir, {recursive: true, force: true});
27
+ });
28
+
29
+ /** @param {number} code */
30
+ const exitWhen = code => buildDoc.exitCodes?.find(e => e.code === code)?.when ?? '';
31
+
32
+ describe('astryx build without @astryxdesign/core', () => {
33
+ it('the CommandDoc lists a query without core under exit 1, and both modes exit 1', async () => {
34
+ expect(exitWhen(1)).toMatch(/a query when @astryxdesign\/core cannot be found/);
35
+
36
+ const text = await runCli(['build', 'dashboard'], tmpDir);
37
+ const json = await runCli(['--json', 'build', 'dashboard'], tmpDir);
38
+ expect(text.status).toBe(1);
39
+ expect(json.status).toBe(1);
40
+ expect(JSON.parse(json.stdout).error).toMatch(/@astryxdesign\/core/);
41
+ }, SLOW);
42
+
43
+ it('the CommandDoc says the playbook needs no core, and it exits 0', async () => {
44
+ expect(exitWhen(1)).toMatch(/the playbook needs no core/);
45
+
46
+ const {status, stdout} = await runCli(['--json', 'build'], tmpDir);
47
+ expect(status).toBe(0);
48
+ expect(JSON.parse(stdout).type).toBe('build.help');
49
+ }, SLOW);
50
+ });