@astryxdesign/cli 0.6.3-canary.ea2f048 → 0.6.3-canary.ee13359

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 (571) hide show
  1. package/README.md +114 -76
  2. package/api/blog/blog.doc.mjs +1 -0
  3. package/api/build/build.doc.mjs +4 -3
  4. package/api/build/build.test.mjs +14 -3
  5. package/api/build/build.type.d.mts +36 -2
  6. package/api/build/build.type.mjs +25 -4
  7. package/api/build/help/help.d.mts +8 -5
  8. package/api/build/help/help.mjs +56 -6
  9. package/api/component/_adapter.d.mts +6 -12
  10. package/api/component/_adapter.mjs +20 -10
  11. package/api/component/component.doc.mjs +13 -3
  12. package/api/component/component.mjs +91 -14
  13. package/api/component/component.test.mjs +38 -0
  14. package/api/component/component.type.d.mts +22 -11
  15. package/api/component/component.type.mjs +32 -24
  16. package/api/component/detail/blocks/blocks.d.mts +2 -1
  17. package/api/component/detail/blocks/blocks.mjs +4 -3
  18. package/api/component/list/list.d.mts +0 -5
  19. package/api/component/list/list.mjs +40 -11
  20. package/api/discover/discover.doc.mjs +2 -1
  21. package/api/discover/discover.type.d.mts +4 -4
  22. package/api/discover/discover.type.mjs +10 -10
  23. package/api/docs/_adapter.d.mts +230 -41
  24. package/api/docs/_adapter.mjs +734 -108
  25. package/api/docs/compiled-topics.test.mjs +78 -0
  26. package/api/docs/detail/detail.mjs +22 -63
  27. package/api/docs/detail/section/section.d.mts +1 -1
  28. package/api/docs/detail/section/section.mjs +54 -19
  29. package/api/docs/detail/section/section.test.mjs +50 -0
  30. package/api/docs/docs.d.mts +10 -3
  31. package/api/docs/docs.doc.mjs +54 -16
  32. package/api/docs/docs.mjs +53 -10
  33. package/api/docs/docs.test.mjs +164 -4
  34. package/api/docs/docs.type.d.mts +205 -5
  35. package/api/docs/docs.type.mjs +137 -11
  36. package/api/docs/index/index.d.mts +18 -0
  37. package/api/docs/index/index.mjs +40 -0
  38. package/api/docs/index/index.test.mjs +62 -0
  39. package/api/docs/integration-tree.test.mjs +547 -0
  40. package/api/docs/integrationDocs.test.mjs +114 -8
  41. package/api/docs/list/list.mjs +28 -12
  42. package/api/docs/node/node.d.mts +43 -0
  43. package/api/docs/node/node.mjs +192 -0
  44. package/api/doctor/doctor.d.mts +99 -1
  45. package/api/doctor/doctor.doc.mjs +1 -0
  46. package/api/doctor/doctor.mjs +544 -1
  47. package/api/doctor/doctor.test.mjs +610 -1
  48. package/api/gap-report/gap-report.doc.mjs +8 -4
  49. package/api/hook/_adapter.mjs +19 -5
  50. package/api/hook/hook.doc.mjs +1 -0
  51. package/api/hook/hook.type.d.mts +3 -3
  52. package/api/hook/hook.type.mjs +11 -11
  53. package/api/hook/list/list.d.mts +2 -2
  54. package/api/hook/list/list.mjs +69 -17
  55. package/api/index.d.mts +1 -1
  56. package/api/index.mjs +1 -0
  57. package/api/init/init.doc.mjs +6 -1
  58. package/api/init/init.test.mjs +41 -1
  59. package/api/init/remove/remove.mjs +1 -1
  60. package/api/init/run/run.mjs +20 -10
  61. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  62. package/api/integration/add-contribution.d.mts +2 -1
  63. package/api/integration/add-contribution.mjs +130 -15
  64. package/api/integration/add-contribution.test.mjs +258 -7
  65. package/api/integration/add-theme.mjs +34 -64
  66. package/api/integration/add-theme.test.mjs +105 -21
  67. package/api/integration/authoring-checks.mjs +108 -31
  68. package/api/integration/authoring-checks.test.mjs +171 -6
  69. package/api/integration/authoring-checks.type.d.mts +3 -1
  70. package/api/integration/authoring-checks.type.mjs +3 -1
  71. package/api/integration/integration-authoring.type.d.mts +3 -1
  72. package/api/integration/integration-authoring.type.mjs +2 -0
  73. package/api/integration/integration-block-exports.test.mjs +10 -6
  74. package/api/integration/integrationAdd.doc.mjs +14 -4
  75. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  76. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  77. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  78. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  79. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  80. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  81. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  82. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  83. package/api/integration/integrationPackCheck.doc.mjs +2 -1
  84. package/api/integration/integrationTemplateConflicts.doc.mjs +7 -5
  85. package/api/integration/pack-check.mjs +83 -7
  86. package/api/integration/pack-check.test.mjs +387 -47
  87. package/api/integration/pack-check.type.d.mts +26 -2
  88. package/api/integration/pack-check.type.mjs +14 -1
  89. package/api/integration/summarizeIssues.doc.mjs +1 -0
  90. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  91. package/api/integration/validate-integration.mjs +52 -102
  92. package/api/integration/validate-integration.test.mjs +179 -26
  93. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  94. package/api/integration/validateIntegration.doc.mjs +3 -2
  95. package/api/json/assertResponse.doc.mjs +1 -0
  96. package/api/json/envelope-types.test.mjs +76 -0
  97. package/api/json/index.ts +2 -0
  98. package/api/json/isError.doc.mjs +1 -0
  99. package/api/json/parseResponse.doc.mjs +3 -2
  100. package/api/layout/_adapter.mjs +20 -5
  101. package/api/layout/expand/expand.mjs +7 -5
  102. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  103. package/api/layout/grammar/grammar.mjs +2 -1
  104. package/api/layout/layoutCheck.doc.mjs +1 -0
  105. package/api/layout/layoutExpand.doc.mjs +2 -1
  106. package/api/layout/layoutGrammar.doc.mjs +1 -0
  107. package/api/search/search-return-type.test.mjs +54 -0
  108. package/api/search/search.d.mts +29 -11
  109. package/api/search/search.doc.mjs +8 -2
  110. package/api/search/search.mjs +337 -41
  111. package/api/search/search.test.mjs +124 -1
  112. package/api/search/search.type.d.mts +15 -3
  113. package/api/search/search.type.mjs +5 -2
  114. package/api/swizzle/copy/copy.mjs +28 -11
  115. package/api/swizzle/swizzle.doc.mjs +2 -1
  116. package/api/swizzle/swizzle.type.d.mts +2 -2
  117. package/api/swizzle/swizzle.type.mjs +2 -2
  118. package/api/template/copy/copy.mjs +17 -23
  119. package/api/template/copy/copy.test.mjs +17 -0
  120. package/api/template/list/list.mjs +1 -0
  121. package/api/template/template-integration.test.mjs +1022 -3
  122. package/api/template/template-suffix.test.mjs +41 -21
  123. package/api/template/template.d.mts +1 -1
  124. package/api/template/template.doc.mjs +30 -8
  125. package/api/template/template.mjs +45 -8
  126. package/api/template/template.type.d.mts +12 -14
  127. package/api/template/template.type.mjs +15 -14
  128. package/api/theme/_adapter.d.mts +2 -3
  129. package/api/theme/_adapter.mjs +4 -5
  130. package/api/theme/add/add.binary.test.mjs +84 -0
  131. package/api/theme/add/add.mjs +20 -3
  132. package/api/theme/add/add.staging.test.mjs +66 -0
  133. package/api/theme/add/add.test.mjs +14 -1
  134. package/api/theme/build/build.mjs +133 -42
  135. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  136. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  137. package/api/theme/build/build.test.mjs +127 -0
  138. package/api/theme/build/font-warning.mjs +3 -3
  139. package/api/theme/build/font-warning.test.mjs +5 -2
  140. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  141. package/api/theme/integration-themes.test.mjs +39 -28
  142. package/api/theme/list/list.test.mjs +19 -20
  143. package/api/theme/listThemes.doc.mjs +6 -5
  144. package/api/theme/palette/generate/generate.mjs +8 -3
  145. package/api/theme/palette/generate/generate.test.mjs +96 -0
  146. package/api/theme/palette/generate/generator.d.mts +10 -13
  147. package/api/theme/palette/generate/generator.mjs +15 -4
  148. package/api/theme/palette/generate/generator.test.mjs +10 -0
  149. package/api/theme/template/template.mjs +11 -2
  150. package/api/theme/template/template.test.mjs +20 -0
  151. package/api/theme/theme.type.d.mts +170 -11
  152. package/api/theme/theme.type.mjs +94 -27
  153. package/api/theme/themeAdd.doc.mjs +4 -3
  154. package/api/theme/themeBuild.doc.mjs +8 -4
  155. package/api/theme/themeList.doc.mjs +6 -3
  156. package/api/theme/themeListAvailable.doc.mjs +5 -3
  157. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  158. package/api/theme/themeTargets.doc.mjs +1 -0
  159. package/api/theme/themeTemplate.doc.mjs +6 -2
  160. package/api/upgrade/_adapter.d.mts +32 -5
  161. package/api/upgrade/_adapter.mjs +139 -22
  162. package/api/upgrade/list/list.mjs +2 -1
  163. package/api/upgrade/list/list.test.mjs +73 -0
  164. package/api/upgrade/project-context.test.mjs +272 -0
  165. package/api/upgrade/provider-agreement.test.mjs +152 -0
  166. package/api/upgrade/run/run.mjs +356 -59
  167. package/api/upgrade/status/status.mjs +2 -2
  168. package/api/upgrade/upgrade.doc.mjs +12 -5
  169. package/api/upgrade/upgrade.type.d.mts +43 -5
  170. package/api/upgrade/upgrade.type.mjs +27 -11
  171. package/assets/codemods/__tests__/runner.test.mjs +330 -8
  172. package/assets/codemods/integration-discovery.mjs +48 -4
  173. package/assets/codemods/integration-discovery.test.mjs +73 -0
  174. package/assets/codemods/integration-runner.mjs +56 -4
  175. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  176. package/assets/codemods/run-codemod.mjs +177 -34
  177. package/assets/codemods/runner.mjs +350 -102
  178. package/assets/codemods/term-log.mjs +32 -8
  179. package/assets/codemods/term-log.test.mjs +19 -1
  180. package/assets/codemods/transform-prop.mjs +109 -0
  181. package/assets/codemods/transform-prop.test.mjs +95 -0
  182. package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  183. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  184. package/assets/codemods/transforms/next/index.mjs +19 -1
  185. package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
  186. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  187. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  188. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  189. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  190. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  191. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  192. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  193. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  194. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  195. package/assets/docs/README.md +9 -0
  196. package/assets/docs/authoring.doc.mjs +14 -0
  197. package/assets/docs/getting-started.doc.mjs +2 -2
  198. package/assets/docs/principles.doc.mjs +6 -6
  199. package/assets/docs/styling-libraries.doc.mjs +3 -3
  200. package/assets/docs/styling.doc.mjs +4 -4
  201. package/assets/docs/theme.doc.mjs +4 -4
  202. package/assets/docs/tokens.doc.mjs +1 -1
  203. package/assets/docs/tree/api.doc.mjs +30 -0
  204. package/assets/docs/tree/cli.doc.mjs +23 -0
  205. package/assets/docs/tree/commands.doc.mjs +25 -0
  206. package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +124 -25
  207. package/assets/docs/tree/integrations.test.mjs +62 -0
  208. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  209. package/assets/docs/working-with-ai.doc.mjs +1 -1
  210. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  211. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  212. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  213. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  214. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  215. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  216. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  217. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  218. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  219. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  220. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  221. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  222. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  223. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  224. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  225. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  226. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  227. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  228. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  229. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  230. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  231. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  232. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  233. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  234. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  235. package/authoring/_shared/contract.ts +22 -0
  236. package/authoring/codemod/codemod.doc.mjs +7 -2
  237. package/authoring/codemod/parse.d.mts +8 -8
  238. package/authoring/codemod/parse.mjs +8 -6
  239. package/authoring/codemod/type.ts +12 -0
  240. package/authoring/config/config.doc.mjs +2 -2
  241. package/authoring/config/debug-composition.test.mjs +92 -0
  242. package/authoring/config/parse.d.mts +13 -13
  243. package/authoring/config/parse.mjs +8 -8
  244. package/authoring/config/type.ts +18 -6
  245. package/authoring/debug/debug.doc.d.mts +11 -0
  246. package/authoring/debug/debug.doc.mjs +182 -0
  247. package/authoring/debug/parse.d.mts +8 -8
  248. package/authoring/debug/parse.mjs +3 -3
  249. package/authoring/doctypes/_schema.d.mts +718 -23
  250. package/authoring/doctypes/_schema.mjs +519 -39
  251. package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
  252. package/authoring/doctypes/base/graph-fields.doc.mjs +64 -0
  253. package/authoring/doctypes/base/type.ts +41 -0
  254. package/authoring/doctypes/command/command.doc.mjs +4 -3
  255. package/authoring/doctypes/command/parse.d.mts +2 -2
  256. package/authoring/doctypes/command/parse.mjs +1 -1
  257. package/authoring/doctypes/command/type.ts +5 -4
  258. package/authoring/doctypes/component/component.doc.mjs +6 -3
  259. package/authoring/doctypes/component/parse.d.mts +2 -2
  260. package/authoring/doctypes/component/parse.mjs +1 -1
  261. package/authoring/doctypes/component/type.ts +6 -5
  262. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  263. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  264. package/authoring/doctypes/enum/parse.d.mts +2 -2
  265. package/authoring/doctypes/enum/parse.mjs +1 -1
  266. package/authoring/doctypes/enum/type.ts +4 -2
  267. package/authoring/doctypes/function/function.doc.mjs +7 -2
  268. package/authoring/doctypes/function/parse.d.mts +2 -2
  269. package/authoring/doctypes/function/parse.mjs +1 -1
  270. package/authoring/doctypes/function/type.ts +9 -4
  271. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  272. package/authoring/doctypes/hook/parse.d.mts +2 -2
  273. package/authoring/doctypes/hook/parse.mjs +1 -1
  274. package/authoring/doctypes/hook/type.ts +5 -4
  275. package/authoring/doctypes/legacy.d.mts +8 -6
  276. package/authoring/doctypes/legacy.mjs +5 -4
  277. package/authoring/doctypes/load-contract.test.mjs +208 -0
  278. package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
  279. package/authoring/doctypes/namespace/namespace.doc.mjs +128 -0
  280. package/authoring/doctypes/namespace/parse.d.mts +12 -0
  281. package/authoring/doctypes/namespace/parse.mjs +25 -0
  282. package/authoring/doctypes/namespace/parse.test.mjs +163 -0
  283. package/authoring/doctypes/namespace/type.ts +74 -0
  284. package/authoring/doctypes/parse.d.mts +22 -18
  285. package/authoring/doctypes/parse.mjs +22 -11
  286. package/authoring/doctypes/parse.test.mjs +77 -3
  287. package/authoring/doctypes/reference/parse.d.mts +2 -2
  288. package/authoring/doctypes/reference/parse.mjs +8 -5
  289. package/authoring/doctypes/reference/reference.doc.mjs +20 -5
  290. package/authoring/doctypes/reference/type.ts +53 -5
  291. package/authoring/doctypes/schema/parse.d.mts +2 -2
  292. package/authoring/doctypes/schema/parse.mjs +1 -1
  293. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  294. package/authoring/doctypes/schema/type.ts +4 -4
  295. package/authoring/doctypes/template/parse.d.mts +94 -1
  296. package/authoring/doctypes/template/parse.mjs +40 -2
  297. package/authoring/doctypes/template/parse.test.mjs +26 -2
  298. package/authoring/doctypes/template/template.doc.mjs +13 -3
  299. package/authoring/doctypes/template/type.ts +13 -2
  300. package/authoring/doctypes/theme/parse.d.mts +35 -0
  301. package/authoring/doctypes/theme/parse.mjs +76 -0
  302. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  303. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  304. package/authoring/doctypes/theme/type.ts +42 -0
  305. package/authoring/doctypes/types.ts +12 -10
  306. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  307. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  308. package/authoring/gap-report/parse.d.mts +10 -10
  309. package/authoring/gap-report/parse.mjs +6 -6
  310. package/authoring/gap-report/type.ts +1 -1
  311. package/authoring/identity/identity.doc.d.mts +9 -0
  312. package/authoring/identity/identity.doc.mjs +61 -0
  313. package/authoring/identity/type.ts +132 -0
  314. package/authoring/index.d.mts +2 -0
  315. package/authoring/index.d.ts +52 -17
  316. package/authoring/index.mjs +3 -1
  317. package/authoring/integration/integration.doc.mjs +15 -8
  318. package/authoring/integration/parse.d.mts +2 -2
  319. package/authoring/integration/parse.mjs +1 -1
  320. package/authoring/integration/parse.test.mjs +10 -1
  321. package/authoring/integration/schema.d.mts +6 -4
  322. package/authoring/integration/schema.mjs +9 -3
  323. package/authoring/integration/type.ts +19 -8
  324. package/authoring/shadcn/receipt.d.mts +6 -6
  325. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  326. package/clients/cli/command-load-failure.test.mjs +83 -0
  327. package/clients/cli/commands/blog.doc.mjs +1 -1
  328. package/clients/cli/commands/blog.mjs +23 -8
  329. package/clients/cli/commands/blog.test.mjs +42 -1
  330. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  331. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  332. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  333. package/clients/cli/commands/build-theme.mjs +16 -50
  334. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  335. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  336. package/clients/cli/commands/build.doc.mjs +5 -2
  337. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  338. package/clients/cli/commands/build.mjs +37 -49
  339. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  340. package/clients/cli/commands/build.text-fields.test.mjs +40 -0
  341. package/clients/cli/commands/component/index.mjs +3 -8
  342. package/clients/cli/commands/component-ownership.test.mjs +3 -3
  343. package/clients/cli/commands/component-package.test.mjs +46 -0
  344. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  345. package/clients/cli/commands/component.doc.mjs +1 -1
  346. package/clients/cli/commands/component.test.mjs +19 -0
  347. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  348. package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
  349. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  350. package/clients/cli/commands/discover.doc.mjs +5 -3
  351. package/clients/cli/commands/discover.mjs +4 -4
  352. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  353. package/clients/cli/commands/docs.doc.mjs +28 -6
  354. package/clients/cli/commands/docs.mjs +238 -24
  355. package/clients/cli/commands/docs.test.mjs +193 -1
  356. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  357. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
  358. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  359. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  360. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  361. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  362. package/clients/cli/commands/doctor-integration.test.mjs +83 -8
  363. package/clients/cli/commands/doctor.doc.mjs +1 -1
  364. package/clients/cli/commands/doctor.mjs +30 -25
  365. package/clients/cli/commands/doctor.test.mjs +42 -0
  366. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  367. package/clients/cli/commands/gap-report.test.mjs +72 -0
  368. package/clients/cli/commands/hook/index.mjs +7 -17
  369. package/clients/cli/commands/hook.doc.mjs +1 -1
  370. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  371. package/clients/cli/commands/init.doc.mjs +20 -9
  372. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  373. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  374. package/clients/cli/commands/integration-add.doc.mjs +32 -6
  375. package/clients/cli/commands/integration-authoring.test.mjs +13 -9
  376. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  377. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  378. package/clients/cli/commands/integration.doc.mjs +1 -1
  379. package/clients/cli/commands/integration.mjs +1 -0
  380. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  381. package/clients/cli/commands/json-contract.test.mjs +33 -0
  382. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  383. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  384. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  385. package/clients/cli/commands/layout.doc.mjs +3 -3
  386. package/clients/cli/commands/layout.mjs +21 -9
  387. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  388. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  389. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  390. package/clients/cli/commands/manifest.doc.mjs +1 -1
  391. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  392. package/clients/cli/commands/search.doc.mjs +7 -4
  393. package/clients/cli/commands/search.mjs +28 -9
  394. package/clients/cli/commands/search.test.mjs +75 -0
  395. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  396. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  397. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  398. package/clients/cli/commands/template.doc.mjs +52 -13
  399. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  400. package/clients/cli/commands/template.mjs +4 -91
  401. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  402. package/clients/cli/commands/text-json-parity.test.mjs +719 -0
  403. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  404. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  405. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  406. package/clients/cli/commands/theme-palette-generate.doc.mjs +9 -5
  407. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  408. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  409. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  410. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  411. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  412. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  413. package/clients/cli/commands/theme.doc.mjs +1 -1
  414. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  415. package/clients/cli/commands/upgrade.doc.mjs +22 -10
  416. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  417. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  418. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  419. package/clients/cli/commands/upgrade.mjs +29 -7
  420. package/clients/cli/formatters/index.mjs +164 -1
  421. package/clients/cli/formatters/index.test.mjs +97 -0
  422. package/clients/cli/index.mjs +21 -30
  423. package/clients/cli/latest-version-env.test.mjs +50 -0
  424. package/clients/cli/lib/cli-error.test.mjs +7 -0
  425. package/clients/cli/lib/component-format.mjs +9 -9
  426. package/clients/cli/lib/component-format.test.mjs +1 -1
  427. package/clients/cli/lib/define-command.mjs +32 -6
  428. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  429. package/clients/cli/lib/exit-codes.test.mjs +97 -0
  430. package/clients/cli/lib/hook-format.mjs +19 -10
  431. package/clients/cli/lib/json-shim.mjs +38 -2
  432. package/clients/cli/lib/json-shim.test.mjs +83 -0
  433. package/clients/cli/lib/manifest.d.ts +2 -0
  434. package/clients/cli/lib/manifest.mjs +36 -2
  435. package/clients/cli/lib/manifest.test.mjs +17 -0
  436. package/foundation/agent-docs/agent-docs.d.mts +4 -0
  437. package/foundation/agent-docs/agent-docs.mjs +70 -3
  438. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  439. package/foundation/agent-docs/agent-docs.test.mjs +10 -1
  440. package/foundation/config/integration-debug.test.mjs +28 -3
  441. package/foundation/config/project-themes.test.mjs +11 -19
  442. package/foundation/config/project.d.mts +20 -11
  443. package/foundation/config/project.mjs +263 -91
  444. package/foundation/config/project.test.mjs +270 -21
  445. package/foundation/discovery/authoring-self-docs.d.mts +75 -0
  446. package/foundation/discovery/authoring-self-docs.mjs +224 -0
  447. package/foundation/discovery/authoring-self-docs.test.mjs +165 -0
  448. package/foundation/discovery/authoring-surface.d.mts +74 -0
  449. package/foundation/discovery/authoring-surface.mjs +525 -0
  450. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  451. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  452. package/foundation/discovery/cli-self-docs.mjs +490 -0
  453. package/foundation/discovery/cli-self-docs.test.mjs +375 -0
  454. package/foundation/discovery/component-discovery.d.mts +39 -1
  455. package/foundation/discovery/component-discovery.mjs +50 -1
  456. package/foundation/discovery/component-loader.d.mts +35 -38
  457. package/foundation/discovery/component-loader.mjs +53 -222
  458. package/foundation/discovery/docs-discovery.d.mts +116 -11
  459. package/foundation/discovery/docs-discovery.mjs +389 -108
  460. package/foundation/discovery/docs-discovery.test.mjs +325 -20
  461. package/foundation/discovery/docs-output-budget.d.mts +28 -0
  462. package/foundation/discovery/docs-output-budget.mjs +50 -0
  463. package/foundation/discovery/docs-section-key.d.mts +116 -0
  464. package/foundation/discovery/docs-section-key.mjs +322 -0
  465. package/foundation/discovery/docs-section-key.test.mjs +246 -0
  466. package/foundation/discovery/template-adapter.d.mts +113 -11
  467. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  468. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  469. package/foundation/discovery/template-adapter.mjs +774 -83
  470. package/foundation/discovery/template-adapter.test.mjs +57 -0
  471. package/foundation/discovery/theme-discovery.d.mts +67 -7
  472. package/foundation/discovery/theme-discovery.mjs +916 -186
  473. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  474. package/foundation/discovery/theming-targets.test.mjs +4 -0
  475. package/foundation/doc-compiler/bundle.d.mts +47 -0
  476. package/foundation/doc-compiler/bundle.mjs +278 -0
  477. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  478. package/foundation/doc-compiler/compile.d.mts +343 -0
  479. package/foundation/doc-compiler/compile.mjs +558 -0
  480. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  481. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  482. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  483. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  484. package/foundation/doc-compiler/import.d.mts +24 -0
  485. package/foundation/doc-compiler/import.mjs +59 -0
  486. package/foundation/doc-compiler/inputs.d.mts +102 -0
  487. package/foundation/doc-compiler/inputs.mjs +291 -0
  488. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  489. package/foundation/doc-compiler/ir.d.mts +22 -0
  490. package/foundation/doc-compiler/ir.mjs +471 -0
  491. package/foundation/doc-compiler/lenses.d.mts +34 -0
  492. package/foundation/doc-compiler/lenses.mjs +128 -0
  493. package/foundation/doc-compiler/links.d.mts +135 -0
  494. package/foundation/doc-compiler/links.mjs +253 -0
  495. package/foundation/doc-compiler/links.test.mjs +139 -0
  496. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  497. package/foundation/doc-compiler/overlays.d.mts +37 -0
  498. package/foundation/doc-compiler/overlays.mjs +206 -0
  499. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  500. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  501. package/foundation/doc-compiler/read.d.mts +127 -0
  502. package/foundation/doc-compiler/read.mjs +325 -0
  503. package/foundation/doc-compiler/read.test.mjs +313 -0
  504. package/foundation/doc-compiler/source.d.mts +33 -0
  505. package/foundation/doc-compiler/source.mjs +128 -0
  506. package/foundation/doc-compiler/tree.d.mts +288 -0
  507. package/foundation/doc-compiler/tree.mjs +876 -0
  508. package/foundation/doc-compiler/tree.test.mjs +598 -0
  509. package/foundation/fs/file-protection.d.mts +33 -0
  510. package/foundation/fs/file-protection.mjs +825 -0
  511. package/foundation/fs/file-protection.test.mjs +250 -0
  512. package/foundation/fs/module-loader.d.mts +1 -0
  513. package/foundation/fs/module-loader.mjs +50 -1
  514. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  515. package/foundation/fs/path-safety.d.mts +3 -2
  516. package/foundation/fs/path-safety.mjs +49 -19
  517. package/foundation/fs/path-safety.test.mjs +50 -0
  518. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  519. package/foundation/identity/provider-identity.d.mts +90 -0
  520. package/foundation/identity/provider-identity.mjs +320 -0
  521. package/foundation/identity/provider-identity.test.mjs +254 -0
  522. package/foundation/identity/providers.d.mts +7 -0
  523. package/foundation/identity/providers.mjs +16 -0
  524. package/foundation/integrations/autolink.d.mts +58 -1
  525. package/foundation/integrations/autolink.mjs +143 -45
  526. package/foundation/integrations/autolink.test.mjs +1 -1
  527. package/foundation/integrations/cli-requirement.d.mts +45 -0
  528. package/foundation/integrations/cli-requirement.mjs +154 -0
  529. package/foundation/integrations/cli-requirement.test.mjs +109 -0
  530. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  531. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  532. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  533. package/foundation/integrations/contribution-inventory.mjs +27 -24
  534. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  535. package/foundation/integrations/integration-warnings.d.mts +9 -2
  536. package/foundation/integrations/integration-warnings.mjs +52 -21
  537. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  538. package/foundation/integrations/integrations.d.mts +49 -2
  539. package/foundation/integrations/integrations.mjs +81 -8
  540. package/foundation/integrations/integrations.test.mjs +384 -1
  541. package/foundation/integrations/provider-conflicts.test.mjs +125 -0
  542. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  543. package/foundation/integrations/provider-resolution.d.mts +152 -0
  544. package/foundation/integrations/provider-resolution.mjs +576 -0
  545. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  546. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  547. package/foundation/integrations/theme-descriptor.mjs +44 -0
  548. package/foundation/integrations/validate-contributions.d.mts +2 -0
  549. package/foundation/integrations/validate-contributions.mjs +131 -29
  550. package/foundation/response/base.d.ts +8 -4
  551. package/foundation/response/error-codes.d.mts +3 -1
  552. package/foundation/response/error-codes.d.ts +2 -0
  553. package/foundation/response/error-codes.doc.mjs +13 -4
  554. package/foundation/response/error-codes.mjs +8 -2
  555. package/foundation/response/error-codes.test.mjs +137 -10
  556. package/foundation/response/json-contract.test.mjs +57 -17
  557. package/foundation/response/json.d.mts +4 -2
  558. package/foundation/response/json.mjs +8 -10
  559. package/foundation/response/response-types.doc.mjs +26 -16
  560. package/foundation/response/response-types.doc.test.mjs +158 -0
  561. package/foundation/response/response.doc.mjs +1 -1
  562. package/foundation/text/string-utils.mjs +22 -10
  563. package/foundation/xle/expand.d.mts +2 -0
  564. package/foundation/xle/expand.mjs +4 -3
  565. package/foundation/xle/expand.test.mjs +54 -0
  566. package/foundation/xle/xle.test.mjs +13 -0
  567. package/package.json +10 -11
  568. package/assets/templates/themes/manifest.json +0 -95
  569. package/clients/cli/lib/update-check.mjs +0 -83
  570. package/clients/cli/lib/update-check.test.mjs +0 -137
  571. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -0,0 +1,109 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * Find imported components, resolve their local JSX names (including aliases),
