@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,111 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * Every field `themeBuild()` returns is named in its FunctionDoc and in the
5
+ * response-types doc.
6
+ *
7
+ * The receipt is a stable machine-readable response, so each field needs
8
+ * consumer documentation, not only a typedef. The fields are read off a real
9
+ * build, so a field added to the receipt without documentation fails here.
10
+ */
11
+
12
+ import {describe, it, expect, beforeAll, afterEach} 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 {themeBuild} from './build.mjs';
17
+ import {doc} from '../themeBuild.doc.mjs';
18
+ import {doc as responseTypes} from '../../../foundation/response/response-types.doc.mjs';
19
+ import {ensureCoreBuilt} from '../../../clients/cli/commands/ensure-core-built.mjs';
20
+
21
+ /** @type {string[]} */
22
+ const dirs = [];
23
+
24
+ beforeAll(() => {
25
+ ensureCoreBuilt();
26
+ }, 200_000);
27
+
28
+ afterEach(() => {
29
+ for (const dir of dirs.splice(0)) {
30
+ fs.rmSync(dir, {recursive: true, force: true});
31
+ }
32
+ });
33
+
34
+ /** @returns {string} a temp dir holding a theme that exercises every field */
35
+ function themeDir() {
36
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-receipt-doc-'));
37
+ dirs.push(dir);
38
+ fs.writeFileSync(
39
+ path.join(dir, 'ocean.mjs'),
40
+ `export default {
41
+ name: 'ocean',
42
+ tokens: {'--color-background-body': '#ffffff', '--font-family-body': '"Inter", sans-serif'},
43
+ components: {progressbar: {base: {color: 'red'}}},
44
+ };
45
+ `,
46
+ );
47
+ return dir;
48
+ }
49
+
50
+ /** @param {string} type */
51
+ function returnsDescription(type) {
52
+ const entry = doc.returns?.find(r => r.type === type);
53
+ expect(entry, `themeBuild doc has no ${type} return`).toBeDefined();
54
+ return /** @type {{description: string}} */ (entry).description;
55
+ }
56
+
57
+ /** @param {string} description @param {string[]} fields */
58
+ function undocumented(description, fields) {
59
+ return fields.filter(
60
+ field => !new RegExp(String.raw`\b${field}\b`).test(description),
61
+ );
62
+ }
63
+
64
+ describe('themeBuild() consumer docs name every receipt field', () => {
65
+ it('theme.build', async () => {
66
+ const dir = themeDir();
67
+ const result = await themeBuild('ocean.mjs', {}, {cwd: dir});
68
+
69
+ expect(result?.type).toBe('theme.build');
70
+ const data = /** @type {Record<string, any>} */ (result?.data);
71
+ // The theme is chosen so the optional arrays are non-empty.
72
+ expect(data.warnings.length).toBeGreaterThan(0);
73
+ expect(data.notices.length).toBeGreaterThan(0);
74
+
75
+ const fields = [
76
+ ...Object.keys(data),
77
+ ...Object.keys(data.outputs),
78
+ 'variantsDts',
79
+ ];
80
+ expect(undocumented(returnsDescription('theme.build'), fields)).toEqual([]);
81
+ });
82
+
83
+ it('theme.build in the response-types doc', async () => {
84
+ const dir = themeDir();
85
+ const result = await themeBuild('ocean.mjs', {}, {cwd: dir});
86
+ const data = /** @type {Record<string, any>} */ (result?.data);
87
+ const member = responseTypes.members.find(m => m.value === 'theme.build');
88
+ expect(member, 'response-types has no theme.build member').toBeDefined();
89
+
90
+ const fields = [
91
+ ...Object.keys(data),
92
+ ...Object.keys(data.outputs),
93
+ 'variantsDts',
94
+ ];
95
+ expect(
96
+ undocumented(/** @type {{description: string}} */ (member).description, fields),
97
+ ).toEqual([]);
98
+ });
99
+
100
+ it('theme.build.check', async () => {
101
+ const dir = themeDir();
102
+ const result = await themeBuild('ocean.mjs', {check: true}, {cwd: dir});
103
+
104
+ expect(result?.type).toBe('theme.build.check');
105
+ const data = /** @type {Record<string, any>} */ (result?.data);
106
+ const fields = [...Object.keys(data), ...Object.keys(data.stale[0])];
107
+ expect(
108
+ undocumented(returnsDescription('theme.build.check'), fields),
109
+ ).toEqual([]);
110
+ });
111
+ });
@@ -0,0 +1,148 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * `theme build` writes its CSS, JS, and declarations as one transaction: when
5
+ * a later output fails to publish, every output it already replaced gets its
6
+ * previous bytes back and every output it created is removed. Publishing is
7
+ * forced to fail by wrapping the two calls that publish a staged file:
8
+ * `linkSync` for a new file and `renameSync` for a replacement.
9
+ *
10
+ * Separate file because vi.mock is hoisted and affects the whole module.
11
+ * `themeBuild` needs a built core; the `node` project's globalSetup builds it.
12
+ */
13
+
14
+ import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
15
+ import * as os from 'node:os';
16
+ import * as path from 'node:path';
17
+
18
+ const failures = vi.hoisted(() => ({
19
+ /** Fail the Nth staged-file publish (1-based); 0 disables. */
20
+ publish: 0,
21
+ count: 0,
22
+ }));
23
+
24
+ vi.mock('node:fs', async importOriginal => {
25
+ const actual = /** @type {typeof import('node:fs')} */ (
26
+ await importOriginal()
27
+ );
28
+ /** @param {string} source @param {string} op */
29
+ const maybeFail = (source, op) => {
30
+ if (!path.basename(String(source)).includes('.tmp')) return;
31
+ if (failures.publish === 0) return;
32
+ failures.count++;
33
+ if (failures.count === failures.publish) {
34
+ throw Object.assign(new Error(`EIO: forced ${op} failure`), {
35
+ code: 'EIO',
36
+ });
37
+ }
38
+ };
39
+ return {
40
+ ...actual,
41
+ linkSync: vi.fn((source, destination) => {
42
+ maybeFail(source, 'link');
43
+ return actual.linkSync(source, destination);
44
+ }),
45
+ renameSync: vi.fn((source, destination) => {
46
+ maybeFail(source, 'rename');
47
+ return actual.renameSync(source, destination);
48
+ }),
49
+ };
50
+ });
51
+
52
+ const fs = await import('node:fs');
53
+ const {themeBuild} = await import('./build.mjs');
54
+
55
+ vi.setConfig({testTimeout: 30000});
56
+
57
+ let tmpDir;
58
+
59
+ beforeEach(() => {
60
+ tmpDir = fs.mkdtempSync(
61
+ path.join(os.tmpdir(), 'astryx-theme-build-rollback-'),
62
+ );
63
+ failures.publish = 0;
64
+ failures.count = 0;
65
+ });
66
+
67
+ afterEach(() => {
68
+ failures.publish = 0;
69
+ fs.rmSync(tmpDir, {recursive: true, force: true});
70
+ });
71
+
72
+ /**
73
+ * Write a source for the theme named `rollbacktheme`. Each call uses a new
74
+ * file so the loader cannot serve an earlier version from its cache.
75
+ * @param {string} file @param {string} background
76
+ */
77
+ function writeTheme(file, background) {
78
+ fs.writeFileSync(
79
+ path.join(tmpDir, file),
80
+ `export default { name: 'rollbacktheme', tokens: { '--color-bg': '${background}' } };\n`,
81
+ );
82
+ return file;
83
+ }
84
+
85
+ const OUTPUTS = ['rollbacktheme.css', 'rollbacktheme.js', 'rollbacktheme.d.ts'];
86
+
87
+ /** @returns {Map<string, Buffer | null>} */
88
+ function readOutputs() {
89
+ return new Map(
90
+ OUTPUTS.map(name => {
91
+ const file = path.join(tmpDir, name);
92
+ return [name, fs.existsSync(file) ? fs.readFileSync(file) : null];
93
+ }),
94
+ );
95
+ }
96
+
97
+ function strays() {
98
+ return fs
99
+ .readdirSync(tmpDir)
100
+ .filter(name => name.includes('.tmp') || name.includes('.restore-'));
101
+ }
102
+
103
+ describe('themeBuild rolls back a partial write', () => {
104
+ it('removes every created output when the second publish fails', async () => {
105
+ const source = writeTheme('first.mjs', '#0a0a0a');
106
+ failures.publish = 2;
107
+
108
+ await expect(themeBuild(source, {}, {cwd: tmpDir})).rejects.toMatchObject({
109
+ code: 'ERR_WRITE_FAILED',
110
+ });
111
+
112
+ for (const bytes of readOutputs().values()) expect(bytes).toBeNull();
113
+ expect(strays()).toEqual([]);
114
+ });
115
+
116
+ it('restores every replaced output when the second publish fails', async () => {
117
+ const first = await themeBuild(
118
+ writeTheme('first.mjs', '#0a0a0a'),
119
+ {},
120
+ {cwd: tmpDir},
121
+ );
122
+ expect(first?.type).toBe('theme.build');
123
+ const before = readOutputs();
124
+ for (const bytes of before.values()) expect(bytes).not.toBeNull();
125
+
126
+ const next = writeTheme('next.mjs', '#fafafa');
127
+ failures.publish = 2;
128
+ await expect(themeBuild(next, {}, {cwd: tmpDir})).rejects.toMatchObject({
129
+ code: 'ERR_WRITE_FAILED',
130
+ });
131
+
132
+ const after = readOutputs();
133
+ for (const name of OUTPUTS) {
134
+ expect(
135
+ after.get(name)?.equals(/** @type {Buffer} */ (before.get(name))),
136
+ ).toBe(true);
137
+ }
138
+
139
+ // The failed build really had different bytes to write.
140
+ failures.publish = 0;
141
+ await themeBuild(next, {}, {cwd: tmpDir});
142
+ const css = readOutputs().get('rollbacktheme.css');
143
+ expect(
144
+ css?.equals(/** @type {Buffer} */ (before.get('rollbacktheme.css'))),
145
+ ).toBe(false);
146
+ expect(strays()).toEqual([]);
147
+ });
148
+ });
@@ -206,6 +206,133 @@ describe('themeBuild() — receipt', () => {
206
206
  });
