@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
@@ -0,0 +1,220 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ import {afterEach, beforeEach, describe, expect, it} from 'vitest';
4
+ import * as fs from 'node:fs';
5
+ import * as os from 'node:os';
6
+ import * as path from 'node:path';
7
+ import manifest from '../index.mjs';
8
+ import migrate from '../migrate-theme-catalog-to-descriptors.mjs';
9
+ import {runCodemods} from '../../../runner.mjs';
10
+ import {discoverThemeDirectory} from '../../../../../foundation/discovery/theme-discovery.mjs';
11
+
12
+ let root;
13
+
14
+ beforeEach(() => {
15
+ root = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-theme-catalog-'));
16
+ });
17
+
18
+ afterEach(() => {
19
+ fs.rmSync(root, {recursive: true, force: true});
20
+ });
21
+
22
+ /** A catalog entry exactly as `astryx integration add theme <slug>` wrote it in 0.6. */
23
+ function entry(slug, overrides = {}) {
24
+ const identifier = slug.replace(/-([a-z0-9])/gu, (_, c) => c.toUpperCase());
25
+ const displayName = slug
26
+ .split('-')
27
+ .map(part => part[0].toUpperCase() + part.slice(1))
28
+ .join(' ');
29
+ return {
30
+ slug,
31
+ displayName,
32
+ description: `${displayName} theme.`,
33
+ maintained: true,
34
+ entry: `${identifier}Theme.ts`,
35
+ exportName: `${identifier}Theme`,
36
+ files: [`${identifier}Theme.ts`],
37
+ ...overrides,
38
+ };
39
+ }
40
+
41
+ /** @param {ReturnType<typeof entry>[]} themes */
42
+ function writeKit(themes, {sources = true} = {}) {
43
+ fs.writeFileSync(
44
+ path.join(root, 'package.json'),
45
+ '{"name":"@acme/kit","version":"1.0.0"}\n',
46
+ );
47
+ fs.writeFileSync(
48
+ path.join(root, 'astryx.integration.mjs'),
49
+ "export default {themes: './themes'};\n",
50
+ );
51
+ for (const theme of themes) {
52
+ const source = path.join(root, 'themes', theme.slug, theme.entry);
53
+ fs.mkdirSync(path.dirname(source), {recursive: true});
54
+ if (sources) {
55
+ fs.writeFileSync(
56
+ source,
57
+ `import {defineTheme} from '@astryxdesign/core/theme';\n\nexport const ${theme.exportName} = defineTheme({\n name: '${theme.slug}',\n});\n`,
58
+ );
59
+ }
60
+ }
61
+ fs.mkdirSync(path.join(root, 'themes'), {recursive: true});
62
+ fs.writeFileSync(
63
+ path.join(root, 'themes', 'manifest.json'),
64
+ `${JSON.stringify({version: 1, themes}, null, 2)}\n`,
65
+ );
66
+ }
67
+
68
+ const catalog = () => path.join(root, 'themes', 'manifest.json');
69
+
70
+ /** @param {boolean} apply @param {string} [srcPath] */
71
+ const run = (apply, srcPath = root) =>
72
+ runCodemods([{version: 'next', transforms: manifest}], {
73
+ apply,
74
+ path: srcPath,
75
+ codemod: undefined,
76
+ silent: true,
77
+ root,
78
+ });
79
+
80
+ describe('migrate-theme-catalog-to-descriptors', () => {
81
+ it('is staged for the next release as a project codemod', () => {
82
+ expect(manifest.map(t => [t.name, t.meta.codemodType])).toEqual([
83
+ ['migrate-theme-catalog-to-descriptors', 'project'],
84
+ ['migrate-native-picker-to-presentation', undefined],
85
+ ]);
86
+ });
87
+
88
+ it('writes one typed descriptor per catalog theme and removes the catalog', async () => {
89
+ writeKit([
90
+ entry('ocean'),
91
+ entry('deep-sea', {
92
+ displayName: "Deep 'Sea'",
93
+ description: 'Line one\nline two \\ done.',
94
+ maintained: false,
95
+ }),
96
+ ]);
97
+
98
+ const result = await run(true);
99
+
100
+ expect(result).toMatchObject({errors: [], totalFilesChanged: 3});
101
+ expect(fs.existsSync(catalog())).toBe(false);
102
+ expect(
103
+ fs.readFileSync(
104
+ path.join(root, 'themes/ocean/oceanTheme.doc.mjs'),
105
+ 'utf-8',
106
+ ),
107
+ ).toBe(
108
+ "/** @type {import('@astryxdesign/cli/authoring').ThemeDoc} */\nexport default {\n type: 'theme',\n name: 'ocean',\n displayName: 'Ocean',\n description: 'Ocean theme.',\n maintained: true,\n};\n",
109
+ );
110
+ const themes = discoverThemeDirectory(
111
+ path.join(root, 'themes'),
112
+ '@acme/kit',
113
+ );
114
+ expect(
115
+ themes.map(({slug, displayName, description, maintained}) => ({
116
+ slug,
117
+ displayName,
118
+ description,
119
+ maintained,
120
+ })),
121
+ ).toEqual([
122
+ {
123
+ slug: 'deep-sea',
124
+ displayName: "Deep 'Sea'",
125
+ description: 'Line one\nline two \\ done.',
126
+ maintained: false,
127
+ },
128
+ {
129
+ slug: 'ocean',
130
+ displayName: 'Ocean',
131
+ description: 'Ocean theme.',
132
+ maintained: true,
133
+ },
134
+ ]);
135
+ });
136
+
137
+ it('previews without writing, even with no source folder', async () => {
138
+ writeKit([entry('ocean')]);
139
+ // A staged code codemod (migrate-native-picker-to-presentation) requires
140
+ // the source folder to exist; an empty one exercises the same preview.
141
+ fs.mkdirSync(path.join(root, 'src'), {recursive: true});
142
+
143
+ const result = await run(false, path.join(root, 'src'));
144
+
145
+ expect(result).toMatchObject({
146
+ errors: [],
147
+ totalFilesChanged: 2,
148
+ writtenFiles: [],
149
+ });
150
+ expect(fs.existsSync(catalog())).toBe(true);
151
+ expect(
152
+ fs.existsSync(path.join(root, 'themes/ocean/oceanTheme.doc.mjs')),
153
+ ).toBe(false);
154
+ });
155
+
156
+ it('keeps a descriptor that already exists and still removes the catalog', async () => {
157
+ writeKit([entry('ocean'), entry('reef')]);
158
+ const kept = path.join(root, 'themes/ocean/oceanTheme.doc.mjs');
159
+ fs.writeFileSync(
160
+ kept,
161
+ "export default {type: 'theme', name: 'ocean', displayName: 'Mine', description: '', maintained: true};\n",
162
+ );
163
+
164
+ const result = await run(true);
165
+
166
+ expect(result.errors).toEqual([]);
167
+ expect(fs.readFileSync(kept, 'utf-8')).toContain("displayName: 'Mine'");
168
+ expect(
169
+ fs.existsSync(path.join(root, 'themes/reef/reefTheme.doc.mjs')),
170
+ ).toBe(true);
171
+ expect(fs.existsSync(catalog())).toBe(false);
172
+ });
173
+
174
+ it('changes nothing and names each entry that cannot convert', async () => {
175
+ writeKit([
176
+ entry('ocean'),
177
+ entry('sea', {exportName: 'oceanBlue'}),
178
+ entry('nested', {
179
+ entry: 'src/nestedTheme.ts',
180
+ files: ['src/nestedTheme.ts'],
181
+ }),
182
+ ]);
183
+ fs.rmSync(path.join(root, 'themes/ocean/oceanTheme.ts'));
184
+ const before = fs.readFileSync(catalog(), 'utf-8');
185
+
186
+ const result = await run(true);
187
+
188
+ expect(result.errors.map(e => [e.file, e.error])).toEqual([
189
+ ['themes/ocean', 'holds no oceanTheme.ts for theme "ocean".'],
190
+ [
191
+ 'themes/manifest.json',
192
+ 'theme "sea" exports "oceanBlue" from seaTheme.ts; a descriptor takes the export name from the file name, so rename the export or the file to match.',
193
+ ],
194
+ [
195
+ 'themes/manifest.json',
196
+ 'theme "nested" has entry "src/nestedTheme.ts"; a descriptor sits beside a .ts, .tsx, .mjs, or .js source directly in themes/nested/.',
197
+ ],
198
+ ]);
199
+ expect(fs.readFileSync(catalog(), 'utf-8')).toBe(before);
200
+ expect(fs.existsSync(path.join(root, 'themes/sea/seaTheme.doc.mjs'))).toBe(
201
+ false,
202
+ );
203
+ });
204
+
205
+ it('leaves a package with no catalog to convert alone', async () => {
206
+ const empty = {writes: [], deletes: [], problems: []};
207
+ await expect(migrate(root)).resolves.toEqual(empty);
208
+ fs.writeFileSync(
209
+ path.join(root, 'astryx.integration.mjs'),
210
+ 'export default {};\n',
211
+ );
212
+ await expect(migrate(root)).resolves.toEqual(empty);
213
+ fs.writeFileSync(
214
+ path.join(root, 'astryx.integration.mjs'),
215
+ "export default {themes: './themes'};\n",
216
+ );
217
+ fs.mkdirSync(path.join(root, 'themes'));
218
+ await expect(migrate(root)).resolves.toEqual(empty);
219
+ });
220
+ });
@@ -7,4 +7,22 @@
7
7
  * this file into the resolved version folder.
