@astryxdesign/cli 0.6.3-canary.db4e378 → 0.6.3-canary.db52d98

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 (397) hide show
  1. package/README.md +38 -15
  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 +14 -7
  6. package/api/build/build.test.mjs +184 -6
  7. package/api/build/build.type.d.mts +57 -2
  8. package/api/build/build.type.mjs +30 -7
  9. package/api/build/help/help.d.mts +4 -0
  10. package/api/build/help/help.mjs +24 -11
  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 +1 -0
  19. package/api/component/component.mjs +60 -12
  20. package/api/component/list/list.mjs +3 -2
  21. package/api/discover/discover.doc.mjs +1 -0
  22. package/api/docs/_adapter.d.mts +252 -34
  23. package/api/docs/_adapter.mjs +923 -132
  24. package/api/docs/detail/detail.mjs +11 -3
  25. package/api/docs/detail/section/section.mjs +24 -13
  26. package/api/docs/detail/section/section.test.mjs +15 -6
  27. package/api/docs/docs.d.mts +5 -3
  28. package/api/docs/docs.doc.mjs +39 -17
  29. package/api/docs/docs.mjs +44 -8
  30. package/api/docs/docs.test.mjs +158 -4
  31. package/api/docs/docs.type.d.mts +181 -2
  32. package/api/docs/docs.type.mjs +117 -3
  33. package/api/docs/index/index.mjs +11 -3
  34. package/api/docs/index/index.test.mjs +1 -1
  35. package/api/docs/integration-tree.test.mjs +555 -0
  36. package/api/docs/integrationDocs.test.mjs +14 -14
  37. package/api/docs/list/list.mjs +28 -12
  38. package/api/docs/node/node.d.mts +43 -0
  39. package/api/docs/node/node.mjs +192 -0
  40. package/api/docs/reference-blocks.test.mjs +406 -0
  41. package/api/doctor/doctor.d.mts +54 -4
  42. package/api/doctor/doctor.doc.mjs +1 -0
  43. package/api/doctor/doctor.mjs +331 -16
  44. package/api/doctor/doctor.test.mjs +420 -7
  45. package/api/gap-report/gap-report.doc.mjs +1 -0
  46. package/api/hook/_adapter.mjs +19 -5
  47. package/api/hook/hook.doc.mjs +1 -0
  48. package/api/hook/list/list.d.mts +1 -1
  49. package/api/hook/list/list.mjs +69 -17
  50. package/api/index.d.mts +1 -1
  51. package/api/index.mjs +1 -0
  52. package/api/init/init.doc.mjs +2 -1
  53. package/api/integration/add-contribution.d.mts +2 -1
  54. package/api/integration/add-contribution.mjs +114 -12
  55. package/api/integration/add-contribution.test.mjs +174 -3
  56. package/api/integration/add-theme.mjs +34 -64
  57. package/api/integration/add-theme.test.mjs +105 -21
  58. package/api/integration/authoring-checks.mjs +138 -28
  59. package/api/integration/authoring-checks.test.mjs +179 -7
  60. package/api/integration/authoring-checks.type.mjs +6 -1
  61. package/api/integration/integration-authoring.type.d.mts +2 -0
  62. package/api/integration/integration-authoring.type.mjs +2 -0
  63. package/api/integration/integration-block-exports.test.mjs +10 -6
  64. package/api/integration/integrationAdd.doc.mjs +7 -0
  65. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  66. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  67. package/api/integration/integrationAddComponent.doc.mjs +1 -0
  68. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  69. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  70. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  71. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  72. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  73. package/api/integration/integrationPackCheck.doc.mjs +2 -1
  74. package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
  75. package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
  76. package/api/integration/pack-check.mjs +34 -0
  77. package/api/integration/pack-check.test.mjs +138 -47
  78. package/api/integration/pack-check.type.d.mts +26 -2
  79. package/api/integration/pack-check.type.mjs +14 -1
  80. package/api/integration/summarizeIssues.doc.mjs +1 -0
  81. package/api/integration/template-conflict-compatibility.test.mjs +73 -0
  82. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  83. package/api/integration/validate-integration.mjs +50 -102
  84. package/api/integration/validate-integration.test.mjs +88 -26
  85. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  86. package/api/integration/validateIntegration.doc.mjs +2 -1
  87. package/api/json/assertResponse.doc.mjs +1 -0
  88. package/api/json/index.ts +2 -0
  89. package/api/json/isError.doc.mjs +1 -0
  90. package/api/json/parseResponse.doc.mjs +1 -0
  91. package/api/layout/_adapter.mjs +20 -5
  92. package/api/layout/layoutCheck.doc.mjs +1 -0
  93. package/api/layout/layoutExpand.doc.mjs +1 -0
  94. package/api/layout/layoutGrammar.doc.mjs +1 -0
  95. package/api/search/search.d.mts +59 -1
  96. package/api/search/search.doc.mjs +5 -3
  97. package/api/search/search.mjs +458 -77
  98. package/api/search/search.test.mjs +91 -2
  99. package/api/search/search.type.d.mts +13 -1
  100. package/api/search/search.type.mjs +4 -1
  101. package/api/swizzle/swizzle.doc.mjs +1 -0
  102. package/api/template/list/list.mjs +1 -0
  103. package/api/template/table-floating-bulk-actions.test.mjs +66 -0
  104. package/api/template/template-integration.test.mjs +1072 -3
  105. package/api/template/template-suffix.test.mjs +41 -21
  106. package/api/template/template.doc.mjs +28 -7
  107. package/api/template/template.mjs +45 -8
  108. package/api/template/template.type.d.mts +6 -8
  109. package/api/template/template.type.mjs +3 -2
  110. package/api/theme/_adapter.d.mts +2 -3
  111. package/api/theme/_adapter.mjs +4 -5
  112. package/api/theme/add/add.binary.test.mjs +10 -17
  113. package/api/theme/add/add.test.mjs +14 -1
  114. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  115. package/api/theme/integration-themes.test.mjs +39 -28
  116. package/api/theme/list/list.test.mjs +19 -20
  117. package/api/theme/listThemes.doc.mjs +6 -5
  118. package/api/theme/template/template.test.mjs +5 -0
  119. package/api/theme/themeAdd.doc.mjs +4 -3
  120. package/api/theme/themeBuild.doc.mjs +1 -0
  121. package/api/theme/themeList.doc.mjs +6 -3
  122. package/api/theme/themeListAvailable.doc.mjs +5 -3
  123. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  124. package/api/theme/themeTargets.doc.mjs +1 -0
  125. package/api/theme/themeTemplate.doc.mjs +2 -1
  126. package/api/upgrade/_adapter.d.mts +32 -5
  127. package/api/upgrade/_adapter.mjs +97 -69
  128. package/api/upgrade/provider-agreement.test.mjs +152 -0
  129. package/api/upgrade/run/run.mjs +356 -59
  130. package/api/upgrade/upgrade.doc.mjs +6 -1
  131. package/api/upgrade/upgrade.type.d.mts +34 -0
  132. package/api/upgrade/upgrade.type.mjs +15 -0
  133. package/assets/codemods/__tests__/runner.test.mjs +330 -8
  134. package/assets/codemods/integration-discovery.mjs +8 -2
  135. package/assets/codemods/integration-discovery.test.mjs +15 -0
  136. package/assets/codemods/integration-runner.mjs +56 -4
  137. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  138. package/assets/codemods/run-codemod.mjs +177 -34
  139. package/assets/codemods/runner.mjs +350 -102
  140. package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  141. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  142. package/assets/codemods/transforms/next/index.mjs +19 -1
  143. package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
  144. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  145. package/assets/docs/getting-started.doc.mjs +2 -2
  146. package/assets/docs/layout.doc.dense.mjs +2 -2
  147. package/assets/docs/layout.doc.mjs +1 -1
  148. package/assets/docs/principles.doc.mjs +6 -6
  149. package/assets/docs/styling-libraries.doc.mjs +3 -3
  150. package/assets/docs/styling.doc.mjs +4 -4
  151. package/assets/docs/theme.doc.mjs +5 -5
  152. package/assets/docs/tokens.doc.mjs +1 -1
  153. package/assets/docs/tree/api.doc.mjs +30 -0
  154. package/assets/docs/tree/cli.doc.mjs +23 -0
  155. package/assets/docs/tree/commands.doc.mjs +25 -0
  156. package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +66 -38
  157. package/assets/docs/tree/integrations.test.mjs +62 -0
  158. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  159. package/assets/docs/working-with-ai.doc.mjs +3 -3
  160. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
  161. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
  162. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  163. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  164. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  165. package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
  166. package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
  167. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
  168. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
  169. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  170. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  171. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  172. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  173. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  174. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  175. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  176. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  177. package/authoring/codemod/codemod.doc.mjs +1 -1
  178. package/authoring/codemod/type.ts +12 -0
  179. package/authoring/config/config.doc.mjs +1 -1
  180. package/authoring/debug/debug.doc.d.mts +11 -0
  181. package/authoring/debug/debug.doc.mjs +182 -0
  182. package/authoring/debug/parse.d.mts +3 -3
  183. package/authoring/doctypes/_schema.d.mts +119 -117
  184. package/authoring/doctypes/_schema.mjs +54 -3
  185. package/authoring/doctypes/base/graph-fields.doc.mjs +8 -6
  186. package/authoring/doctypes/base/type.ts +6 -5
  187. package/authoring/doctypes/command/command.doc.mjs +1 -1
  188. package/authoring/doctypes/command/type.ts +2 -2
  189. package/authoring/doctypes/component/type.ts +2 -2
  190. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  191. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  192. package/authoring/doctypes/enum/type.ts +1 -1
  193. package/authoring/doctypes/function/function.doc.mjs +3 -2
  194. package/authoring/doctypes/function/type.ts +3 -2
  195. package/authoring/doctypes/hook/type.ts +2 -2
  196. package/authoring/doctypes/load-contract.test.mjs +28 -2
  197. package/authoring/doctypes/namespace/namespace.doc.mjs +6 -10
  198. package/authoring/doctypes/namespace/parse.test.mjs +23 -25
  199. package/authoring/doctypes/namespace/type.ts +5 -2
  200. package/authoring/doctypes/parse.d.mts +4 -2
  201. package/authoring/doctypes/parse.mjs +10 -5
  202. package/authoring/doctypes/reference/reference.doc.mjs +35 -6
  203. package/authoring/doctypes/reference/type.ts +30 -13
  204. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  205. package/authoring/doctypes/schema/type.ts +1 -2
  206. package/authoring/doctypes/template/parse.d.mts +2 -0
  207. package/authoring/doctypes/template/parse.mjs +4 -0
  208. package/authoring/doctypes/template/parse.test.mjs +18 -0
  209. package/authoring/doctypes/template/template.doc.mjs +9 -3
  210. package/authoring/doctypes/template/type.ts +8 -0
  211. package/authoring/doctypes/theme/parse.d.mts +35 -0
  212. package/authoring/doctypes/theme/parse.mjs +76 -0
  213. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  214. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  215. package/authoring/doctypes/theme/type.ts +42 -0
  216. package/authoring/doctypes/types.ts +2 -1
  217. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  218. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  219. package/authoring/identity/identity.doc.mjs +2 -2
  220. package/authoring/index.d.mts +1 -0
  221. package/authoring/index.d.ts +7 -4
  222. package/authoring/index.mjs +2 -1
  223. package/authoring/integration/integration.doc.mjs +2 -2
  224. package/authoring/integration/type.ts +4 -10
  225. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  226. package/clients/cli/commands/blog.doc.mjs +1 -1
  227. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  228. package/clients/cli/commands/build-theme.mjs +11 -45
  229. package/clients/cli/commands/build.doc.mjs +12 -7
  230. package/clients/cli/commands/build.mjs +105 -67
  231. package/clients/cli/commands/build.text-fields.test.mjs +41 -0
  232. package/clients/cli/commands/component/index.mjs +1 -1
  233. package/clients/cli/commands/component-ownership.test.mjs +3 -3
  234. package/clients/cli/commands/component.doc.mjs +1 -1
  235. package/clients/cli/commands/discover.broken-integration.test.mjs +7 -8
  236. package/clients/cli/commands/discover.doc.mjs +1 -1
  237. package/clients/cli/commands/discover.mjs +1 -1
  238. package/clients/cli/commands/docs.doc.mjs +21 -9
  239. package/clients/cli/commands/docs.mjs +184 -70
  240. package/clients/cli/commands/docs.test.mjs +120 -16
  241. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  242. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
  243. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  244. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  245. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  246. package/clients/cli/commands/doctor-integration.test.mjs +90 -8
  247. package/clients/cli/commands/doctor.doc.mjs +1 -1
  248. package/clients/cli/commands/doctor.mjs +53 -16
  249. package/clients/cli/commands/gap-report.doc.mjs +1 -1
  250. package/clients/cli/commands/hook.doc.mjs +1 -1
  251. package/clients/cli/commands/init.doc.mjs +1 -1
  252. package/clients/cli/commands/integration-add.controls.test.mjs +1 -1
  253. package/clients/cli/commands/integration-add.doc.mjs +11 -1
  254. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  255. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  256. package/clients/cli/commands/integration.doc.mjs +1 -1
  257. package/clients/cli/commands/integration.mjs +1 -0
  258. package/clients/cli/commands/layout-check.doc.mjs +1 -1
  259. package/clients/cli/commands/layout-expand.doc.mjs +1 -1
  260. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  261. package/clients/cli/commands/layout.doc.mjs +1 -1
  262. package/clients/cli/commands/manifest.doc.mjs +1 -1
  263. package/clients/cli/commands/search.doc.mjs +1 -1
  264. package/clients/cli/commands/search.mjs +11 -2
  265. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  266. package/clients/cli/commands/swizzle.doc.mjs +1 -1
  267. package/clients/cli/commands/template.doc.mjs +24 -7
  268. package/clients/cli/commands/template.mjs +4 -91
  269. package/clients/cli/commands/text-json-parity.test.mjs +719 -0
  270. package/clients/cli/commands/theme-add.doc.mjs +2 -2
  271. package/clients/cli/commands/theme-build.doc.mjs +1 -1
  272. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  273. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
  274. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  275. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  276. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  277. package/clients/cli/commands/theme-template.doc.mjs +1 -1
  278. package/clients/cli/commands/theme.doc.mjs +1 -1
  279. package/clients/cli/commands/upgrade.doc.mjs +3 -2
  280. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  281. package/clients/cli/commands/upgrade.mjs +29 -7
  282. package/clients/cli/formatters/index.mjs +2 -0
  283. package/clients/cli/formatters/index.test.mjs +6 -0
  284. package/clients/cli/index.mjs +8 -0
  285. package/clients/cli/lib/hook-format.mjs +14 -5
  286. package/clients/cli/lib/manifest.mjs +9 -2
  287. package/foundation/agent-docs/agent-docs.d.mts +3 -2
  288. package/foundation/agent-docs/agent-docs.mjs +13 -9
  289. package/foundation/agent-docs/agent-docs.test.mjs +19 -1
  290. package/foundation/config/project-themes.test.mjs +11 -19
  291. package/foundation/config/project.d.mts +20 -11
  292. package/foundation/config/project.mjs +123 -80
  293. package/foundation/config/project.test.mjs +144 -21
  294. package/foundation/discovery/authoring-self-docs.d.mts +18 -0
  295. package/foundation/discovery/authoring-self-docs.mjs +37 -15
  296. package/foundation/discovery/authoring-self-docs.test.mjs +25 -9
  297. package/foundation/discovery/authoring-surface.d.mts +74 -0
  298. package/foundation/discovery/authoring-surface.mjs +525 -0
  299. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  300. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  301. package/foundation/discovery/cli-self-docs.mjs +490 -0
  302. package/foundation/discovery/cli-self-docs.test.mjs +375 -0
  303. package/foundation/discovery/component-discovery.d.mts +38 -0
  304. package/foundation/discovery/component-discovery.mjs +48 -0
  305. package/foundation/discovery/component-loader.d.mts +35 -38
  306. package/foundation/discovery/component-loader.mjs +53 -222
  307. package/foundation/discovery/docs-discovery.d.mts +112 -11
  308. package/foundation/discovery/docs-discovery.mjs +231 -36
  309. package/foundation/discovery/docs-discovery.test.mjs +111 -32
  310. package/foundation/discovery/docs-output-budget.d.mts +2 -2
  311. package/foundation/discovery/docs-output-budget.mjs +1 -1
  312. package/foundation/discovery/docs-section-key.d.mts +28 -10
  313. package/foundation/discovery/docs-section-key.mjs +134 -33
  314. package/foundation/discovery/docs-section-key.test.mjs +41 -19
  315. package/foundation/discovery/template-adapter.d.mts +99 -6
  316. package/foundation/discovery/template-adapter.mjs +480 -57
  317. package/foundation/discovery/template-adapter.test.mjs +57 -0
  318. package/foundation/discovery/template-conflict-release.d.mts +13 -0
  319. package/foundation/discovery/template-conflict-release.mjs +40 -0
  320. package/foundation/discovery/template-conflict-release.test.mjs +40 -0
  321. package/foundation/discovery/theme-discovery.d.mts +67 -7
  322. package/foundation/discovery/theme-discovery.mjs +916 -186
  323. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  324. package/foundation/doc-compiler/bundle.d.mts +47 -0
  325. package/foundation/doc-compiler/bundle.mjs +278 -0
  326. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  327. package/foundation/doc-compiler/compile.d.mts +220 -39
  328. package/foundation/doc-compiler/compile.mjs +311 -15
  329. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  330. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  331. package/foundation/doc-compiler/doc-compiler.test.mjs +28 -1
  332. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  333. package/foundation/doc-compiler/import.d.mts +24 -0
  334. package/foundation/doc-compiler/import.mjs +59 -0
  335. package/foundation/doc-compiler/inputs.d.mts +102 -0
  336. package/foundation/doc-compiler/inputs.mjs +291 -0
  337. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  338. package/foundation/doc-compiler/ir.d.mts +13 -0
  339. package/foundation/doc-compiler/ir.mjs +196 -12
  340. package/foundation/doc-compiler/lenses.d.mts +8 -5
  341. package/foundation/doc-compiler/lenses.mjs +50 -4
  342. package/foundation/doc-compiler/links.d.mts +162 -0
  343. package/foundation/doc-compiler/links.mjs +294 -0
  344. package/foundation/doc-compiler/links.test.mjs +192 -0
  345. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  346. package/foundation/doc-compiler/overlays.d.mts +37 -0
  347. package/foundation/doc-compiler/overlays.mjs +206 -0
  348. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  349. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  350. package/foundation/doc-compiler/read.d.mts +127 -0
  351. package/foundation/doc-compiler/read.mjs +325 -0
  352. package/foundation/doc-compiler/read.test.mjs +313 -0
  353. package/foundation/doc-compiler/source.d.mts +33 -0
  354. package/foundation/doc-compiler/source.mjs +128 -0
  355. package/foundation/doc-compiler/tree.d.mts +288 -0
  356. package/foundation/doc-compiler/tree.mjs +876 -0
  357. package/foundation/doc-compiler/tree.test.mjs +598 -0
  358. package/foundation/fs/file-protection.d.mts +33 -0
  359. package/foundation/fs/file-protection.mjs +825 -0
  360. package/foundation/fs/file-protection.test.mjs +250 -0
  361. package/foundation/integrations/autolink.d.mts +58 -1
  362. package/foundation/integrations/autolink.mjs +143 -57
  363. package/foundation/integrations/autolink.test.mjs +1 -1
  364. package/foundation/integrations/cli-requirement.d.mts +45 -0
  365. package/foundation/integrations/cli-requirement.mjs +154 -0
  366. package/foundation/integrations/cli-requirement.test.mjs +84 -0
  367. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  368. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  369. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  370. package/foundation/integrations/contribution-inventory.mjs +27 -24
  371. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  372. package/foundation/integrations/integration-warnings.d.mts +9 -2
  373. package/foundation/integrations/integration-warnings.mjs +51 -26
  374. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  375. package/foundation/integrations/integrations.d.mts +3 -0
  376. package/foundation/integrations/integrations.mjs +11 -97
  377. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  378. package/foundation/integrations/provider-resolution.d.mts +152 -0
  379. package/foundation/integrations/provider-resolution.mjs +576 -0
  380. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  381. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  382. package/foundation/integrations/theme-descriptor.mjs +44 -0
  383. package/foundation/integrations/validate-contributions.mjs +121 -29
  384. package/foundation/response/error-codes.d.mts +3 -1
  385. package/foundation/response/error-codes.d.ts +2 -0
  386. package/foundation/response/error-codes.doc.mjs +12 -2
  387. package/foundation/response/error-codes.mjs +7 -1
  388. package/foundation/response/error-codes.test.mjs +55 -11
  389. package/foundation/response/response-types.doc.d.mts +5 -1
  390. package/foundation/response/response-types.doc.mjs +20 -11
  391. package/foundation/response/response.doc.mjs +1 -1
  392. package/foundation/text/string-utils.d.mts +8 -0
  393. package/foundation/text/string-utils.mjs +40 -10
  394. package/foundation/xle/expand.mjs +1 -1
  395. package/foundation/xle/xle.test.mjs +13 -0
  396. package/package.json +10 -9
  397. package/assets/templates/themes/manifest.json +0 -95