207
207
  });
208
208
 
209
+ describe('themeBuild() — dropped declarations reach the receipt', () => {
210
+ // Core's generator refuses a declaration whose value would end it early
211
+ // (an unquoted `;` or brace, an unclosed string/comment/url). The runtime
212
+ // says so on the console; a build has a receipt, so every drop must land in
213
+ // `warnings` — a programmatic caller otherwise sees `warnings: []` while the
214
+ // CSS silently omits a value the generated JS still carries.
215
+ it('reports every dropped declaration, from every generator path, in warnings', async () => {
216
+ const themeFile = path.join(tmpDir, 'dropped.mjs');
217
+ fs.writeFileSync(
218
+ themeFile,
219
+ `export default {
220
+ name: 'dropped',
221
+ tokens: {
222
+ '--color-bg': '#0a0a0a } body { background: url(https://example.com/token) ',
223
+ },
224
+ components: {
225
+ button: {
226
+ 'variant:secondary': {
227
+ backgroundColor: 'red; background-image: url(https://example.com/component)',
228
+ ':hover': {color: '"https://example.com/pseudo'},
229
+ },
230
+ },
231
+ },
232
+ onDark: {
233
+ tokens: {'--color-bg': 'url(https://example.com/dark'},
234
+ },
235
+ adaptations: {
236
+ rules: [
237
+ {
238
+ when: {pointer: 'coarse'},
239
+ value: {tokens: {'--color-bg': 'red /* https://example.com/adaptation'}},
240
+ },
241
+ ],
242
+ },
243
+ };\n`,
244
+ );
245
+
246
+ const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
247
+ let result;
248
+ try {
249
+ result = await themeBuild('dropped.mjs', {}, {cwd: tmpDir});
250
+ // Drops are collected, not printed: the programmatic API stays silent.
251
+ expect(warnSpy).not.toHaveBeenCalled();
252
+ } finally {
253
+ warnSpy.mockRestore();
254
+ }
255
+
256
+ const css = fs.readFileSync(path.join(tmpDir, 'dropped.css'), 'utf8');
257
+ expect(css).not.toContain('example.com');
258
+
259
+ const warnings = result?.data.warnings ?? [];
260
+ expect(warnings).toHaveLength(5);
261
+ expect(warnings).toEqual(
262
+ expect.arrayContaining([
263
+ expect.stringMatching(
264
+ /^Declaration dropped "--color-bg" in tokens: an unquoted "}" would close the rule/,
265
+ ),
266
+ expect.stringMatching(
267
+ /^Declaration dropped "background-color" in components\.button\["variant:secondary"\]: an unquoted ";" would end the declaration/,
268
+ ),
269
+ expect.stringMatching(
270
+ /^Declaration dropped "color" in components\.button\["variant:secondary"\]\[":hover"\]: an unclosed " string/,
271
+ ),
272
+ expect.stringMatching(
273
+ /^Declaration dropped "--color-bg" in onDark\.tokens: an unclosed url\(/,
274
+ ),
275
+ expect.stringMatching(
276
+ /^Declaration dropped "--color-bg" in adaptations\[0\]\.tokens: an unclosed \/\* comment/,
277
+ ),
278
+ ]),
279
+ );
280
+ for (const w of warnings) {
281
+ expect(w).toContain('The generated CSS omits it');
282
+ }
283
+ });
284
+
285
+ it('generates CSS for legacy null tokens without losing neighboring declarations', async () => {
286
+ fs.writeFileSync(
287
+ path.join(tmpDir, 'legacy.mjs'),
288
+ `export default {
289
+ name: 'legacy',
290
+ tokens: {'--color-background-body': null, '--spacing-4': 12},
291
+ onDark: {tokens: {'--color-background-body': null}},
292
+ components: {button: {base: {borderRadius: '4px'}}},
293
+ };\n`,
294
+ );
295
+
296
+ const result = await themeBuild('legacy.mjs', {}, {cwd: tmpDir});
297
+ const css = fs.readFileSync(path.join(tmpDir, 'legacy.css'), 'utf8');
298
+ expect(css).toContain('--color-background-body: null;');
299
+ expect(css).toContain('--spacing-4: 12;');
300
+ expect(css).toContain('border-radius: 4px;');
301
+ expect(result?.data.warnings).toEqual([]);
302
+ });
303
+
304
+ it('keeps valid CSS that carries semicolons, and reports nothing', async () => {
305
+ const themeFile = path.join(tmpDir, 'kept.mjs');
306
+ fs.writeFileSync(
307
+ themeFile,
308
+ `export default {
309
+ name: 'kept',
310
+ tokens: {'--font-family-body': 'Gill\\\\ Sans, "Segoe;UI", serif /* ; */'},
311
+ components: {
312
+ button: {
313
+ 'variant:secondary': {
314
+ backgroundImage: 'URL(data:image/svg+xml;base64,PHN2Zz4=)',
315
+ WebkitLineClamp: '2',
316
+ },
317
+ },
318
+ },
319
+ };\n`,
320
+ );
321
+
322
+ const result = await themeBuild('kept.mjs', {}, {cwd: tmpDir});
323
+ const css = fs.readFileSync(path.join(tmpDir, 'kept.css'), 'utf8');
324
+
325
+ expect(css).toContain(
326
+ '--font-family-body: Gill\\ Sans, "Segoe;UI", serif /* ; */;',
327
+ );
328
+ expect(css).toContain(
329
+ 'background-image: URL(data:image/svg+xml;base64,PHN2Zz4=);',
330
+ );
331
+ expect(css).toContain('-webkit-line-clamp: 2;');
332
+ expect(result?.data.warnings).toEqual([]);
333
+ });
334
+ });
335
+
209
336
  describe('themeBuild() — nothing to build', () => {
210
337
  it('returns null and writes nothing when the generator yields no CSS', async () => {
211
338
  const themeFile = path.join(tmpDir, 'empty.mjs');
@@ -211,11 +211,11 @@ export function formatFontLoadingHelp(themeName, families) {
211
211
  const first = families[0];
212
212
  const slug = first.toLowerCase().replace(/ /g, '-');
213
213
  return `
214
- ⚠ Theme "${themeName}" names fonts it does not load: ${named}
215
- The built CSS only sets font-family — load these in your app, or every
214
+ [note] Theme "${themeName}" names fonts it does not load: ${named}
215
+ The built CSS only sets font-family; load these in your app, or every
216
216
  browser quietly falls back.
217
217
 
218
- Google Fonts (add :wght@… axes as your theme's weights require):
218
+ Google Fonts (add :wght@... axes as your theme's weights require):
219
219
 
220
220
  <link rel="preconnect" href="https://fonts.googleapis.com" />
221
221
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
@@ -227,12 +227,15 @@ describe('formatFontLoadingHelp', () => {
227
227
  const help = formatFontLoadingHelp('ocean', ['Fraunces', 'JetBrains Mono']);
228
228
 
229
229
  it('names the theme and every family in the headline', () => {
230
- expect(help).toContain('⚠');
231
- expect(help).toContain('ocean');
230
+ expect(help).toContain('[note] Theme "ocean"');
232
231
  expect(help).toContain('"Fraunces"');
233
232
  expect(help).toContain('"JetBrains Mono"');
234
233
  });
235
234
 
235
+ it('is plain ASCII', () => {
236
+ expect(help).not.toMatch(/[\u0080-\uffff]/);
237
+ });
238
+
236
239
  it('includes the Google Fonts recipe: preconnect pair + the exact css2 URL', () => {
237
240
  expect(help).toContain(
238
241
  '<link rel="preconnect" href="https://fonts.googleapis.com"',
@@ -5,6 +5,7 @@ export const doc = {
5
5
  type: 'function',
6
6
  kind: 'api',
7
7
  name: 'generateTonalPalette',
8
+ namespace: 'cli/api',
8
9
  displayName: 'generateTonalPalette()',
9
10
  summary: 'Generate candidate tonal palette data without filesystem effects.',
10
11
  description:
@@ -7,18 +7,14 @@ import {themeAdd} from './add/add.mjs';
7
7
 
8
8
  let tmpDir;
9
9
 
10
- function installThemeIntegration(
11
- packageName,
12
- slug,
13
- source = 'export const oceanTheme = {};\n',
14
- extraFiles = {},
15
- ) {
10
+ function installThemeIntegration(packageName, slug, source, extraFiles = {}) {
16
11
  const packageDir = path.join(
17
12
  tmpDir,
18
13
  'node_modules',
19
14
  ...packageName.split('/'),
20
15
  );
21
16
  const themeDir = path.join(packageDir, 'themes', slug);
17
+ const stem = `${slug.replace(/-([a-z0-9])/gu, (_, character) => character.toUpperCase())}Theme`;
22
18
  fs.mkdirSync(themeDir, {recursive: true});
23
19
  fs.writeFileSync(
24
20
  path.join(packageDir, 'package.json'),
@@ -26,26 +22,21 @@ function installThemeIntegration(
26
22
  );
27
23
  fs.writeFileSync(
28
24
  path.join(packageDir, 'astryx.integration.mjs'),
29
- `export default {themes: './themes'};\n`,
25
+ `export default {themes: './themes'};
26
+ `,
30
27
  );
31
28
  fs.writeFileSync(
32
- path.join(packageDir, 'themes', 'manifest.json'),
33
- JSON.stringify({
34
- version: 1,
35
- themes: [
36
- {
37
- slug,
38
- displayName: slug === 'neutral' ? 'Neutral Plus' : 'Ocean',
39
- description: 'Integration-owned theme.',
40
- maintained: true,
41
- entry: 'oceanTheme.ts',
42
- exportName: 'oceanTheme',
43
- files: ['oceanTheme.ts', ...Object.keys(extraFiles)],
44
- },
45
- ],
46
- }),
29
+ path.join(themeDir, `${stem}.doc.mjs`),
30
+ `/** @type {import('@astryxdesign/cli/authoring').ThemeDoc} */
31
+ export default {type: 'theme', name: '${slug}', displayName: '${slug === 'neutral' ? 'Neutral Plus' : 'Ocean'}', description: 'Integration-owned theme.', maintained: true};
32
+ `,
33
+ );
34
+ fs.writeFileSync(
35
+ path.join(themeDir, `${stem}.ts`),
36
+ source ??
37
+ `export const ${stem} = {};
38
+ `,
47
39
  );
48
- fs.writeFileSync(path.join(themeDir, 'oceanTheme.ts'), source);
49
40
  for (const [relativePath, contents] of Object.entries(extraFiles)) {
50
41
  const file = path.join(themeDir, relativePath);
51
42
  fs.mkdirSync(path.dirname(file), {recursive: true});
@@ -85,23 +76,43 @@ describe('themeAdd with integration themes', () => {
85
76
  ).toContain('oceanTheme');
86
77
  });
87
78
 
88
- it('copies nested files listed by an integration theme catalog', async () => {
79
+ it('copies the complete nested integration theme directory', async () => {
89
80
  installThemeIntegration(
90
81
  '@acme/themes',
91
82
  'ocean',
92
83
  "import {oceanBlue} from './tokens/colors';\nexport const oceanTheme = {oceanBlue};\n",
93
- {'tokens/colors.ts': "export const oceanBlue = '#0064e0';\n"},
84
+ {
85
+ 'tokens/colors.ts': "export const oceanBlue = '#0064e0';\n",
86
+ 'receipts/palette.json': '{"version":1}\n',
87
+ },
94
88
  );
95
89
 
96
90
  const result = await themeAdd('ocean', {cwd: tmpDir});
97
91
 
98
- expect(result.data.files).toEqual(['oceanTheme.ts', 'tokens/colors.ts']);
92
+ expect(result.data.files).toEqual([
93
+ 'oceanTheme.ts',
94
+ 'oceanTheme.doc.mjs',
95
+ 'receipts/palette.json',
96
+ 'tokens/colors.ts',
97
+ ]);
98
+ expect(
99
+ fs.readFileSync(
100
+ path.join(tmpDir, 'src', 'themes', 'ocean', 'oceanTheme.doc.mjs'),
101
+ 'utf-8',
102
+ ),
103
+ ).toContain("type: 'theme'");
99
104
  expect(
100
105
  fs.readFileSync(
101
106
  path.join(tmpDir, 'src', 'themes', 'ocean', 'tokens', 'colors.ts'),
102
107
  'utf-8',
103
108
  ),
104
109
  ).toContain('oceanBlue');
110
+ expect(
111
+ fs.readFileSync(
112
+ path.join(tmpDir, 'src', 'themes', 'ocean', 'receipts', 'palette.json'),
113
+ 'utf-8',
114
+ ),
115
+ ).toBe('{"version":1}\n');
105
116
  });
106
117
 
107
118
  it('rejects a nested destination symlink that escapes the project', async () => {
@@ -146,7 +157,7 @@ describe('themeAdd with integration themes', () => {
146
157
  expect(result.data.package).toBe('@acme/themes');
147
158
  });
148
159
 
149
- it('reports a selected installed package with a corrupted theme catalog', async () => {
160
+ it('reports a selected installed package with a corrupted theme directory', async () => {
150
161
  installThemeIntegration(
151
162
  '@acme/themes',
152
163
  'ocean',
@@ -170,7 +181,7 @@ describe('themeAdd with integration themes', () => {
170
181
  themeAdd('ocean', {cwd: tmpDir, package: '@acme/themes'}),
171
182
  ).rejects.toMatchObject({
172
183
  code: 'ERR_THEME_INVALID',
173
- message: expect.stringContaining('tokens/colors.ts'),
184
+ message: expect.stringContaining('./tokens/colors'),
174
185
  });
175
186
  });
176
187
 
@@ -9,8 +9,13 @@ import {BUNDLED_THEME_PACKAGE} from '../../../foundation/discovery/theme-discove
9
9
  let tmpDir;
10
10
 
11
11
  function installThemeIntegration(packageName = '@acme/themes', slug = 'ocean') {
12
- const packageDir = path.join(tmpDir, 'node_modules', ...packageName.split('/'));
12
+ const packageDir = path.join(
13
+ tmpDir,
14
+ 'node_modules',
15
+ ...packageName.split('/'),
16
+ );
13
17
  const themeDir = path.join(packageDir, 'themes', slug);
18
+ const stem = `${slug.replace(/-([a-z0-9])/gu, (_, character) => character.toUpperCase())}Theme`;
14
19
  fs.mkdirSync(themeDir, {recursive: true});
15
20
  fs.writeFileSync(
16
21
  path.join(packageDir, 'package.json'),
@@ -18,28 +23,19 @@ function installThemeIntegration(packageName = '@acme/themes', slug = 'ocean') {
18
23
  );
19
24
  fs.writeFileSync(
20
25
  path.join(packageDir, 'astryx.integration.mjs'),
21
- `export default {themes: './themes'};\n`,
26
+ `export default {themes: './themes'};
27
+ `,
22
28
  );
23
29
  fs.writeFileSync(
24
- path.join(packageDir, 'themes', 'manifest.json'),
25
- JSON.stringify({
26
- version: 1,
27
- themes: [
28
- {
29
- slug,
30
- displayName: 'Ocean',
31
- description: 'Blue and calm.',
32
- maintained: true,
33
- entry: 'oceanTheme.ts',
34
- exportName: 'oceanTheme',
35
- files: ['oceanTheme.ts'],
36
- },
37
- ],
38
- }),
30
+ path.join(themeDir, `${stem}.doc.mjs`),
31
+ `/** @type {import('@astryxdesign/cli/authoring').ThemeDoc} */
32
+ export default {type: 'theme', name: '${slug}', displayName: 'Ocean', description: 'Blue and calm.', maintained: true};
33
+ `,
39
34
  );
40
35
  fs.writeFileSync(
41
- path.join(themeDir, 'oceanTheme.ts'),
42
- 'export const oceanTheme = {};\n',
36
+ path.join(themeDir, `${stem}.ts`),
37
+ `export const ${stem} = {};
38
+ `,
43
39
  );
44
40
  }
45
41
 
@@ -47,7 +43,10 @@ beforeEach(() => {
47
43
  tmpDir = fs.mkdtempSync(path.join(process.cwd(), '.astryx-theme-list-'));
48
44
  fs.writeFileSync(
49
45
  path.join(tmpDir, 'package.json'),
50
- JSON.stringify({name: 'consumer', dependencies: {'@acme/themes': '^1.0.0'}}),
46
+ JSON.stringify({
47
+ name: 'consumer',
48
+ dependencies: {'@acme/themes': '^1.0.0'},
49
+ }),
51
50
  );
52
51
  });
53
52
 
@@ -9,25 +9,26 @@ export const doc = {
9
9
  type: 'function',
10
10
  kind: 'api',
11
11
  name: 'listThemes',
12
+ namespace: 'cli/api',
12
13
  displayName: 'listThemes()',
13
- summary: 'Read the CLI bundled-theme manifest.',
14
+ summary: 'Read the CLI bundled-theme descriptors.',
14
15
  description:
15
- 'Reads templates/themes/manifest.json and returns its raw entries synchronously. This low-level helper keeps its historical bundled-only contract; project-aware themeList() and themeAdd() also discover source themes from installed integrations.',
16
+ 'Reads the typed same-stem descriptors under templates/themes and returns normalized entries synchronously. This low-level helper keeps its historical bundled-only contract; project-aware themeList() and themeAdd() also discover source themes from installed integrations.',
16
17
  importPath: '@astryxdesign/cli/api',
17
18
  signature: 'listThemes(): BundledTheme[]',
18
- keywords: ['theme', 'themes', 'manifest', 'bundled', 'adapter', 'list'],
19
+ keywords: ['theme', 'themes', 'descriptor', 'bundled', 'adapter', 'list'],
19
20
  params: [],
20
21
  returns: [
21
22
  {
22
23
  type: 'BundledTheme[]',
23
24
  description:
24
- 'The bundled manifest entries: slug, displayName, description, maintained, entry, exportName, and files.',
25
+ 'The normalized bundled descriptor entries: slug, displayName, description, maintained, entry, exportName, and files.',
25
26
  },
26
27
  ],
27
28
  throws: [
28
29
  {
29
30
  code: 'ERR_NO_SOURCE',
30
- when: 'the bundled catalog is missing, invalid, or references missing source files',
31
+ when: 'the bundled descriptors are missing, invalid, or have missing source files',
31
32
  },
32
33
  ],
33
34
  examples: [