8
8
  */
9
9
 
10
- export default [];
10
+ import migrateThemeCatalogToDescriptors, {
11
+ meta as migrateThemeCatalogToDescriptorsMeta,
12
+ } from './migrate-theme-catalog-to-descriptors.mjs';
13
+ import migrateNativePickerToPresentation, {
14
+ meta as migrateNativePickerToPresentationMeta,
15
+ } from './migrate-native-picker-to-presentation.mjs';
16
+
17
+ export default [
18
+ {
19
+ name: 'migrate-theme-catalog-to-descriptors',
20
+ transform: migrateThemeCatalogToDescriptors,
21
+ meta: migrateThemeCatalogToDescriptorsMeta,
22
+ },
23
+ {
24
+ name: 'migrate-native-picker-to-presentation',
25
+ transform: migrateNativePickerToPresentation,
26
+ meta: migrateNativePickerToPresentationMeta,
27
+ },
28
+ ];
@@ -0,0 +1,148 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Codemod: migrate nativePicker to presentation on date/time inputs
5
+ *
6
+ * `spec:AST-043` FR3 mapping, applied only to static literals written
7
+ * directly on imported `DateInput`, `DateTimeInput`, and `TimeInput`
8
+ * elements: the prop is renamed to `presentation` and its value mapped.
9
+ * When the element already sets `presentation`, the deprecated prop is
10
+ * removed (presentation wins, FR4). Dynamic values are left unchanged —
11
+ * the deprecated prop keeps working, so an unmigrated callsite is still
12
+ * correct, and guessing at an expression's values would not be.
13
+ */
14
+
15
+ import {transformProp} from '../../transform-prop.mjs';
16
+
17
+ export const meta = {
18
+ title: 'Migrate nativePicker to presentation',
19
+ description:
20
+ 'Renames `nativePicker` to `presentation` on DateInput, DateTimeInput, ' +
21
+ 'and TimeInput, mapping touch→adaptive-native, always→native, and ' +
22
+ 'never→adaptive-bottom-sheet (text-input for TimeInput). Dynamic ' +
23
+ 'values are left for manual migration; the deprecated prop still works.',
24
+ };
25
+
26
+ const CORE_IMPORT_RE = /^@(astryxdesign|xds)\/core(?:\/|$)/;
27
+
28
+ const COMPONENT_PROPS = new Map([
29
+ ['DateInput', new Set(['nativePicker'])],
30
+ ['DateTimeInput', new Set(['nativePicker'])],
31
+ ['TimeInput', new Set(['nativePicker'])],
32
+ ]);
33
+
34
+ /** @param {string} component @param {string} value */
35
+ function mapValue(component, value) {
36
+ switch (value) {
37
+ case 'touch':
38
+ return 'adaptive-native';
39
+ case 'always':
40
+ return 'native';
41
+ case 'never':
42
+ return component === 'TimeInput' ? 'text-input' : 'adaptive-bottom-sheet';
43
+ default:
44
+ return undefined;
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Collect the string-literal leaves of a value expression without mutating
50
+ * anything. Returns false for any dynamic or non-string node.
51
+ * @param {any} node
52
+ * @param {any[]} leaves
53
+ * @returns {boolean}
54
+ */
55
+ function collectStaticLeaves(node, leaves) {
56
+ if (!node) return false;
57
+ if (
58
+ node.type === 'TSAsExpression' ||
59
+ node.type === 'TSSatisfiesExpression' ||
60
+ node.type === 'TypeCastExpression' ||
61
+ node.type === 'ParenthesizedExpression'
62
+ ) {
63
+ return collectStaticLeaves(node.expression, leaves);
64
+ }
65
+ if (node.type === 'ConditionalExpression') {
66
+ return (
67
+ collectStaticLeaves(node.consequent, leaves) &&
68
+ collectStaticLeaves(node.alternate, leaves)
69
+ );
70
+ }
71
+ if (
72
+ (node.type !== 'StringLiteral' && node.type !== 'Literal') ||
73
+ typeof node.value !== 'string'
74
+ ) {
75
+ return false;
76
+ }
77
+ leaves.push(node);
78
+ return true;
79
+ }
80
+
81
+ /**
82
+ * Map every leaf, or none of them: a mixed static/dynamic conditional must
83
+ * stay byte-identical, never half-migrated.
84
+ * @param {any} node
85
+ * @param {string} component
86
+ */
87
+ function mapStaticValue(node, component) {
88
+ /** @type {any[]} */
89
+ const leaves = [];
90
+ if (!collectStaticLeaves(node, leaves)) return false;
91
+ if (leaves.some(leaf => mapValue(component, leaf.value) === undefined)) {
92
+ return false;
93
+ }
94
+ for (const leaf of leaves) {
95
+ leaf.value = mapValue(component, leaf.value);
96
+ if (leaf.raw) leaf.raw = undefined;
97
+ }
98
+ return true;
99
+ }
100
+
101
+ /**
102
+ * @param {import('../../../../authoring/codemod/type').AstryxCodemodFile} file
103
+ * @param {import('../../../../authoring/codemod/type').CodemodTransformApi} api
104
+ * @returns {string | null | undefined}
105
+ */
106
+ export default function transformer(file, api) {
107
+ if (!file.source.includes('nativePicker')) return undefined;
108
+ const j = api.jscodeshift;
109
+ const root = j(file.source);
110
+ let hasChanges = false;
111
+
112
+ transformProp(
113
+ root,
114
+ j,
115
+ {
116
+ matchesImport: source => CORE_IMPORT_RE.test(source),
117
+ components: COMPONENT_PROPS,
118
+ },
119
+ (propPath, {component}) => {
120
+ const opening = propPath.parent?.node;
121
+ const attributes = opening?.attributes ?? [];
122
+ const hasPresentation = attributes.some(
123
+ (/** @type {any} */ attribute) =>
124
+ attribute.type === 'JSXAttribute' &&
125
+ attribute.name?.name === 'presentation',
126
+ );
127
+ const prop = propPath.node;
128
+ if (hasPresentation) {
129
+ // FR4: presentation wins; drop the deprecated prop.
130
+ opening.attributes = attributes.filter(
131
+ (/** @type {any} */ attribute) => attribute !== prop,
132
+ );
133
+ hasChanges = true;
134
+ return;
135
+ }
136
+ const value =
137
+ prop.value?.type === 'JSXExpressionContainer'
138
+ ? prop.value.expression
139
+ : prop.value;
140
+ if (!mapStaticValue(value, component)) return;
141
+ prop.name.name = 'presentation';
142
+ hasChanges = true;
143
+ },
144
+ );
145
+
146
+ if (!hasChanges) return undefined;
147
+ return root.toSource({quote: 'single'});
148
+ }
@@ -0,0 +1,141 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Give each integration theme a typed descriptor instead of the
5
+ * `manifest.json` theme catalog.
6
+ *
7
+ * Astryx 0.6 scaffolded integration themes into one catalog,
8
+ * `<themes root>/manifest.json`. Each theme now carries a strongly typed
9
+ * same-stem `.doc.mjs` descriptor, and a themes root that still holds the
10
+ * catalog is refused. This project codemod reads the package's integration
11
+ * manifest, plans one descriptor per catalog entry beside that theme's source,
12
+ * and removes the catalog. When any entry cannot convert, it plans nothing and
13
+ * names the entry, so the package is never left half converted.
14
+ */
15
+
16
+ import * as fs from 'node:fs';
17
+ import * as path from 'node:path';
18
+ import {loadManifestObject} from '../../../../foundation/integrations/integrations.mjs';
19
+ import {findLocalIntegrationManifestOrNull} from '../../../../foundation/integrations/manifest-writer.mjs';
20
+ import {themeDescriptorSource} from '../../../../foundation/integrations/theme-descriptor.mjs';
21
+
22
+ export const meta = {
23
+ title:
24
+ 'Give each integration theme a typed descriptor instead of the manifest.json catalog',
25
+ description:
26
+ 'Writes <name>Theme.doc.mjs beside each theme the catalog lists, then removes the catalog.',
27
+ codemodType: 'project',
28
+ };
29
+
30
+ const SLUG = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
31
+ const SOURCE = /\.(?:ts|tsx|mjs|js)$/u;
32
+
33
+ /**
34
+ * @param {string} root the package directory
35
+ * @returns {Promise<import('../../runner.mjs').ProjectCodemodPlan>}
36
+ */
37
+ export default async function migrateThemeCatalogToDescriptors(root) {
38
+ /** @type {import('../../runner.mjs').ProjectCodemodPlan} */
39
+ const plan = {writes: [], deletes: [], problems: []};
40
+ /** @param {string} file @returns {string} */
41
+ const rel = file => path.relative(root, file).split(path.sep).join('/');
42
+ /** @param {string} file @param {string} message */
43
+ const problem = (file, message) => plan.problems.push({file, message});
44
+
45
+ const manifestFile = findLocalIntegrationManifestOrNull(root);
46
+ if (!manifestFile) return plan;
47
+ const manifest = await loadManifestObject(
48
+ manifestFile,
49
+ `Integration manifest ${path.basename(manifestFile)}`,
50
+ {fresh: true},
51
+ );
52
+ if (typeof manifest.themes !== 'string') return plan;
53
+ const themesRoot = path.resolve(root, manifest.themes);
54
+ const fromRoot = path.relative(root, themesRoot);
55
+ if (fromRoot.startsWith('..') || path.isAbsolute(fromRoot)) return plan;
56
+ const catalogFile = path.join(themesRoot, 'manifest.json');
57
+ if (!fs.existsSync(catalogFile)) return plan;
58
+ const catalogPath = rel(catalogFile);
59
+
60
+ let catalog;
61
+ try {
62
+ catalog = JSON.parse(fs.readFileSync(catalogFile, 'utf-8'));
63
+ } catch (error) {
64
+ const reason = error instanceof Error ? error.message : String(error);
65
+ problem(catalogPath, `is not valid JSON (${reason}).`);
66
+ return plan;
67
+ }
68
+ if (
69
+ !catalog ||
70
+ typeof catalog !== 'object' ||
71
+ catalog.version !== 1 ||
72
+ !Array.isArray(catalog.themes)
73
+ ) {
74
+ problem(catalogPath, 'is not a version 1 theme catalog.');
75
+ return plan;
76
+ }
77
+
78
+ for (const [index, entry] of catalog.themes.entries()) {
79
+ const slug = entry?.slug;
80
+ if (typeof slug !== 'string' || !SLUG.test(slug)) {
81
+ problem(
82
+ catalogPath,
83
+ `themes[${index}] has no lowercase kebab-case slug; fix the entry or add that theme's descriptor by hand.`,
84
+ );
85
+ continue;
86
+ }
87
+ const themeDir = path.join(themesRoot, slug);
88
+ const source = entry.entry;
89
+ if (
90
+ typeof source !== 'string' ||
91
+ !SOURCE.test(source) ||
92
+ source !== path.basename(source)
93
+ ) {
94
+ problem(
95
+ catalogPath,
96
+ `theme "${slug}" has entry ${JSON.stringify(source)}; a descriptor sits beside a .ts, .tsx, .mjs, or .js source directly in ${rel(themeDir)}/.`,
97
+ );
98
+ continue;
99
+ }
100
+ const stem = source.replace(SOURCE, '');
101
+ if (entry.exportName !== stem) {
102
+ problem(
103
+ catalogPath,
104
+ `theme "${slug}" exports ${JSON.stringify(entry.exportName)} from ${source}; a descriptor takes the export name from the file name, so rename the export or the file to match.`,
105
+ );
106
+ continue;
107
+ }
108
+ if (typeof entry.displayName !== 'string' || !entry.displayName.trim()) {
109
+ problem(catalogPath, `theme "${slug}" has no displayName.`);
110
+ continue;
111
+ }
112
+ if (typeof entry.description !== 'string') {
113
+ problem(catalogPath, `theme "${slug}" has no description string.`);
114
+ continue;
115
+ }
116
+ if (typeof entry.maintained !== 'boolean') {
117
+ problem(catalogPath, `theme "${slug}" has no maintained flag.`);
118
+ continue;
119
+ }
120
+ if (!fs.existsSync(path.join(themeDir, source))) {
121
+ problem(rel(themeDir), `holds no ${source} for theme "${slug}".`);
122
+ continue;
123
+ }
124
+ const descriptor = path.join(themeDir, `${stem}.doc.mjs`);
125
+ if (fs.existsSync(descriptor)) continue;
126
+ plan.writes.push({
127
+ path: descriptor,
128
+ contents: themeDescriptorSource({
129
+ type: 'theme',
130
+ name: slug,
131
+ displayName: entry.displayName,
132
+ description: entry.description,
133
+ maintained: entry.maintained,
134
+ }),
135
+ });
136
+ }
137
+ if (plan.problems.length > 0)
138
+ return {writes: [], deletes: [], problems: plan.problems};
139
+ plan.deletes.push(catalogFile);
140
+ return plan;
141
+ }
@@ -98,11 +98,11 @@ export const docs = {
98
98
  },
99
99
  {
100
100
  type: 'prose',
101
- text: 'These stylesheets are cascade-layered: the reset loads in @layer reset and component styles in @layer astryx-base. If your project has existing global CSS, a legacy reset, or Tailwind, declare the layer order explicitly and assign every stylesheet to a layer deliberately: unlayered styles and later layers both override astryx-base regardless of specificity. See the Cascade Layer Safety section in `astryx docs migration` before building screens.',
101
+ text: 'These stylesheets are cascade-layered: the reset loads in @layer reset and component styles in @layer astryx-base. If your project has existing global CSS, a legacy reset, or Tailwind, declare the layer order explicitly and assign every stylesheet to a layer deliberately: unlayered styles and later layers both override astryx-base regardless of specificity. See the Cascade Layer Safety section in {@link generic:migration} before building screens.',
102
102
  },
103
103
  {
104
104
  type: 'prose',
105
- text: 'Run `astryx docs theme` for the full theming guide.',
105
+ text: 'Run {@link generic:theme} for the full theming guide.',
106
106
  },
107
107
  ],
108
108
  },