@@ -1,25 +1,20 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
3
  /**
4
- * @file The canonical `.template.{ts,mjs,js}` suffix is discovered identically
5
- * to the legacy `.doc.{ts,mjs,js}` suffix.
4
+ * @file The canonical `.doc.{mjs,ts,js}` suffix is discovered identically
5
+ * to the released `.template.{ts,mjs,js}` compatibility suffix.
6
6
  *
7
- * Template-spec files are named for what they are: a scaffoldable TEMPLATE
8
- * stamped with `type: 'page' | 'block'`. The `.doc.*` suffix was
9
- * inherited from the component-doc convention and is still accepted during the
10
- * transition. These tests stand up integration templates and external blocks in
11
- * both families and assert byte-for-byte-equivalent discovery + scaffolding.
7
+ * New authoring writes `.doc.mjs`, the canonical typed descriptor. Stable
8
+ * 0.6.0 already accepted `.template.*`, so these tests
9
+ * keep that family as a compatibility input and assert equivalent discovery +
10
+ * scaffolding.
12
11
  */
13
12
 
14
13
  import {afterEach, beforeEach, describe, expect, it} from 'vitest';
15
14
  import * as fs from 'node:fs';
16
15
  import * as path from 'node:path';
17
16
  import * as os from 'node:os';