5
+ * and yield matching JSX prop paths to a visitor.
6
+ *
7
+ * This helper intentionally stops at the JSX boundary. It does not follow
8
+ * variables, helper calls, object spreads, wrapper components, or types.
9
+ *
10
+ * @param {any} root jscodeshift collection for one source file
11
+ * @param {any} j configured jscodeshift instance
12
+ * @param {{
13
+ * matchesImport: (source: string) => boolean,
14
+ * components: ReadonlyMap<string, ReadonlySet<string>>,
15
+ * normalizeComponentName?: (name: string) => string,
16
+ * }} options
17
+ * @param {(propPath: any, context: {component: string, localName: string}) => void} visit
18
+ */
19
+ export function transformProp(root, j, options, visit) {
20
+ const normalize = options.normalizeComponentName ?? (name => name);
21
+ /** @type {Map<string, {component: string, props: ReadonlySet<string>}>} */
22
+ const directBindings = new Map();
23
+ /** @type {Set<string>} */
24
+ const namespaceBindings = new Set();
25
+
26
+ root.find(j.ImportDeclaration).forEach((/** @type {any} */ importPath) => {
27
+ const source = importPath.node.source.value;
28
+ if (
29
+ importPath.node.importKind === 'type' ||
30
+ typeof source !== 'string' ||
31
+ !options.matchesImport(source)
32
+ ) {
33
+ return;
34
+ }
35
+
36
+ const subpathName = normalize(source.split('/').at(-1) ?? '');
37
+ const subpathProps = options.components.get(subpathName);
38
+
39
+ for (const specifier of importPath.node.specifiers ?? []) {
40
+ if (specifier.importKind === 'type') continue;
41
+
42
+ if (specifier.type === 'ImportSpecifier') {
43
+ const importedName =
44
+ specifier.imported?.name ?? specifier.imported?.value;
45
+ if (typeof importedName !== 'string') continue;
46
+ const component = normalize(importedName);
47
+ const props = options.components.get(component);
48
+ if (!props) continue;
49
+ directBindings.set(specifier.local?.name ?? importedName, {
50
+ component,
51
+ props,
52
+ });
53
+ } else if (specifier.type === 'ImportDefaultSpecifier' && subpathProps) {
54
+ directBindings.set(specifier.local.name, {
55
+ component: subpathName,
56
+ props: subpathProps,
57
+ });
58
+ } else if (specifier.type === 'ImportNamespaceSpecifier') {
59
+ namespaceBindings.add(specifier.local.name);
60
+ }
61
+ }
62
+ });
63
+
64
+ if (directBindings.size === 0 && namespaceBindings.size === 0) return;
65
+
66
+ root.find(j.JSXOpeningElement).forEach((/** @type {any} */ jsxPath) => {
67
+ const name = jsxPath.node.name;
68
+ let localName;
69
+ let component;
70
+ let props;
71
+
72
+ if (name.type === 'JSXIdentifier') {
73
+ localName = name.name;
74
+ const binding = directBindings.get(localName);
75
+ if (!binding) return;
76
+ ({component, props} = binding);
77
+ } else if (
78
+ name.type === 'JSXMemberExpression' &&
79
+ name.object?.type === 'JSXIdentifier' &&
80
+ name.property?.type === 'JSXIdentifier' &&
81
+ namespaceBindings.has(name.object.name)
82
+ ) {
83
+ localName = name.object.name;
84
+ component = normalize(name.property.name);
85
+ props = options.components.get(component);
86
+ if (!props) return;
87
+ } else {
88
+ return;
89
+ }
90
+
91
+ // A parameter or local declaration with the imported name shadows the
92
+ // module binding. Only JSX tags whose root binding resolves to Program are
93
+ // considered usages of the import discovered above.
94
+ const bindingScope = jsxPath.scope.lookup(localName);
95
+ if (!bindingScope || bindingScope.path.node.type !== 'Program') return;
96
+
97
+ for (let index = 0; index < jsxPath.node.attributes.length; index++) {
98
+ const attribute = jsxPath.node.attributes[index];
99
+ if (
100
+ attribute.type !== 'JSXAttribute' ||
101
+ attribute.name?.type !== 'JSXIdentifier' ||
102
+ !props.has(attribute.name.name)
103
+ ) {
104
+ continue;
105
+ }
106
+ visit(jsxPath.get('attributes', index), {component, localName});
107
+ }
108
+ });
109
+ }
@@ -0,0 +1,95 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ import {describe, expect, it} from 'vitest';
4
+ import jscodeshift from 'jscodeshift';
5
+ import {transformProp} from './transform-prop.mjs';
6
+
7
+ const j = jscodeshift.withParser('tsx');
8
+ const components = new Map([
9
+ ['Widget', new Set(['tone'])],
10
+ ['Group', new Set(['size'])],
11
+ ]);
12
+
13
+ function apply(source) {
14
+ const root = j(source);
15
+ transformProp(
16
+ root,
17
+ j,
18
+ {
19
+ matchesImport: value => /^@example\/core(?:\/|$)/.test(value),
20
+ components,
21
+ normalizeComponentName: name =>
22
+ name.startsWith('XDS') ? name.slice(3) : name,
23
+ },
24
+ propPath => {
25
+ propPath.node.name.name = `migrated${propPath.node.name.name}`;
26
+ },
27
+ );
28
+ return root.toSource({quote: 'single'});
29
+ }
30
+
31
+ describe('transformProp', () => {
32
+ it('maps named import aliases to their JSX usages', () => {
33
+ const output = apply(`import {Widget as Card} from '@example/core';
34
+ const view = <Card tone="old" other="old" />;`);
35
+
36
+ expect(output).toContain('<Card migratedtone="old" other="old"');
37
+ });
38
+
39
+ it('maps default subpath imports', () => {
40
+ const output = apply(`import Card from '@example/core/Widget';
41
+ const view = <Card tone="old" />;`);
42
+
43
+ expect(output).toContain('<Card migratedtone="old"');
44
+ });
45
+
46
+ it('ignores declaration-level type imports', () => {
47
+ const output = apply(`import type {Widget} from '@example/core';
48
+ const Widget = props => <div {...props} />;
49
+ const view = <Widget tone="old" />;`);
50
+
51
+ expect(output).toContain('<Widget tone="old"');
52
+ expect(output).not.toContain('migratedtone');
53
+ });
54
+
55
+ it('ignores type specifiers in mixed imports', () => {
56
+ const output = apply(`import {type Widget, Group} from '@example/core';
57
+ const Widget = props => <div {...props} />;
58
+ const view = <><Widget tone="old" /><Group size="old" /></>;`);
59
+
60
+ expect(output).toContain('<Widget tone="old"');
61
+ expect(output).toContain('<Group migratedsize="old"');
62
+ expect(output).not.toContain('<Widget migratedtone');
63
+ });
64
+
65
+ it('maps namespace imports', () => {
66
+ const output = apply(`import * as Core from '@example/core';
67
+ const view = <Core.Group size="old" />;`);
68
+
69
+ expect(output).toContain('<Core.Group migratedsize="old"');
70
+ });
71
+
72
+ it('ignores same-named imports from other packages', () => {
73
+ const source = `import {Widget} from '@other/core';
74
+ const view = <Widget tone="old" />;`;
75
+ expect(apply(source)).toBe(source);
76
+ });
77
+
78
+ it('ignores a local binding that shadows an imported alias', () => {
79
+ const output = apply(`import {Widget as Card} from '@example/core';
80
+ const migrated = <Card tone="old" />;
81
+ function Local(Card) { return <Card tone="local" />; }`);
82
+
83
+ expect(output).toContain('<Card migratedtone="old"');
84
+ expect(output).toContain('<Card tone="local"');
85
+ });
86
+
87
+ it('yields only configured props on configured components', () => {
88
+ const output = apply(`import {Widget, Group} from '@example/core';
89
+ const a = <Widget size="old" tone="old" />;
90
+ const b = <Group tone="old" size="old" />;`);
91
+
92
+ expect(output).toContain('<Widget size="old" migratedtone="old"');
93
+ expect(output).toContain('<Group tone="old" migratedsize="old"');
94
+ });
95
+ });
@@ -0,0 +1,63 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ import {describe, expect, it} from 'vitest';
4
+ import transform from '../migrate-native-picker-to-presentation.mjs';
5
+
6
+ async function applyTransform(source) {
7
+ const jscodeshift = (await import('jscodeshift')).default;
8
+ const j = jscodeshift.withParser('tsx');
9
+ const api = {jscodeshift: j, stats: () => {}, report: () => {}};
10
+ return transform({source, path: 'test.tsx'}, api) ?? source;
11
+ }
12
+
13
+ describe('migrate-native-picker-to-presentation', () => {
14
+ it('maps DateInput and DateTimeInput values (FR3)', async () => {
15
+ const output =
16
+ await applyTransform(`import {DateInput, DateTimeInput} from '@astryxdesign/core';
17
+ const a = <DateInput label="d" nativePicker="touch" />;
18
+ const b = <DateInput label="d" nativePicker="always" />;
19
+ const c = <DateTimeInput label="dt" nativePicker="never" />;`);
20
+
21
+ expect(output).toContain("presentation='adaptive-native'");
22
+ expect(output).toContain("presentation='native'");
23
+ expect(output).toContain("presentation='adaptive-bottom-sheet'");
24
+ expect(output).not.toContain('nativePicker');
25
+ });
26
+
27
+ it('maps TimeInput never to text-input (FR3)', async () => {
28
+ const output =
29
+ await applyTransform(`import {TimeInput} from '@astryxdesign/core';
30
+ const a = <TimeInput label="t" nativePicker="never" />;
31
+ const b = <TimeInput label="t" nativePicker={'touch'} />;`);
32
+
33
+ expect(output).toContain("presentation='text-input'");
34
+ expect(output).toContain("presentation={'adaptive-native'}");
35
+ });
36
+
37
+ it('drops nativePicker when presentation is already set (FR4)', async () => {
38
+ const output =
39
+ await applyTransform(`import {DateInput} from '@astryxdesign/core';
40
+ const a = <DateInput label="d" presentation="popover" nativePicker="always" />;`);
41
+
42
+ expect(output).toContain('presentation="popover"');
43
+ expect(output).not.toContain('nativePicker');
44
+ });
45
+
46
+ it('leaves dynamic values and unrelated components unchanged', async () => {
47
+ const source = `import {DateInput, Selector} from '@astryxdesign/core';
48
+ const a = <DateInput label="d" nativePicker={mode} />;
49
+ const b = <Selector nativePicker="never" />;`;
50
+ expect(await applyTransform(source)).toBe(source);
51
+ });
52
+
53
+ it('leaves a mixed static/dynamic conditional byte-identical when a sibling migrates', async () => {
54
+ const output =
55
+ await applyTransform(`import {TimeInput} from '@astryxdesign/core';
56
+ const a = <TimeInput label="t" nativePicker="touch" />;
57
+ const b = <TimeInput label="t" nativePicker={flag ? 'always' : mode} />;`);
58
+
59
+ expect(output).toContain("presentation='adaptive-native'");
60
+ expect(output).toContain("nativePicker={flag ? 'always' : mode}");
61
+ expect(output).not.toContain("'native'");
62
+ });
63
+ });
@@ -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
+ }