@@ -25,7 +25,7 @@ export const docsDense = {
25
25
  },
26
26
  {
27
27
  type: 'prose',
28
- text: 'decides layout, not component APIs. npx astryx build "<idea>" = closest template for your app type. npx astryx component <Name> = props.',
28
+ text: 'decides layout, not component APIs. npx astryx build "<idea>" = the template to start from for your app type. npx astryx component <Name> = props.',
29
29
  },
30
30
  ],
31
31
  },
@@ -71,7 +71,7 @@ export const docsDense = {
71
71
  null,
72
72
  {
73
73
  type: 'prose',
74
- text: 'verify: you can state the reason in one sentence, and it still holds if the nav doubles. npx astryx build "<idea>" names the closest template, --skeleton shows the pairing wired up.',
74
+ text: 'verify: you can state the reason in one sentence, and it still holds if the nav doubles. npx astryx build "<idea>" names the template to start from; scaffold it and the pairing is wired up.',
75
75
  },
76
76
  // Best practices
77
77
  null,
@@ -106,7 +106,7 @@ export const docs = {
106
106
  },
107
107
  {
108
108
  type: 'prose',
109
- text: 'Verify: you can state the reason in one sentence, and the choice still holds if the nav doubles in size. `npx astryx build "<idea>"` names the closest template, and its `--skeleton` shows the pairing already wired up.',
109
+ text: 'Verify: you can state the reason in one sentence, and the choice still holds if the nav doubles in size. `npx astryx build "<idea>"` names the template to start from; scaffold it and the pairing is already wired up.',
110
110
  },
111
111
 
112
112
  {type: 'heading', level: 3, text: 'Best practices'},
@@ -39,10 +39,10 @@ export const docs = {
39
39
  style: 'ordered',
40
40
  items: [
41
41
  'Use components for everything they cover',
42
- 'Page layout is frame-first: pick the shell and budget regions before writing content (see \`astryx docs layout\`)',
42
+ 'Page layout is frame-first: pick the shell and budget regions before writing content (see {@link generic:layout})',
43
43
  'Dense data renders as rows (Table, List/Item), edge-to-edge with dividers; Card is for widgets, galleries, and settings groups',
44
- 'StyleX or Tailwind for custom styling; both are first-class (see \`astryx docs styling\`)',
45
- 'Semantic tokens, not hardcoded values (see \`astryx docs tokens\`)',
44
+ 'StyleX or Tailwind for custom styling; both are first-class (see {@link generic:styling})',
45
+ 'Semantic tokens, not hardcoded values (see {@link generic:tokens})',
46
46
  'CSS custom properties for colors, not hex values',
47
47
  'Form inputs are controlled (value + onChange)',
48
48
  'Use useLinkComponent() for navigation so consumers can plug in their framework router via LinkProvider',
@@ -60,7 +60,7 @@ export const docs = {
60
60
  },
61
61
  {
62
62
  type: 'prose',
63
- text: 'See \`astryx docs styling\` for the complete guide with examples.',
63
+ text: 'See {@link generic:styling} for the complete guide with examples.',
64
64
  },
65
65
  ],
66
66
  },
@@ -76,7 +76,7 @@ export const docs = {
76
76
  'Hardcoded colors (#fff). Use var(--color-*) or Tailwind semantic classes (text-primary, bg-surface)',
77
77
  'Hardcoded spacing (16px). Use spacing tokens or Tailwind spacing utilities',
78
78
  'Hardcoded <a> elements. Use useLinkComponent() so consumers can swap in their framework router via LinkProvider',
79
- 'Wrapping every list item or page section in a Card. Decide the frame first; dense data renders as rows (see \`astryx docs layout\`)',
79
+ 'Wrapping every list item or page section in a Card. Decide the frame first; dense data renders as rows (see {@link generic:layout})',
80
80
  'Badge as decoration. Reserve Badge for counts and enumerated states; use StatusDot or Token for status',
81
81
  'Inventing props. Read component docs first',
82
82
  ],
@@ -89,7 +89,7 @@ export const docs = {
89
89
  content: [
90
90
  {
91
91
  type: 'prose',
92
- text: 'The design system provides semantic design tokens for spacing, color, radius, shadow, typography, and size. Tokens adapt to the active theme and color mode. Run \`astryx docs tokens\` for the full reference with all values.',
92
+ text: 'The design system provides semantic design tokens for spacing, color, radius, shadow, typography, and size. Tokens adapt to the active theme and color mode. Run {@link generic:tokens} for the full reference with all values.',
93
93
  },
94
94
  ],
95
95
  },
@@ -24,7 +24,7 @@ export const docs = {
24
24
  },
25
25
  {
26
26
  type: 'prose',
27
- text: 'For available token names and values, run `astryx docs tokens`. Focused references are also available with `astryx docs color`, `astryx docs spacing`, `astryx docs shape`, `astryx docs typography`, `astryx docs elevation`, and `astryx docs motion`.',
27
+ text: 'For available token names and values, run {@link generic:tokens}. Focused references are also available with {@link generic:color}, {@link generic:spacing}, {@link generic:shape}, {@link generic:typography}, {@link generic:elevation}, and {@link generic:motion}.',
28
28
  },
29
29
  ],