18
- import {
19
- template,
20
- findShowcase,
21
- findRelatedBlocks,
22
- } from './template.mjs';
17
+ import {template, findShowcase, findRelatedBlocks} from './template.mjs';
23
18
 
24
19
  let tmpDir;
25
20
  let originalCwd;
@@ -82,8 +77,8 @@ afterEach(() => {
82
77
  fs.rmSync(tmpDir, {recursive: true, force: true});
83
78
  });
84
79
 
85
- describe('integration templates: .template.* discovered like legacy .doc.*', () => {
86
- for (const suffix of ['.template.ts', '.template.mjs', '.doc.mjs']) {
80
+ describe('integration templates: canonical .doc.* plus released .template.* compatibility', () => {
81
+ for (const suffix of ['.doc.mjs', '.doc.ts', '.template.mjs']) {
87
82
  it(`discovers + lists a page template authored as ${suffix}`, async () => {
88
83
  const pkgDir = installWidgets(tmpDir);
89
84
  writeTemplate(pkgDir, 'pricing', {kind: 'page', suffix});
@@ -124,7 +119,7 @@ describe('integration templates: .template.* discovered like legacy .doc.*', ()
124
119
  });
125
120
  }
126
121
 
127
- it('treats a .template.ts and a legacy .doc.mjs identically (same shape)', async () => {
122
+ it('treats canonical .doc.mjs and released .template.ts identically (same shape)', async () => {
128
123
  const pkgDir = installWidgets(tmpDir);
129
124
  writeTemplate(pkgDir, 'gauge', {kind: 'block', suffix: '.template.ts'});
130
125
  writeTemplate(pkgDir, 'chip', {kind: 'block', suffix: '.doc.mjs'});
@@ -143,12 +138,33 @@ describe('integration templates: .template.* discovered like legacy .doc.*', ()
143
138
  expect(gauge.type).toBe(chip.type);
144
139
  expect(gauge.package).toBe(chip.package);
145
140
  });
141
+ it('lists both same-stem specs and reads the id as ambiguous', async () => {
142
+ for (const [first, second] of [
143
+ ['.doc.mjs', '.template.ts'],
144
+ ['.doc.ts', '.doc.mjs'],
145
+ ]) {
146
+ const pkgDir = installWidgets(tmpDir);
147
+ fs.rmSync(path.join(pkgDir, 'templates'), {recursive: true, force: true});
148
+ writeTemplate(pkgDir, 'pricing', {kind: 'page', suffix: first});
149
+ writeTemplate(pkgDir, 'pricing', {kind: 'page', suffix: second});
150
+
151
+ const result = await template(undefined, {list: true, cwd: tmpDir});
152
+ expect(
153
+ result.data.filter(entry => entry.id === 'pricing'),
154
+ `${first} + ${second}`,
155
+ ).toHaveLength(2);
156
+ await expect(
157
+ template('pricing', {cwd: tmpDir}),
158
+ `${first} + ${second}`,
159
+ ).rejects.toMatchObject({code: 'ERR_AMBIGUOUS_TEMPLATE'});
160
+ }
161
+ });
146
162
  });
147
163
 
148
- describe('external showcase blocks: .template.* discovered like legacy .doc.*', () => {
164
+ describe('external showcase blocks: canonical .doc.* plus released .template.* compatibility', () => {
149
165
  /**
150
166
  * Create a consumer whose @test/ext package contributes two showcase blocks,
151
- * one authored as `Foo.template.ts` and one as legacy `Bar.doc.mjs`.
167
+ * one authored with released `Foo.template.ts` and one with canonical `Bar.doc.mjs`.
152
168
  */
153
169
  function makeShowcaseFixture() {
154
170
  // Symlink the real core package (needed by findCoreDir during discovery).
@@ -166,7 +182,7 @@ describe('external showcase blocks: .template.* discovered like legacy .doc.*',
166
182
  const extDir = path.join(tmpDir, 'node_modules', '@test', 'ext');
167
183
  const blocksDir = path.join(extDir, 'blocks', 'components');
168
184
 
169
- // Foo showcase — canonical .template.ts (stamped type: 'block' default export).
185
+ // Foo showcase — released .template.ts compatibility input.
170
186
  const fooDir = path.join(blocksDir, 'Foo');
171
187
  fs.mkdirSync(fooDir, {recursive: true});
172
188
  fs.writeFileSync(
@@ -185,7 +201,7 @@ describe('external showcase blocks: .template.* discovered like legacy .doc.*',
185
201
  "'use client';\nexport default function FooShowcase() { return <div>Foo</div>; }",
186
202
  );
187
203
 
188
- // Bar showcase — legacy .doc.mjs (export const doc).
204
+ // Bar showcase — canonical .doc.mjs (historical named export).
189
205
  const barDir = path.join(blocksDir, 'Bar');
190
206
  fs.mkdirSync(barDir, {recursive: true});
191
207
  fs.writeFileSync(
@@ -209,7 +225,11 @@ describe('external showcase blocks: .template.* discovered like legacy .doc.*',
209
225
  path.join(extDir, 'package.json'),
210
226
  JSON.stringify({
211
227
  name: '@test/ext',
212
- astryx: {docs: './src', category: 'Common', blocks: './blocks/components'},
228
+ astryx: {
229
+ docs: './src',
230
+ category: 'Common',
231
+ blocks: './blocks/components',
232
+ },
213
233
  }),
214
234
  );
215
235
  fs.mkdirSync(path.join(extDir, 'src'), {recursive: true});
@@ -223,7 +243,7 @@ describe('external showcase blocks: .template.* discovered like legacy .doc.*',
223
243
  expect(result.filePath).toContain('FooShowcase.tsx');
224
244
  });
225
245
 
226
- it('findShowcase resolves a legacy .doc.mjs external block by componentsUsed', async () => {
246
+ it('findShowcase resolves a canonical .doc.mjs external block by componentsUsed', async () => {
227
247
  makeShowcaseFixture();
228
248
  const result = await findShowcase('Bar', tmpDir);
229
249
  expect(result).not.toBeNull();
@@ -11,20 +11,33 @@ export const doc = {
11
11
  type: 'function',
12
12
  kind: 'api',
13
13
  name: 'template',
14
+ namespace: 'cli/api',
14
15
  displayName: 'template()',
15
16
  summary: 'List, inspect, or scaffold page and block templates.',
16
17
  description:
17
18
  'One entry point for the template family: with no name it lists the discovered ' +
18
19
  "templates; with a name it returns that template's source, a layout skeleton, or " +
19
- 'scaffolds it into the project. Templates are discovered across core, external ' +
20
- 'packages, and integrations, so the same id can appear in more than one place; ' +
21
- 'narrow an ambiguous name with type and/or package. The cdn option writes the ' +
22
- 'annotated no-build-step CDN starter page, which ships as an asset rather than as ' +
20
+ 'scaffolds it into the project. A configured integration may replace a Core ' +
21
+ 'template id for unqualified discovery and lookup; package selection still ' +
22
+ 'addresses the Core original. Other duplicate ids remain ambiguous and can be ' +
23
+ 'narrowed by type and/or package. The cdn option writes the annotated ' +
24
+ 'no-build-step CDN starter page, which ships as an asset rather than as ' +
23
25
  'a discovered template.',
24
26
  importPath: '@astryxdesign/cli/api',
25
27
  signature:
26
28
  'template(name?: string, options?: TemplateOptions): Promise<TemplateListResponse | TemplateShowResponse | TemplateSkeletonResponse | TemplateCopyResponse | TemplateCdnResponse>',
27
- keywords: ['template', 'scaffold', 'page', 'block', 'skeleton', 'starter', 'cdn', 'esm', 'importmap', 'no-build'],
29
+ keywords: [
30
+ 'template',
31
+ 'scaffold',
32
+ 'page',
33
+ 'block',
34
+ 'skeleton',
35
+ 'starter',
36
+ 'cdn',
37
+ 'esm',
38
+ 'importmap',
39
+ 'no-build',
40
+ ],
28
41
  params: [
29
42
  {
30
43
  name: 'name',
@@ -69,7 +82,7 @@ export const doc = {
69
82
  name: 'options.package',
70
83
  type: 'string',
71
84
  description:
72
- 'Narrow lookups to templates from a specific owning package (core templates report @astryxdesign/core).',
85
+ 'Narrow lookups to templates from a specific owning package. Without it, a valid integration replacement is selected for the Core id; use @astryxdesign/core to select the original.',
73
86
  },
74
87
  {
75
88
  name: 'options.targetPath',
@@ -95,7 +108,7 @@ export const doc = {
95
108
  {
96
109
  type: 'template.list',
97
110
  description:
98
- 'Every discovered template (page + block); each entry carries id, name, description, kind, owning package, optional category and componentsUsed, and readiness flags. Filtered by type/package when provided.',
111
+ 'The effective templates (page + block); a valid integration replacement takes the place of its Core target and carries `replaces`. Pass `package` to list one package, including replaced Core originals.',
99
112
  },
100
113
  {
101
114
  type: 'template.show',
@@ -142,7 +155,15 @@ export const doc = {
142
155
  ],
143
156
  examples: [
144
157
  {label: 'List templates', code: 'const {data} = await template();'},
158
+ {
159
+ label: 'List exact Core ids',
160
+ code: "await template(undefined, {list: true, package: '@astryxdesign/core'});",
161
+ },
145
162
  {label: 'Show source', code: "await template('dashboard');"},
163
+ {
164
+ label: 'Select a replaced Core original',
165
+ code: "await template('shell-side-nav', {package: '@astryxdesign/core'});",
166
+ },
146
167
  {
147
168
  label: 'Layout skeleton',
148
169
  code: "await template('dashboard', {skeleton: true});",
@@ -15,7 +15,13 @@
15
15
  * ./list, ./show, ./skeleton, ./copy, ./cdn and shared discovery in foundation/discovery.
16
16
  */
17
17
 
18
- import {discoverAll, pkgOf} from '../../foundation/discovery/template-adapter.mjs';
18
+ import {
19
+ discoverAll,
20
+ discoverAllResolved,
21
+ discoverAllUnresolved,
22
+ pkgOf,
23
+ templateLookupIds,
24
+ } from '../../foundation/discovery/template-adapter.mjs';
19
25
  import {AstryxError} from '../error.mjs';
20
26
  import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
21
27
  import {templateList} from './list/list.mjs';
@@ -88,18 +94,49 @@ export async function template(name, options = {}) {
88
94
  });
89
95
  }
90
96
 
91
- const templates = await discoverAll(cwd);
97
+ const templates =
98
+ packageFilter === '@astryxdesign/core'
99
+ ? await discoverAllUnresolved(cwd)
100
+ : packageFilter
101
+ ? await discoverAllResolved(cwd)
102
+ : await discoverAll(cwd);
92
103
 
93
104
  if (list || (!name && !skeleton)) {
94
105
  return templateList(templates, {type, package: packageFilter});
95
106
  }
96
107
 
97
- // Resolve `name` to a single template. The same id can appear across types
98
- // and/or packages (e.g. a core "hero" page and an integration "hero"
99
- // block); narrow with --type / --package.
100
- let candidates = templates.filter(t => t.dirName === name);
101
- if (type) candidates = candidates.filter(t => t.type === type);
102
- if (packageFilter) candidates = candidates.filter(t => pkgOf(t) === packageFilter);
108
+ // Resolve `name` to a single template. Without an explicit package, an active
109
+ // integration replacement owns the Core id it names. Package-qualified lookup
110
+ // stays exact, which keeps the original addressable as
111
+ // `--package @astryxdesign/core`.
112
+ let pool = templates;
113
+ if (type) pool = pool.filter(t => t.type === type);
114
+ if (packageFilter) pool = pool.filter(t => pkgOf(t) === packageFilter);
115
+ // With no name there is nothing to replace; `--skeleton` alone must still
116
+ // fail as an unknown template.
117
+ const replacements =
118
+ packageFilter || name == null ? [] : pool.filter(t => t.replaces === name);
119
+ let candidates = packageFilter
120
+ ? pool.filter(t => t.dirName === (name ?? ''))
121
+ : replacements.length > 0
122
+ ? replacements
123
+ : pool.filter(t => templateLookupIds(t).includes(name ?? ''));
124
+
125
+ // A rejected same-id declaration must not displace Core for the bare command,
126
+ // but a different-kind integration template remains reachable with --type.
127
+ if (!packageFilter && !type && candidates.length > 1) {
128
+ const core = candidates.filter(t => pkgOf(t) === '@astryxdesign/core');
129
+ const rejected = candidates.filter(t => pkgOf(t) !== '@astryxdesign/core');
130
+ if (
131
+ core.length === 1 &&
132
+ rejected.length === candidates.length - 1 &&
133
+ rejected.every(
134
+ t => t.replacementRejected && t.replacementTarget === (name ?? ''),
135
+ )
136
+ ) {
137
+ candidates = core;
138
+ }
139
+ }
103
140
 
104
141
  if (name && candidates.length === 0) {
105
142
  throw new AstryxError(
@@ -21,6 +21,10 @@ export type TemplateListEntry = {
21
21
  * - Owning package; core (built-in) templates report '@astryxdesign/core'.
22
22
  */
23
23
  package: string;
24
+ /**
25
+ * - Core template id this integration template replaces by default.
26
+ */
27
+ replaces?: string | undefined;
24
28
  /**
25
29
  * - Optional grouping/category label.
26
30
  */
@@ -116,17 +120,11 @@ export type TemplateOptions = {
116
120
  */
117
121
  cdn?: string | boolean | undefined;
118
122
  /**
119
- * Filter templates by kind: 'page' or 'block'. Only applies to list views.
123
+ * Filter templates by kind: 'page' or 'block'. Narrows both list and direct lookup.
120
124
  */
121
125
  type?: "page" | "block" | undefined;
122
126
  /**
123
- * Narrow to templates from a specific package (id-only lookups across packages are ambiguous).
127
+ * Narrow to templates from a specific package. Without it, a valid integration replacement is selected for the Core id;
124
128
  */
125
129
  package?: string | undefined;
126
- targetPath?: string | undefined;
127
- /**
128
- * Overwrite an existing target file instead of erroring (ERR_FILE_EXISTS).
129
- */
130
- overwrite?: boolean | undefined;
131
- cwd?: string | undefined;
132
130
  };
@@ -31,6 +31,7 @@
31
31
  * @property {string} description
32
32
  * @property {'page' | 'block'} type
33
33
  * @property {string} package - Owning package; core (built-in) templates report '@astryxdesign/core'.
34
+ * @property {string} [replaces] - Core template id this integration template replaces by default.
34
35
  * @property {string} [category] - Optional grouping/category label.
35
36
  * @property {string[]} [componentsUsed] - Component display names the template composes.
36
37
  * @property {number} [aspectRatio] - Block preview width/height ratio.
@@ -93,8 +94,8 @@
93
94
  * @property {boolean} [skeleton]
94
95
  * @property {boolean} [show]
95
96
  * @property {boolean | string} [cdn] Write the no-build-step CDN starter page instead of resolving a template. A string is used as the destination path.
96
- * @property {'page' | 'block'} [type] Filter templates by kind: 'page' or 'block'. Only applies to list views.
97
- * @property {string} [package] Narrow to templates from a specific package (id-only lookups across packages are ambiguous).
97
+ * @property {'page' | 'block'} [type] Filter templates by kind: 'page' or 'block'. Narrows both list and direct lookup.
98
+ * @property {string} [package] Narrow to templates from a specific package. Without it, a valid integration replacement is selected for the Core id; @astryxdesign/core explicitly selects the original.
98
99
  * @property {string} [targetPath]
99
100
  * @property {boolean} [overwrite] Overwrite an existing target file instead of erroring (ERR_FILE_EXISTS).
100
101
  * @property {string} [cwd]
@@ -13,7 +13,7 @@
13
13
  export function listThemes(): BundledTheme[];
14
14
  /**
15
15
  * Bundled themes plus source themes from integrations installed in `cwd`.
16
- * A project/config load failure degrades to the bundled catalog, preserving the
16
+ * A project/config load failure degrades to the bundled set, preserving the
17
17
  * command's historical usefulness outside a configured project.
18
18
  * @param {string} [cwd]
19
19
  * @returns {Promise<import('../../foundation/discovery/theme-discovery.mjs').DiscoveredTheme[]>}
@@ -35,6 +35,5 @@ export function findTheme(slug?: string, options?: {
35
35
  */
36
36
  export type BundledTheme = Pick<import("../../foundation/discovery/theme-discovery.mjs").DiscoveredTheme, "slug" | "displayName" | "description" | "maintained" | "entry" | "exportName" | "files">;
37
37
  import { BUNDLED_THEME_PACKAGE } from '../../foundation/discovery/theme-discovery.mjs';
38
- import { MANIFEST_PATH } from '../../foundation/discovery/theme-discovery.mjs';
39
38
  import { THEMES_DIR } from '../../foundation/discovery/theme-discovery.mjs';
40
- export { BUNDLED_THEME_PACKAGE, MANIFEST_PATH, THEMES_DIR };
39
+ export { BUNDLED_THEME_PACKAGE, THEMES_DIR };
@@ -5,20 +5,19 @@
5
5
  *
6
6
  * `listThemes()` intentionally keeps its historical synchronous, bundled-only
7
7
  * contract. Project-aware callers use `listAvailableThemes()`, which asks
8
- * Project for the bundled catalog plus every installed integration catalog.
8
+ * Project for the bundled themes plus every installed integration theme root.
9
9
  */
10
10
 
11
11
  import {Project} from '../../foundation/config/project.mjs';
12
12
  import {
13
13
  BUNDLED_THEME_PACKAGE,
14
- MANIFEST_PATH,
15
14
  THEMES_DIR,
16
15
  discoverBundledThemes,
17
16
  } from '../../foundation/discovery/theme-discovery.mjs';
18
17
  import {AstryxError} from '../error.mjs';
19
18
  import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
20
19
 
21
- export {BUNDLED_THEME_PACKAGE, MANIFEST_PATH, THEMES_DIR};
20
+ export {BUNDLED_THEME_PACKAGE, THEMES_DIR};
22
21
 
23
22
  /**
24
23
  * A bundled theme entry kept for the historical public `listThemes()` helper.
@@ -55,7 +54,7 @@ function availableBundledThemes() {
55
54
  /**
56
55
  * Load available themes with any package-owned integration issues found while
57
56
  * discovering them. The issue set lets a package-scoped lookup distinguish an
58
- * absent theme from an installed package whose catalog is broken.
57
+ * absent theme from an installed package whose theme descriptors are broken.
59
58
  * @param {string} cwd
60
59
  * @returns {Promise<{themes: import('../../foundation/discovery/theme-discovery.mjs').DiscoveredTheme[], issues: Array<import('../../foundation/integrations/issue').AstryxIntegrationIssue & {package: string}>}>}
61
60
  */
@@ -71,7 +70,7 @@ async function availableThemeState(cwd) {
71
70
 
72
71
  /**
73
72
  * Bundled themes plus source themes from integrations installed in `cwd`.
74
- * A project/config load failure degrades to the bundled catalog, preserving the
73
+ * A project/config load failure degrades to the bundled set, preserving the
75
74
  * command's historical usefulness outside a configured project.
76
75
  * @param {string} [cwd]
77
76
  * @returns {Promise<import('../../foundation/discovery/theme-discovery.mjs').DiscoveredTheme[]>}
@@ -37,21 +37,10 @@ beforeEach(() => {
37
37
  "export default {themes: './themes'};\n",
38
38
  );
39
39
  fs.writeFileSync(
40
- path.join(packageDir, 'themes', 'manifest.json'),
41
- JSON.stringify({
42
- version: 1,
43
- themes: [
44
- {
45
- slug: 'ocean',
46
- displayName: 'Ocean',
47
- description: 'Integration theme that ships a font.',
48
- maintained: true,
49
- entry: 'oceanTheme.ts',
50
- exportName: 'oceanTheme',
51
- files: ['oceanTheme.ts', 'fonts/ocean.woff2'],
52
- },
53
- ],
54
- }),
40
+ path.join(themeDir, 'oceanTheme.doc.mjs'),
41
+ `/** @type {import('@astryxdesign/cli/authoring').ThemeDoc} */
42
+ export default {type: 'theme', name: 'ocean', displayName: 'Ocean', description: 'Integration theme that ships a font.', maintained: true};
43
+ `,
55
44
  );
56
45
  fs.writeFileSync(
57
46
  path.join(themeDir, 'oceanTheme.ts'),
@@ -64,14 +53,18 @@ afterEach(() => {
64
53
  fs.rmSync(tmpDir, {recursive: true, force: true});
65
54
  });
66
55
 
67
- describe('themeAdd copies every listed file', () => {
56
+ describe('themeAdd copies every file of the theme', () => {
68
57
  it('copies a binary file byte for byte', async () => {
69
58
  const result = await themeAdd('ocean', {
70
59
  cwd: tmpDir,
71
60
  package: '@acme/themes',
72
61
  });
73
62
 
74
- expect(result.data.files).toEqual(['oceanTheme.ts', 'fonts/ocean.woff2']);
63
+ expect(result.data.files).toEqual([
64
+ 'oceanTheme.ts',
65
+ 'fonts/ocean.woff2',
66
+ 'oceanTheme.doc.mjs',
67
+ ]);
75
68
  const copied = fs.readFileSync(
76
69
  path.join(tmpDir, 'src', 'themes', 'ocean', 'fonts', 'ocean.woff2'),
77
70
  );
@@ -30,7 +30,20 @@ describe('themeAdd (api/theme/add)', () => {
30
30
  expect(result.data.slug).toBe('neutral');
31
31
  expect(result.data.package).toBe('@astryxdesign/cli');
32
32
  expect(result.data.outputDir).toBe(path.join('src', 'themes', 'neutral'));
33
- expect(result.data.files.length).toBeGreaterThan(0);
33
+ // Exactly what the bundle has always copied, in that order: the CLI's own
34
+ // descriptor stays behind.
35
+ expect(result.data.files).toEqual([
36
+ 'neutralTheme.ts',
37
+ 'icons.tsx',
38
+ 'neutralPalettes.ts',
39
+ 'neutralPalettes.generated.ts',
40
+ 'neutralPaletteRefs.generated.ts',
41
+ 'neutralPalettes.generated.receipt.json',
42
+ 'palette.config.json',
43
+ ]);
44
+ expect(
45
+ fs.readdirSync(path.join(tmpDir, 'src', 'themes', 'neutral')).sort(),
46
+ ).toEqual([...result.data.files].sort());
34
47
  for (const f of result.data.files) {
35
48
  expect(
36
49
  fs.existsSync(path.join(tmpDir, 'src', 'themes', 'neutral', f)),
@@ -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