30
30
  },
@@ -150,7 +150,7 @@ const styles = stylex.create({
150
150
  content: [
151
151
  {
152
152
  type: 'prose',
153
- text: 'The Tailwind v4 bridge at `@astryxdesign/core/tailwind-theme.css` maps Tailwind theme variables to system CSS variables with `@theme inline`, so utility classes like `text-primary`, `bg-surface`, `border-border`, `rounded-lg`, and `shadow-md` stay in sync with the active theme.',
153
+ text: 'The Tailwind v4 bridge at `@astryxdesign/core/tailwind-theme.css` maps Tailwind theme variables to system CSS variables with `@theme reference inline`, so utility classes like `text-primary`, `bg-surface`, `border-border`, `rounded-lg`, and `shadow-md` stay in sync with the active theme without emitting competing runtime declarations.',
154
154
  },
155
155
  {
156
156
  type: 'code',
@@ -455,7 +455,7 @@ function RevenueChart({data}: {data: Array<{x: string; y: number}>}) {
455
455
  'Import the reset/base CSS and a theme CSS file early enough for first paint. For production SSR, prefer built themes from `astryx theme build` or published `/built` theme imports plus `theme.css`.',
456
456
  'Choose one owner for color mode. Theme uses `data-theme="light|dark"` and `color-scheme` to resolve `light-dark()` tokens.',
457
457
  'Map the external library\'s semantic layer to system variables by intent, not by exact naming. For example, MUI `background.paper` maps to `--color-background-surface`.',
458
- 'Use `astryx docs tokens` and focused token docs when building mappings. Keep mappings small at first: text, surface/body/card/popover, border, accent, status, spacing, radius, typography, shadow.',
458
+ 'Use {@link generic:tokens} and focused token docs when building mappings. Keep mappings small at first: text, surface/body/card/popover, border, accent, status, spacing, radius, typography, shadow.',
459
459
  'Use token resolver APIs only for non-CSS APIs that need resolved values.',
460
460
  ],
461
461
  },