@astryxdesign/cli 0.1.7 → 0.1.8-canary.07362a9

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 (389) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +115 -19
  3. package/{src/api → api/blog}/blog.mjs +42 -6
  4. package/{src/api → api/blog}/blog.test.mjs +2 -2
  5. package/api/build/build.mjs +92 -0
  6. package/api/build/build.test.mjs +92 -0
  7. package/{src/api → api/component}/component.mjs +49 -26
  8. package/{src/api → api/discover}/discover.mjs +55 -18
  9. package/{src/api → api/docs}/docs.mjs +47 -21
  10. package/{src/api → api/doctor}/doctor.mjs +13 -10
  11. package/{src/api → api}/error.mjs +2 -2
  12. package/{src/api → api/hook}/hook.mjs +11 -11
  13. package/{src/api → api}/index.mjs +16 -9
  14. package/{src/api → api/integration}/validate-integration.mjs +48 -15
  15. package/{src/api → api/integration}/validate-integration.test.mjs +1 -1
  16. package/{src/api → api/layout}/layout.mjs +66 -17
  17. package/{src/api → api/layout}/layout.test.mjs +1 -1
  18. package/{src/api → api/search}/search.mjs +71 -12
  19. package/api/swizzle/swizzle.mjs +283 -0
  20. package/{src/commands → api/swizzle}/swizzle.test.mjs +26 -1
  21. package/{src/api → api/template}/template-integration.test.mjs +2 -2
  22. package/{src/api → api/template}/template-suffix.test.mjs +3 -3
  23. package/{src/api → api/template}/template.mjs +96 -19
  24. package/{src/api → api/theme}/theme-add.mjs +35 -7
  25. package/{src → authoring}/codemod.mjs +6 -6
  26. package/{src → authoring}/config.test.mjs +1 -1
  27. package/{src → authoring}/doc.mjs +1 -1
  28. package/{src → authoring}/doc.test.mjs +1 -1
  29. package/{src → authoring}/template.mjs +1 -1
  30. package/bin/astryx.mjs +12 -10
  31. package/{src → cli}/commands/blog.mjs +48 -7
  32. package/{src → cli}/commands/build-theme.mjs +133 -115
  33. package/cli/commands/build.mjs +172 -0
  34. package/cli/commands/cli-postinstall.test.mjs +42 -0
  35. package/{src → cli}/commands/component/index.mjs +52 -25
  36. package/{src → cli}/commands/component-ownership.test.mjs +3 -3
  37. package/{src → cli}/commands/component-package.test.mjs +1 -1
  38. package/{src → cli}/commands/component-resolution.test.mjs +2 -2
  39. package/{src → cli}/commands/discover.mjs +23 -12
  40. package/{src → cli}/commands/docs.mjs +42 -10
  41. package/{src → cli}/commands/docs.test.mjs +1 -1
  42. package/{src → cli}/commands/doctor.mjs +3 -3
  43. package/{src → cli}/commands/doctor.test.mjs +2 -2
  44. package/{src → cli}/commands/ensure-core-built.mjs +3 -2
  45. package/{src → cli}/commands/external-showcase.test.mjs +1 -1
  46. package/{src → cli}/commands/hook/index.mjs +40 -17
  47. package/{src → cli}/commands/import-hint-correctness.test.mjs +1 -1
  48. package/cli/commands/init.mjs +195 -0
  49. package/{src → cli}/commands/init.next-steps.test.mjs +1 -1
  50. package/cli/commands/interactive-guard.test.mjs +66 -0
  51. package/{src → cli}/commands/json-contract.test.mjs +2 -2
  52. package/{src → cli}/commands/layout.mjs +59 -19
  53. package/{src → cli}/commands/search.mjs +22 -15
  54. package/{src → cli}/commands/search.test.mjs +1 -1
  55. package/cli/commands/setup-nudge.test.mjs +108 -0
  56. package/cli/commands/swizzle.mjs +103 -0
  57. package/{src → cli}/commands/template.mjs +84 -53
  58. package/{src → cli}/commands/template.path-safety.test.mjs +2 -2
  59. package/{src → cli}/commands/upgrade.integration-policy.test.mjs +1 -1
  60. package/{src → cli}/commands/upgrade.mjs +291 -77
  61. package/cli/commands/upgrade.test.mjs +314 -0
  62. package/{src → cli}/commands/validate-integration.mjs +17 -37
  63. package/{src → cli}/index.mjs +55 -19
  64. package/{src/codemods → codemods}/__tests__/registry.test.mjs +1 -0
  65. package/{src/codemods → codemods}/ensure-jscodeshift.mjs +12 -28
  66. package/{src/codemods → codemods}/integration-discovery.mjs +6 -3
  67. package/{src/codemods → codemods}/integration-discovery.test.mjs +1 -1
  68. package/{src/codemods → codemods}/integration-runner.mjs +8 -3
  69. package/{src/codemods → codemods}/registry.mjs +4 -1
  70. package/{src/codemods → codemods}/run-codemod.mjs +18 -11
  71. package/{src/codemods → codemods}/runner.mjs +24 -14
  72. package/{src/codemods → codemods}/transforms/v0.0.10/remove-size-props.mjs +9 -4
  73. package/{src/codemods → codemods}/transforms/v0.0.12/add-is-icon-only.mjs +27 -22
  74. package/{src/codemods → codemods}/transforms/v0.0.13/icon-name-deprecations.mjs +12 -5
  75. package/{src/codemods → codemods}/transforms/v0.0.13/rename-attachments-to-drawer.mjs +15 -8
  76. package/{src/codemods → codemods}/transforms/v0.0.13/toolbar-density-to-size.mjs +10 -4
  77. package/{src/codemods → codemods}/transforms/v0.0.14/rename-action-props.mjs +11 -5
  78. package/{src/codemods → codemods}/transforms/v0.0.14/rename-section-wash-to-muted.mjs +11 -6
  79. package/{src/codemods → codemods}/transforms/v0.0.14/rename-status-variants.mjs +15 -10
  80. package/{src/codemods → codemods}/transforms/v0.0.15/migrate-item-children-to-endcontent.mjs +13 -8
  81. package/{src/codemods → codemods}/transforms/v0.0.15/migrate-selector-children-to-render-option.mjs +18 -13
  82. package/{src/codemods → codemods}/transforms/v0.0.15/migrate-theme-selectors-to-data-attrs.mjs +8 -4
  83. package/{src/codemods → codemods}/transforms/v0.0.15/rename-date-picker-to-input.mjs +11 -6
  84. package/{src/codemods → codemods}/transforms/v0.0.15/rename-imperative-ref-to-handleRef.mjs +6 -1
  85. package/{src/codemods → codemods}/transforms/v0.0.15/rename-isStreaming-to-isStopShown.mjs +6 -1
  86. package/{src/codemods → codemods}/transforms/v0.0.15/rename-stack-element-to-as.mjs +8 -3
  87. package/{src/codemods → codemods}/transforms/v0.0.2/migrate-badge-dot-to-statusdot.mjs +17 -10
  88. package/{src/codemods → codemods}/transforms/v0.0.2/migrate-gap-to-numeric.mjs +7 -1
  89. package/{src/codemods → codemods}/transforms/v0.0.2/migrate-isFullBleed-to-padding.mjs +9 -4
  90. package/{src/codemods → codemods}/transforms/v0.0.2/migrate-useXDSIcon-to-getIcon.mjs +12 -7
  91. package/{src/codemods → codemods}/transforms/v0.0.2/rename-banner-endButton-to-endContent.mjs +7 -2
  92. package/{src/codemods → codemods}/transforms/v0.0.2/rename-form-tooltip-startIcon.mjs +8 -2
  93. package/{src/codemods → codemods}/transforms/v0.0.2/rename-isShown-to-isOpen.mjs +7 -2
  94. package/{src/codemods → codemods}/transforms/v0.0.2/rename-selector-items-to-options.mjs +7 -2
  95. package/{src/codemods → codemods}/transforms/v0.0.2/rename-sidenav-header-to-heading.mjs +11 -4
  96. package/{src/codemods → codemods}/transforms/v0.0.2/rename-topnav-title-to-heading.mjs +10 -4
  97. package/{src/codemods → codemods}/transforms/v0.0.2/unify-uncontrolled-to-defaultX.mjs +7 -2
  98. package/{src/codemods → codemods}/transforms/v0.0.2/unify-visibility-to-onOpenChange.mjs +10 -5
  99. package/{src/codemods → codemods}/transforms/v0.0.6/migrate-badge-children-to-label.mjs +7 -2
  100. package/{src/codemods → codemods}/transforms/v0.0.6/migrate-collapse-to-collapsible.mjs +9 -3
  101. package/{src/codemods → codemods}/transforms/v0.0.6/migrate-radius-tokens.mjs +11 -5
  102. package/{src/codemods → codemods}/transforms/v0.0.6/migrate-shadow-tokens.mjs +13 -6
  103. package/{src/codemods → codemods}/transforms/v0.0.6/migrate-skeleton-radius.mjs +7 -1
  104. package/{src/codemods → codemods}/transforms/v0.0.6/migrate-token-names.mjs +11 -5
  105. package/{src/codemods → codemods}/transforms/v0.0.7/rename-banner-variant-to-container.mjs +8 -3
  106. package/{src/codemods → codemods}/transforms/v0.0.8/migrate-token-renames.mjs +15 -8
  107. package/{src/codemods → codemods}/transforms/v0.0.8/rename-endslot-to-endcontent.mjs +7 -2
  108. package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/drop-xds-prefix-imports.test.mjs +42 -7
  109. package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-module-specifiers.test.mjs +43 -0
  110. package/{src/codemods → codemods}/transforms/v0.1.0/drop-xds-prefix-imports.mjs +117 -13
  111. package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-css-surfaces.mjs +21 -17
  112. package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-declare-module.mjs +7 -2
  113. package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-module-specifiers.mjs +86 -15
  114. package/{src/codemods → codemods}/transforms/v0.1.2/rename-text-color-active-to-accent.mjs +15 -9
  115. package/{src/codemods → codemods}/transforms/v0.1.3/migrate-layout-components-to-experimental.mjs +17 -12
  116. package/{src/codemods → codemods}/transforms/v0.1.5/rename-switch-label-spacing-default-to-hug.mjs +15 -9
  117. package/{src/codemods → codemods}/transforms/v0.1.7/migrate-table-tableprops-to-direct-props.mjs +17 -10
  118. package/{src/codemods → codemods}/transforms/v0.1.7/rename-table-renderprops-styles-to-xstyle.mjs +18 -13
  119. package/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +161 -0
  120. package/codemods/transforms/v0.1.8/index.mjs +19 -0
  121. package/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +239 -0
  122. package/docs/cli-integrations.doc.mjs +150 -0
  123. package/docs/elevation.doc.mjs +79 -1
  124. package/docs/getting-started.doc.mjs +9 -9
  125. package/docs/internationalization.doc.mjs +92 -46
  126. package/docs/migration.doc.mjs +18 -18
  127. package/docs/principles.doc.dense.mjs +1 -1
  128. package/docs/principles.doc.mjs +6 -6
  129. package/docs/principles.doc.zh.mjs +1 -1
  130. package/docs/styling-libraries.doc.mjs +3 -3
  131. package/docs/styling.doc.mjs +4 -4
  132. package/docs/theme.doc.dense.mjs +2 -2
  133. package/docs/theme.doc.mjs +7 -7
  134. package/docs/theme.doc.zh.mjs +1 -1
  135. package/docs/tokens.doc.mjs +1 -1
  136. package/docs/working-with-ai.doc.mjs +19 -19
  137. package/{src/commands → lib/agent-docs}/agent-docs.mjs +164 -29
  138. package/{src/commands → lib/agent-docs}/agent-docs.path-safety.test.mjs +1 -1
  139. package/{src/commands → lib/agent-docs}/agent-docs.test.mjs +123 -10
  140. package/{src/lib → lib}/cli-error.mjs +2 -2
  141. package/{src/lib → lib}/component-discovery.mjs +44 -2
  142. package/{src/lib → lib}/component-format.mjs +67 -25
  143. package/{src/lib → lib}/component-loader.mjs +27 -13
  144. package/{src/lib → lib}/componentDocOverlay.test.mjs +0 -1
  145. package/{src/lib → lib}/error-codes.test.mjs +1 -1
  146. package/{src/lib → lib}/hook-discovery.mjs +14 -1
  147. package/{src/lib → lib}/hook-format.mjs +29 -5
  148. package/{src/lib → lib}/integration-warnings.mjs +2 -2
  149. package/{src/lib → lib}/integrations.mjs +20 -0
  150. package/{src/lib → lib}/integrations.test.mjs +1 -1
  151. package/{src/lib → lib}/json-contract.test.mjs +1 -1
  152. package/{src/lib → lib}/json-shim.mjs +11 -6
  153. package/{src/lib → lib}/json-shim.test.mjs +1 -1
  154. package/{src/lib → lib}/json.mjs +3 -3
  155. package/{src/lib → lib}/levenshtein.mjs +6 -0
  156. package/{src/lib → lib}/manifest.mjs +7 -5
  157. package/{src/lib → lib}/manifest.test.mjs +2 -2
  158. package/{src/lib → lib}/module-loader.mjs +1 -0
  159. package/{src/lib → lib}/package-scanner.mjs +47 -0
  160. package/{src/lib → lib}/project.mjs +48 -18
  161. package/{src/lib → lib}/project.test.mjs +1 -1
  162. package/{src/lib → lib}/resolve-theme.mjs +5 -0
  163. package/{src/lib → lib}/string-utils.mjs +15 -0
  164. package/lib/term-log.mjs +57 -0
  165. package/{src/lib → lib}/xle/browser.mjs +18 -8
  166. package/{src/lib → lib}/xle/expand.mjs +155 -22
  167. package/{src/lib → lib}/xle/parse.mjs +119 -13
  168. package/{src/lib → lib}/xle/print.mjs +54 -14
  169. package/{src/lib → lib}/xle/registry-core.mjs +28 -3
  170. package/{src/lib → lib}/xle/registry.mjs +9 -4
  171. package/{src/lib → lib}/xle/splice.mjs +13 -2
  172. package/{src/lib → lib}/xle/validate.mjs +95 -14
  173. package/lib/xle/xle-ast.d.ts +214 -0
  174. package/package.json +37 -28
  175. package/scripts/postinstall.mjs +74 -0
  176. package/templates/blocks/components/Avatar/AvatarFallbackChain.tsx +4 -4
  177. package/templates/blocks/components/Avatar/AvatarGroup.tsx +2 -2
  178. package/templates/blocks/components/Avatar/AvatarInitialsFallback.tsx +1 -1
  179. package/templates/blocks/components/Avatar/AvatarShowcase.tsx +5 -5
  180. package/templates/blocks/components/Avatar/AvatarUserCard.tsx +1 -1
  181. package/templates/blocks/components/Avatar/AvatarWithImage.tsx +4 -4
  182. package/templates/blocks/components/Avatar/AvatarWithStatus.tsx +3 -3
  183. package/templates/blocks/components/AvatarGroup/AvatarGroupShowcase.tsx +2 -2
  184. package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowCustomText.tsx +1 -1
  185. package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowDefault.tsx +1 -1
  186. package/templates/blocks/components/AvatarGroupOverflow/AvatarGroupOverflowShowcase.tsx +2 -2
  187. package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotShowcase.tsx +3 -3
  188. package/templates/blocks/components/AvatarStatusDot/AvatarStatusDotVariants.tsx +3 -3
  189. package/templates/blocks/components/Banner/BannerFloating.doc.mjs +14 -0
  190. package/templates/blocks/components/Banner/BannerFloating.tsx +16 -0
  191. package/templates/blocks/components/Button/ButtonFloating.doc.mjs +14 -0
  192. package/templates/blocks/components/Button/ButtonFloating.tsx +37 -0
  193. package/templates/blocks/components/ButtonGroup/ButtonGroupFloating.doc.mjs +14 -0
  194. package/templates/blocks/components/ButtonGroup/ButtonGroupFloating.tsx +23 -0
  195. package/templates/blocks/components/Card/CardElevations.doc.mjs +14 -0
  196. package/templates/blocks/components/Card/CardElevations.tsx +32 -0
  197. package/templates/blocks/components/Card/ClickableCardElevated.doc.mjs +14 -0
  198. package/templates/blocks/components/Card/ClickableCardElevated.tsx +21 -0
  199. package/templates/blocks/components/Card/SelectableCardElevated.doc.mjs +14 -0
  200. package/templates/blocks/components/Card/SelectableCardElevated.tsx +37 -0
  201. package/templates/blocks/components/Carousel/CarouselSnap.tsx +1 -1
  202. package/templates/blocks/components/ChatComposer/ChatComposerFlat.doc.mjs +14 -0
  203. package/templates/blocks/components/ChatComposer/ChatComposerFlat.tsx +75 -0
  204. package/templates/blocks/components/ChatMessage/ChatMessageAvatarName.tsx +2 -2
  205. package/templates/blocks/components/ChatMessage/ChatMessageMultiBubble.tsx +1 -1
  206. package/templates/blocks/components/ChatMessageBubble/ChatMessageBubbleGrouping.tsx +1 -1
  207. package/templates/blocks/components/ChatMessageBubble/ChatMessageBubbleMetadata.tsx +1 -1
  208. package/templates/blocks/components/ChatMessageList/ChatMessageListDensity.tsx +5 -9
  209. package/templates/blocks/components/ChatMessageList/ChatMessageListFullFeatured.tsx +1 -1
  210. package/templates/blocks/components/CodeBlock/CodeBlockTerminal.tsx +1 -1
  211. package/templates/blocks/components/HoverCard/HoverCardShowcase.tsx +1 -1
  212. package/templates/blocks/components/IconButton/IconButtonFloating.doc.mjs +14 -0
  213. package/templates/blocks/components/IconButton/IconButtonFloating.tsx +37 -0
  214. package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.doc.mjs +19 -0
  215. package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +46 -0
  216. package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider02Overrides.doc.mjs +14 -0
  217. package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider02Overrides.tsx +33 -0
  218. package/templates/blocks/components/Item/ItemWithMedia.tsx +2 -2
  219. package/templates/blocks/components/ListItem/ListItemWithMedia.tsx +2 -2
  220. package/templates/blocks/components/OverflowList/OverflowListCappedToolbar.doc.mjs +14 -0
  221. package/templates/blocks/components/OverflowList/OverflowListCappedToolbar.tsx +39 -0
  222. package/templates/blocks/components/OverflowList/OverflowListMultiRowTags.doc.mjs +14 -0
  223. package/templates/blocks/components/OverflowList/OverflowListMultiRowTags.tsx +44 -0
  224. package/templates/blocks/components/Pagination/PaginationDotsCarousel.tsx +2 -6
  225. package/templates/blocks/components/Stack/StackFillItem.tsx +2 -6
  226. package/templates/blocks/components/TabList/TabListTabsWithActions.doc.mjs +1 -1
  227. package/templates/blocks/components/TabList/TabListTabsWithActions.tsx +2 -7
  228. package/templates/blocks/components/Table/TableRowStatusTable.doc.mjs +14 -0
  229. package/templates/blocks/components/Table/TableRowStatusTable.tsx +59 -0
  230. package/templates/blocks/components/Thumbnail/ThumbnailDisabled.tsx +6 -1
  231. package/templates/blocks/components/Thumbnail/ThumbnailGallery.tsx +1 -0
  232. package/templates/blocks/components/Thumbnail/ThumbnailRemovable.tsx +1 -0
  233. package/templates/blocks/components/TypeaheadItem/TypeaheadItemShowcase.tsx +1 -1
  234. package/templates/pages/ai-chat/page.tsx +4 -4
  235. package/templates/pages/dashboard-portfolio/page.tsx +3 -11
  236. package/templates/pages/detail-page/page.tsx +5 -12
  237. package/templates/pages/documentation-design/page.tsx +1 -1
  238. package/templates/pages/messaging-shell/page.tsx +6 -8
  239. package/templates/pages/table-grouped/page.tsx +9 -14
  240. package/templates/pages/table-page/page.tsx +7 -9
  241. package/templates/pages/table-page-heatmap-status/page.tsx +5 -13
  242. package/{src/types → types}/api.contract.assert.ts +17 -8
  243. package/{src/types → types}/api.d.ts +110 -9
  244. package/{src/types → types}/base.d.ts +40 -4
  245. package/types/build.d.ts +53 -0
  246. package/types/codemod.d.ts +166 -0
  247. package/{src/types → types}/component.d.ts +1 -1
  248. package/{src/types → types}/discover.d.ts +1 -1
  249. package/{src/types → types}/docs.d.ts +1 -4
  250. package/{src/types → types}/hook.d.ts +1 -1
  251. package/{src/types → types}/index.d.ts +1 -0
  252. package/types/jscodeshift.d.ts +19 -0
  253. package/types/layout.d.ts +74 -0
  254. package/{src/types → types}/swizzle.d.ts +4 -0
  255. package/{src/types → types}/template-api.d.ts +4 -1
  256. package/types/theme.d.ts +53 -0
  257. package/types/upgrade.d.ts +108 -0
  258. package/utils/package-manager.mjs +178 -0
  259. package/utils/package-manager.test.mjs +220 -0
  260. package/{src/utils → utils}/path-safety.mjs +0 -18
  261. package/{src/utils → utils}/paths.mjs +4 -1
  262. package/{src/utils → utils}/update-check.mjs +5 -4
  263. package/{src/utils → utils}/update-check.test.mjs +3 -3
  264. package/docs/integration-authoring.md +0 -105
  265. package/src/commands/build.mjs +0 -196
  266. package/src/commands/init.mjs +0 -288
  267. package/src/commands/interactive-guard.test.mjs +0 -69
  268. package/src/commands/swizzle.mjs +0 -440
  269. package/src/commands/upgrade.test.mjs +0 -160
  270. package/src/types/codemod.d.ts +0 -81
  271. package/src/types/theme.d.ts +0 -23
  272. package/src/types/upgrade.d.ts +0 -64
  273. package/src/utils/interactive.mjs +0 -76
  274. package/src/utils/interactive.test.mjs +0 -70
  275. package/src/utils/package-manager.mjs +0 -74
  276. package/src/utils/package-manager.test.mjs +0 -113
  277. /package/{src/api → api/docs}/docOverlays.test.mjs +0 -0
  278. /package/{src/api → api/integration}/integration-block-exports.test.mjs +0 -0
  279. /package/{src/api → api/template}/template.test.mjs +0 -0
  280. /package/{src → authoring}/codemod.test.mjs +0 -0
  281. /package/{src → authoring}/config.mjs +0 -0
  282. /package/{src → authoring}/integration.mjs +0 -0
  283. /package/{src → authoring}/template.test.mjs +0 -0
  284. /package/{src → cli}/cli-exit-codes.test.mjs +0 -0
  285. /package/{src → cli}/commands/build-theme.color-scheme.test.mjs +0 -0
  286. /package/{src → cli}/commands/build-theme.import-path.test.mjs +0 -0
  287. /package/{src → cli}/commands/build-theme.path-safety.test.mjs +0 -0
  288. /package/{src → cli}/commands/build-theme.prose.test.mjs +0 -0
  289. /package/{src → cli}/commands/build-theme.variants.test.mjs +0 -0
  290. /package/{src → cli}/commands/build-theme.watch.test.mjs +0 -0
  291. /package/{src → cli}/commands/component.test.mjs +0 -0
  292. /package/{src → cli}/commands/detail-levels.test.mjs +0 -0
  293. /package/{src → cli}/commands/swizzle.path-safety.test.mjs +0 -0
  294. /package/{src → cli}/commands/swizzle.routing.test.mjs +0 -0
  295. /package/{src → cli}/commands/template.test.mjs +0 -0
  296. /package/{src → cli}/commands/upgrade.config-ordering.test.mjs +0 -0
  297. /package/{src → cli}/commands/validate-integration.test.mjs +0 -0
  298. /package/{src → cli}/update-hint-commands.test.mjs +0 -0
  299. /package/{src/codemods → codemods}/__tests__/rename-imperative-ref-to-handleRef.test.mjs +0 -0
  300. /package/{src/codemods → codemods}/__tests__/rename-isStreaming-to-isStopShown.test.mjs +0 -0
  301. /package/{src/codemods → codemods}/__tests__/rename-section-wash-to-muted.test.mjs +0 -0
  302. /package/{src/codemods → codemods}/__tests__/runner.test.mjs +0 -0
  303. /package/{src/codemods → codemods}/__tests__/toolbar-density-to-size.test.mjs +0 -0
  304. /package/{src/codemods → codemods}/__tests__/validation.test.mjs +0 -0
  305. /package/{src/codemods → codemods}/transforms/v0.0.10/__tests__/remove-size-props.test.mjs +0 -0
  306. /package/{src/codemods → codemods}/transforms/v0.0.10/index.mjs +0 -0
  307. /package/{src/codemods → codemods}/transforms/v0.0.12/__tests__/add-is-icon-only.test.mjs +0 -0
  308. /package/{src/codemods → codemods}/transforms/v0.0.12/index.mjs +0 -0
  309. /package/{src/codemods → codemods}/transforms/v0.0.13/__tests__/icon-name-deprecations.test.mjs +0 -0
  310. /package/{src/codemods → codemods}/transforms/v0.0.13/__tests__/rename-attachments-to-drawer.test.mjs +0 -0
  311. /package/{src/codemods → codemods}/transforms/v0.0.13/index.mjs +0 -0
  312. /package/{src/codemods → codemods}/transforms/v0.0.14/__tests__/rename-action-props.test.mjs +0 -0
  313. /package/{src/codemods → codemods}/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +0 -0
  314. /package/{src/codemods → codemods}/transforms/v0.0.14/index.mjs +0 -0
  315. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-item-children-to-endcontent.test.mjs +0 -0
  316. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-selector-children-to-render-option.test.mjs +0 -0
  317. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-theme-selectors-to-data-attrs.test.mjs +0 -0
  318. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/rename-date-picker-to-input.test.mjs +0 -0
  319. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/rename-stack-element-to-as.test.mjs +0 -0
  320. /package/{src/codemods → codemods}/transforms/v0.0.15/index.mjs +0 -0
  321. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-badge-dot-to-statusdot.test.mjs +0 -0
  322. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-gap-to-numeric.test.mjs +0 -0
  323. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-isFullBleed-to-padding.test.mjs +0 -0
  324. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-useXDSIcon-to-getIcon.test.mjs +0 -0
  325. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-banner-endButton-to-endContent.test.mjs +0 -0
  326. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-form-tooltip-startIcon.test.mjs +0 -0
  327. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-isShown-to-isOpen.test.mjs +0 -0
  328. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-selector-items-to-options.test.mjs +0 -0
  329. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-sidenav-header-to-heading.test.mjs +0 -0
  330. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-topnav-title-to-heading.test.mjs +0 -0
  331. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/unify-uncontrolled-to-defaultX.test.mjs +0 -0
  332. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/unify-visibility-to-onOpenChange.test.mjs +0 -0
  333. /package/{src/codemods → codemods}/transforms/v0.0.2/index.mjs +0 -0
  334. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-collapse-to-collapsible.test.mjs +0 -0
  335. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-radius-tokens.test.mjs +0 -0
  336. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-shadow-tokens.test.mjs +0 -0
  337. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-skeleton-radius.test.mjs +0 -0
  338. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-token-names.test.mjs +0 -0
  339. /package/{src/codemods → codemods}/transforms/v0.0.6/index.mjs +0 -0
  340. /package/{src/codemods → codemods}/transforms/v0.0.7/__tests__/rename-banner-variant-to-container.test.mjs +0 -0
  341. /package/{src/codemods → codemods}/transforms/v0.0.7/index.mjs +0 -0
  342. /package/{src/codemods → codemods}/transforms/v0.0.8/__tests__/migrate-token-renames.test.mjs +0 -0
  343. /package/{src/codemods → codemods}/transforms/v0.0.8/__tests__/rename-endslot-to-endcontent.test.mjs +0 -0
  344. /package/{src/codemods → codemods}/transforms/v0.0.8/index.mjs +0 -0
  345. /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-css-surfaces.test.mjs +0 -0
  346. /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-declare-module.test.mjs +0 -0
  347. /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/v0.1.0-ordering.test.mjs +0 -0
  348. /package/{src/codemods → codemods}/transforms/v0.1.0/index.mjs +0 -0
  349. /package/{src/codemods → codemods}/transforms/v0.1.2/__tests__/rename-text-color-active-to-accent.test.mjs +0 -0
  350. /package/{src/codemods → codemods}/transforms/v0.1.2/index.mjs +0 -0
  351. /package/{src/codemods → codemods}/transforms/v0.1.3/__tests__/migrate-layout-components-to-experimental.test.mjs +0 -0
  352. /package/{src/codemods → codemods}/transforms/v0.1.3/index.mjs +0 -0
  353. /package/{src/codemods → codemods}/transforms/v0.1.5/__tests__/rename-switch-label-spacing-default-to-hug.test.mjs +0 -0
  354. /package/{src/codemods → codemods}/transforms/v0.1.5/index.mjs +0 -0
  355. /package/{src/codemods → codemods}/transforms/v0.1.7/__tests__/migrate-table-tableprops-to-direct-props.test.mjs +0 -0
  356. /package/{src/codemods → codemods}/transforms/v0.1.7/__tests__/rename-table-renderprops-styles-to-xstyle.test.mjs +0 -0
  357. /package/{src/codemods → codemods}/transforms/v0.1.7/index.mjs +0 -0
  358. /package/{src/lib → lib}/cli-error.test.mjs +0 -0
  359. /package/{src/lib → lib}/component-discovery.importpath.test.mjs +0 -0
  360. /package/{src/lib → lib}/component-format.test.mjs +0 -0
  361. /package/{src/lib → lib}/component-loader.test.mjs +0 -0
  362. /package/{src/lib → lib}/config-cache.mjs +0 -0
  363. /package/{src/lib → lib}/config-cache.test.mjs +0 -0
  364. /package/{src/lib → lib}/config-schema.mjs +0 -0
  365. /package/{src/lib → lib}/error-codes.mjs +0 -0
  366. /package/{src/lib → lib}/integration-warnings.test.mjs +0 -0
  367. /package/{src/lib → lib}/module-loader.test.mjs +0 -0
  368. /package/{src/lib → lib}/node-version.mjs +0 -0
  369. /package/{src/lib → lib}/node-version.test.mjs +0 -0
  370. /package/{src/lib → lib}/parse.mjs +0 -0
  371. /package/{src/lib → lib}/site.mjs +0 -0
  372. /package/{src/lib → lib}/xle/browser.d.ts +0 -0
  373. /package/{src/lib → lib}/xle/xle.test.mjs +0 -0
  374. /package/{src/schemas → schemas}/doc-schema.mjs +0 -0
  375. /package/{src/schemas → schemas}/template-schema.mjs +0 -0
  376. /package/{src/types → types}/config.d.ts +0 -0
  377. /package/{src/types → types}/doc.d.ts +0 -0
  378. /package/{src/types → types}/doctor.d.ts +0 -0
  379. /package/{src/types → types}/error-codes.d.ts +0 -0
  380. /package/{src/types → types}/integration.d.ts +0 -0
  381. /package/{src/types → types}/manifest.d.ts +0 -0
  382. /package/{src/types → types}/search.d.ts +0 -0
  383. /package/{src/types → types}/template.d.ts +0 -0
  384. /package/{src/types → types}/validate-integration.d.ts +0 -0
  385. /package/{src/utils → utils}/github.mjs +0 -0
  386. /package/{src/utils → utils}/path-safety.test.mjs +0 -0
  387. /package/{src/utils → utils}/paths.test.mjs +0 -0
  388. /package/{src/utils → utils}/semver.mjs +0 -0
  389. /package/{src/utils → utils}/semver.test.mjs +0 -0
@@ -16,10 +16,10 @@
16
16
  * astryx search button --json Typed JSON envelope
17
17
  */
18
18
 
19
- import {getRunPrefix} from '../utils/package-manager.mjs';
20
- import {jsonOut, humanLog} from '../lib/json.mjs';
21
- import {cliError} from '../lib/cli-error.mjs';
22
- import {search as searchApi, SEARCH_DOMAINS} from '../api/search.mjs';
19
+ import {getCliInvocation, formatCliCommand} from '../../utils/package-manager.mjs';
20
+ import {jsonOut, humanLog} from '../../lib/json.mjs';
21
+ import {cliError} from '../../lib/cli-error.mjs';
22
+ import {search as searchApi, SEARCH_DOMAINS} from '../../api/search/search.mjs';
23
23
 
24
24
  const DOMAIN_LABEL = {
25
25
  component: 'component',
@@ -28,6 +28,9 @@ const DOMAIN_LABEL = {
28
28
  template: 'template',
29
29
  };
30
30
 
31
+ /**
32
+ * @param {import('commander').Command} program
33
+ */
31
34
  export function registerSearch(program) {
32
35
  program
33
36
  .command('search <query>')
@@ -35,7 +38,7 @@ export function registerSearch(program) {
35
38
  .option('--type <domain>', `Filter to one domain (${SEARCH_DOMAINS.join('|')})`)
36
39
  .option('--limit <n>', 'Max number of results (default 20)')
37
40
  .option('--detail', 'Verbose output (include import paths and match reason)')
38
- .action(async (query, options) => {
41
+ .action(async (/** @type {string} */ query, /** @type {{type?: import('../../types/search').SearchDomain, limit?: string, detail?: boolean}} */ options) => {
39
42
  const json = program.opts().json || false;
40
43
 
41
44
  let limit = 20;
@@ -48,22 +51,26 @@ export function registerSearch(program) {
48
51
  limit = parsed;
49
52
  }
50
53
 
54
+ /** @type {import('../../types/search').SearchResponse} */
51
55
  let result;
52
56
  try {
53
- result = await searchApi(query, {
54
- cwd: process.cwd(),
55
- type: options.type,
56
- limit,
57
- });
57
+ result = /** @type {import('../../types/search').SearchResponse} */ (
58
+ await searchApi(query, {
59
+ cwd: process.cwd(),
60
+ type: options.type,
61
+ limit,
62
+ })
63
+ );
58
64
  } catch (e) {
59
- cliError(e.message, {suggestions: e.suggestions});
65
+ const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
66
+ cliError(err.message, {suggestions: err.suggestions});
60
67
  return;
61
68
  }
62
69
 
63
70
  if (json) return jsonOut(result.type, result.data);
64
71
 
65
72
  // ── Text output ──────────────────────────────────────────────
66
- const run = getRunPrefix();
73
+ const run = getCliInvocation();
67
74
  const {query: q, results} = result.data;
68
75
 
69
76
  // No matches is a valid, successful outcome — clean message, exit 0.
@@ -71,7 +78,7 @@ export function registerSearch(program) {
71
78
  humanLog('');
72
79
  humanLog(`No results for "${q}".`);
73
80
  humanLog('');
74
- humanLog(`Try a broader term, or browse: ${run} astryx component --list`);
81
+ humanLog(`Try a broader term, or browse: ${run} component --list`);
75
82
  humanLog('');
76
83
  return;
77
84
  }
@@ -86,7 +93,7 @@ export function registerSearch(program) {
86
93
  if (r.description) {
87
94
  humanLog(` ${r.description}`);
88
95
  }
89
- humanLog(` → ${run} ${r.command}`);
96
+ humanLog(` → ${formatCliCommand(r.command)}`);
90
97
  if (options.detail) {
91
98
  if (r.import) humanLog(` import: ${r.import}`);
92
99
  humanLog(` match: ${r.reason} (score ${r.score})`);
@@ -97,4 +104,4 @@ export function registerSearch(program) {
97
104
  }
98
105
 
99
106
  // Re-export the API for external consumers.
100
- export {search, SEARCH_DOMAINS} from '../api/search.mjs';
107
+ export {search, SEARCH_DOMAINS} from '../../api/search/search.mjs';
@@ -14,7 +14,7 @@ import {describe, it, expect} from 'vitest';
14
14
  import {spawnSync} from 'node:child_process';
15
15
  import * as path from 'node:path';
16
16
  import {fileURLToPath} from 'node:url';
17
- import {search, scoreCandidate, SEARCH_DOMAINS} from '../api/search.mjs';
17
+ import {search, scoreCandidate, SEARCH_DOMAINS} from '../../api/search/search.mjs';
18
18
 
19
19
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
20
20
  const CLI_BIN = path.resolve(__dirname, '../../bin/astryx.mjs');
@@ -0,0 +1,108 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Guardrail tests — the centralized setup check + enforcement layer 3.
5
+ *
6
+ * Unit: isAstryxInitialized() detects the Astryx marker across EVERY agent-doc
7
+ * location (including the previously-missed Hermes files) and legacy XDS blocks.
8
+ *
9
+ * Integration: the CLI nudges (stderr) before a command when the project hasn't
10
+ * run init — INCLUDING in --json mode (agents pass --json, and stderr never
11
+ * corrupts the stdout JSON envelope). Quiet once set up, outside a project, and
12
+ * for the installer command itself.
13
+ */
14
+
15
+ import {describe, it, expect, beforeEach, afterEach} from 'vitest';
16
+ import {spawnSync} from 'node:child_process';
17
+ import * as fs from 'node:fs';
18
+ import * as path from 'node:path';
19
+ import * as os from 'node:os';
20
+ import {fileURLToPath} from 'node:url';
21
+ import {isAstryxInitialized} from '../../lib/agent-docs/agent-docs.mjs';
22
+
23
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
24
+ const CLI = path.resolve(__dirname, '..', '..', 'bin', 'astryx.mjs');
25
+ const MARKER = '<!-- ASTRYX:START -->';
26
+ const NUDGE = /finish setup and install the Astryx agent prompt/;
27
+
28
+ let tmp;
29
+ beforeEach(() => {
30
+ tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-setup-nudge-'));
31
+ });
32
+ afterEach(() => {
33
+ fs.rmSync(tmp, {recursive: true, force: true});
34
+ });
35
+
36
+ function write(rel, body) {
37
+ const p = path.join(tmp, rel);
38
+ fs.mkdirSync(path.dirname(p), {recursive: true});
39
+ fs.writeFileSync(p, body);
40
+ }
41
+
42
+ function run(args, cwd = tmp) {
43
+ return spawnSync(process.execPath, [CLI, ...args], {
44
+ cwd,
45
+ encoding: 'utf8',
46
+ timeout: 30_000,
47
+ env: {...process.env, FORCE_COLOR: '0'},
48
+ });
49
+ }
50
+
51
+ describe('isAstryxInitialized — centralized setup check (one place)', () => {
52
+ it('is false in an empty project', () => {
53
+ expect(isAstryxInitialized(tmp)).toBe(false);
54
+ });
55
+
56
+ // Covers EVERY location a preset can write — .hermes.md/HERMES.md were the gap.
57
+ it.each(['AGENTS.md', 'CLAUDE.md', '.claude/CLAUDE.md', '.cursorrules', '.hermes.md', 'HERMES.md'])(
58
+ 'detects the marker in %s',
59
+ file => {
60
+ write(file, `# doc\n${MARKER}\nbody`);
61
+ expect(isAstryxInitialized(tmp)).toBe(true);
62
+ },
63
+ );
64
+
65
+ it('detects the legacy XDS marker for back-compat', () => {
66
+ write('AGENTS.md', '<!-- XDS:START -->');
67
+ expect(isAstryxInitialized(tmp)).toBe(true);
68
+ });
69
+
70
+ it('is false when a doc file exists WITHOUT the marker', () => {
71
+ write('AGENTS.md', 'project notes, no astryx block');
72
+ expect(isAstryxInitialized(tmp)).toBe(false);
73
+ });
74
+ });
75
+
76
+ describe('enforcement layer 3 — per-command setup nudge', () => {
77
+ const asProject = () => write('package.json', '{"name":"t"}');
78
+
79
+ it('nudges on stderr after a command when not set up', () => {
80
+ asProject();
81
+ const r = run(['docs', 'tokens']);
82
+ expect(r.stderr).toMatch(NUDGE);
83
+ });
84
+
85
+ it('is suppressed in --json (machine mode stays clean), stdout valid JSON', () => {
86
+ asProject();
87
+ const r = run(['--json', 'docs', 'tokens']);
88
+ // --json is machine output with a clean stdout+stderr contract; the human
89
+ // nudge must NOT leak into it (json-shim: error envelopes have empty stderr).
90
+ expect(r.stderr).not.toMatch(NUDGE);
91
+ expect(() => JSON.parse(r.stdout)).not.toThrow();
92
+ });
93
+
94
+ it('is quiet once set up (marker present)', () => {
95
+ asProject();
96
+ write('AGENTS.md', MARKER);
97
+ expect(run(['docs', 'tokens']).stderr).not.toMatch(NUDGE);
98
+ });
99
+
100
+ it('is quiet outside a project (no package.json)', () => {
101
+ expect(run(['docs', 'tokens']).stderr).not.toMatch(NUDGE);
102
+ });
103
+
104
+ it('does not nudge for the installer command itself', () => {
105
+ asProject();
106
+ expect(run(['init']).stderr).not.toMatch(NUDGE);
107
+ });
108
+ });
@@ -0,0 +1,103 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file swizzle command — thin wrapper around api/swizzle.
5
+ *
6
+ * Copies a component's source into the consumer project for customization
7
+ * (imports rewritten to the owner package's subpaths). All logic — owner
8
+ * resolution, copy, import rewriting, StyleX detection, maintainer feedback —
9
+ * lives in api/swizzle; this file only parses flags, prints, and prefixes
10
+ * commands for the caller's package manager.
11
+ */
12
+
13
+ import {jsonOut, humanLog} from '../../lib/json.mjs';
14
+ import {cliError} from '../../lib/cli-error.mjs';
15
+ import {getCliInvocation} from '../../utils/package-manager.mjs';
16
+ import {swizzle as swizzleApi} from '../../api/swizzle/swizzle.mjs';
17
+
18
+ /**
19
+ * @param {import('commander').Command} program
20
+ */
21
+ export function registerSwizzle(program) {
22
+ program
23
+ .command('swizzle [component]')
24
+ .description('Copy component source for customization')
25
+ .option('--output <dir>', 'Output directory', './components/astryx')
26
+ .option('--package <pkg>', 'Scope to a specific owning package')
27
+ .option('--list', 'List available components')
28
+ .option('-f, --overwrite', 'Overwrite existing files without prompting')
29
+ .action(async (/** @type {string | undefined} */ component, /** @type {{output: string, package?: string, list?: boolean, overwrite?: boolean}} */ options) => {
30
+ const json = program.opts().json || false;
31
+ const run = getCliInvocation();
32
+
33
+ /** @type {import('../../types/swizzle').SwizzleListResponse | import('../../types/swizzle').SwizzleCopyResponse} */
34
+ let result;
35
+ try {
36
+ result = await swizzleApi(component, {
37
+ cwd: process.cwd(),
38
+ output: options.output,
39
+ package: options.package,
40
+ list: options.list,
41
+ overwrite: options.overwrite,
42
+ });
43
+ } catch (e) {
44
+ const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
45
+ cliError(err.message, {suggestions: err.suggestions, code: err.code});
46
+ return;
47
+ }
48
+
49
+ if (json) return jsonOut(result.type, result.data);
50
+
51
+ if (result.type === 'swizzle.list') {
52
+ const components = result.data;
53
+ humanLog('\nAvailable components:\n');
54
+ for (const name of components) {
55
+ humanLog(` ${name}`);
56
+ }
57
+ humanLog(`\nUsage: ${run} swizzle <component>\n`);
58
+ humanLog(`Example: ${run} swizzle Button`);
59
+ humanLog(` ${run} swizzle XDSButton (XDS prefix also works)\n`);
60
+ return;
61
+ }
62
+
63
+ const {package: ownerPackage, outputDir, filesCopied, usesStyleX, feedback} =
64
+ result.data;
65
+
66
+ humanLog(`\n✓ Copied ${filesCopied} files to ${outputDir}/\n`);
67
+ humanLog(`Relative imports have been rewritten to use ${ownerPackage}.`);
68
+ humanLog('You can now customize the component source freely.\n');
69
+
70
+ // StyleX build requirement — swizzled StyleX source renders unstyled with
71
+ // no error unless the consumer's build runs a StyleX compiler.
72
+ if (usesStyleX) {
73
+ humanLog(
74
+ '⚠ These components use StyleX and require a StyleX compiler in your build.',
75
+ );
76
+ humanLog(
77
+ ' Without one they render unstyled (no error). See setup per framework:',
78
+ );
79
+ humanLog(` ${run} docs styling`);
80
+ humanLog(
81
+ ' Next.js note: the StyleX Babel plugin disables SWC and breaks next/font —',
82
+ );
83
+ humanLog(
84
+ ' use an SWC-based StyleX transform instead (covered in the guide).',
85
+ );
86
+ humanLog('');
87
+ }
88
+
89
+ // Maintainer feedback note (skipped when the owner ships no issues URL).
90
+ if (feedback) {
91
+ humanLog(
92
+ 'Customizing a component often signals a gap in the design system.',
93
+ );
94
+ humanLog('Let the maintainers know what you needed:');
95
+ if (feedback.ghCommand) {
96
+ humanLog(` ${feedback.ghCommand}`);
97
+ } else {
98
+ humanLog(` ${feedback.issuesUrl}`);
99
+ }
100
+ humanLog('');
101
+ }
102
+ });
103
+ }
@@ -6,25 +6,44 @@
6
6
 
7
7
  import * as path from 'node:path';
8
8
  import * as fs from 'node:fs';
9
- import * as p from '@clack/prompts';
10
- import {isNonInteractive} from '../utils/path-safety.mjs';
11
- import {jsonOut, humanLog} from '../lib/json.mjs';
12
- import {cliError} from '../lib/cli-error.mjs';
13
- import {ERROR_CODES} from '../lib/error-codes.mjs';
14
- import {template as templateApi} from '../api/template.mjs';
15
- import {Project} from '../lib/project.mjs';
16
- import {warnOnIntegrationIssues} from '../lib/integration-warnings.mjs';
17
-
18
- export {discoverTemplates, listTemplates} from '../api/template.mjs';
19
-
20
- function isCancel(value) {
21
- if (p.isCancel(value)) {
22
- p.cancel('Cancelled.');
23
- process.exit(0);
24
- }
25
- return value;
26
- }
9
+ import {jsonOut, humanLog} from '../../lib/json.mjs';
10
+ import {cliError} from '../../lib/cli-error.mjs';
11
+ import {ERROR_CODES} from '../../lib/error-codes.mjs';
12
+ import {template as templateApi} from '../../api/template/template.mjs';
13
+ import {Project} from '../../lib/project.mjs';
14
+ import {warnOnIntegrationIssues} from '../../lib/integration-warnings.mjs';
15
+ import {getCliInvocation} from '../../utils/package-manager.mjs';
16
+
17
+ export {discoverTemplates, listTemplates} from '../../api/template/template.mjs';
18
+
19
+ /**
20
+ * A template entry as produced by the discover* helpers in api/template.mjs.
21
+ * The api layer returns these as `object[]`; this local shape captures the
22
+ * fields the command consumes. Remove once api/template.mjs exports a precise
23
+ * type for its discovered templates.
24
+ * @typedef {object} DiscoveredTemplate
25
+ * @property {'page' | 'block'} type
26
+ * @property {string} dirName
27
+ * @property {string} name
28
+ * @property {string} filePath
29
+ */
30
+
31
+ /**
32
+ * The discriminated response returned by the template API. The api layer
33
+ * currently declares `{type: string, data: unknown}`; narrow it here to the
34
+ * precise union so the switch below type-checks. Replace with the api's own
35
+ * return type once it is tightened.
36
+ * @typedef {(
37
+ * import('../../types/template').TemplateListResponse |
38
+ * import('../../types/template').TemplateShowResponse |
39
+ * import('../../types/template').TemplateSkeletonResponse |
40
+ * import('../../types/template').TemplateCopyResponse
41
+ * )} TemplateResponse
42
+ */
27
43
 
44
+ /**
45
+ * @param {import('commander').Command} program
46
+ */
28
47
  export function registerTemplate(program) {
29
48
  program
30
49
  .command('template [name] [path]')
@@ -34,15 +53,27 @@ export function registerTemplate(program) {
34
53
  .option('--package <pkg>', 'Narrow to templates from a specific package')
35
54
  .option('--skeleton', 'Show layout skeleton with spatial annotations (padding, gap, nesting)')
36
55
  .option('-f, --overwrite', 'Overwrite existing files without prompting')
37
- .action(async (name, targetPath, options) => {
56
+ .action(
57
+ /**
58
+ * @param {string | undefined} name
59
+ * @param {string | undefined} targetPath
60
+ * @param {{list?: boolean, type?: string, package?: string, skeleton?: boolean, overwrite?: boolean}} options
61
+ */
62
+ async (name, targetPath, options) => {
38
63
  const json = program.opts().json || false;
64
+ const run = getCliInvocation();
39
65
 
40
66
  // Non-blocking nudge: if any configured integration has validation
41
67
  // issues, print one compact line to stderr pointing at
42
68
  // validate-integration. Best-effort; suppressed in --json mode.
43
69
  try {
44
70
  const project = await Project.load(process.cwd());
45
- await warnOnIntegrationIssues(project.loadedIntegrations, {json});
71
+ await warnOnIntegrationIssues(
72
+ /** @type {Array<import('../../lib/integrations.mjs').LoadedIntegration>} */ (
73
+ project.loadedIntegrations
74
+ ),
75
+ {json},
76
+ );
46
77
  } catch {
47
78
  // Never let the nudge break the command.
48
79
  }
@@ -59,40 +90,32 @@ export function registerTemplate(program) {
59
90
  const collision = await detectTemplateCollision(name, targetPath);
60
91
  if (collision && !options.overwrite) {
61
92
  const rel = path.relative(process.cwd(), collision) || collision;
62
- if (json || isNonInteractive({json})) {
63
- const msg =
64
- `Refusing to overwrite existing file ${rel}. ` +
65
- `Re-run with --overwrite (or -f) to replace it.`;
66
- cliError(msg, {code: ERROR_CODES.ERR_FILE_EXISTS});
67
- return;
68
- }
69
- const confirmed = isCancel(
70
- await p.confirm({
71
- message: `Overwrite existing file ${rel}?`,
72
- initialValue: false,
73
- }),
74
- );
75
- if (!confirmed) {
76
- humanLog('Aborted. Re-run with --overwrite to replace the file.');
77
- return;
78
- }
93
+ const msg =
94
+ `Refusing to overwrite existing file ${rel}. ` +
95
+ `Re-run with --overwrite (or -f) to replace it.`;
96
+ cliError(msg, {code: ERROR_CODES.ERR_FILE_EXISTS});
97
+ return;
79
98
  }
80
99
  }
81
100
 
101
+ /** @type {TemplateResponse} */
82
102
  let result;
83
103
  try {
84
- result = await templateApi(name, {
85
- list: options.list,
86
- skeleton: options.skeleton,
87
- type: options.type,
88
- package: options.package,
89
- targetPath,
90
- cwd: process.cwd(),
91
- });
104
+ result = /** @type {TemplateResponse} */ (
105
+ await templateApi(name, {
106
+ list: options.list,
107
+ skeleton: options.skeleton,
108
+ type: /** @type {'page' | 'block' | undefined} */ (options.type),
109
+ package: options.package,
110
+ targetPath,
111
+ cwd: process.cwd(),
112
+ })
113
+ );
92
114
  } catch (e) {
93
115
  // template API throws structured errors with {name, reason} suggestions —
94
116
  // pass them through untouched so the CLI envelope matches the API.
95
- cliError(e.message, {suggestions: e.suggestions || [], code: e.code});
117
+ const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
118
+ cliError(err.message, {suggestions: err.suggestions || [], code: err.code});
96
119
  return;
97
120
  }
98
121
 
@@ -102,6 +125,7 @@ export function registerTemplate(program) {
102
125
  case 'template.list': {
103
126
  const pages = result.data.filter(t => t.type === 'page');
104
127
  const blocks = result.data.filter(t => t.type === 'block');
128
+ /** @param {import('../../types/template').TemplateListEntry} t */
105
129
  const renderEntry = t => {
106
130
  const status = t.isReady ? '' : ' (WIP)';
107
131
  const pkg =
@@ -120,10 +144,10 @@ export function registerTemplate(program) {
120
144
  for (const t of blocks) renderEntry(t);
121
145
  }
122
146
  humanLog('\nUsage:');
123
- humanLog(' astryx template <id> [target-path] Scaffold page or block');
124
- humanLog(' astryx template <id> --skeleton Layout reference');
125
- humanLog(' astryx template --list --type block List only blocks');
126
- humanLog(' astryx template --list --package <pkg> List from one package\n');
147
+ humanLog(` ${run} template <id> [target-path] Scaffold page or block`);
148
+ humanLog(` ${run} template <id> --skeleton Layout reference`);
149
+ humanLog(` ${run} template --list --type block List only blocks`);
150
+ humanLog(` ${run} template --list --package <pkg> List from one package\n`);
127
151
  break;
128
152
  }
129
153
 
@@ -159,12 +183,19 @@ export function registerTemplate(program) {
159
183
  * Path-safety enforcement happens inside the API; here we only need
160
184
  * enough precision to check existence — a false negative just means the
161
185
  * API will catch the issue and abort.
186
+ *
187
+ * @param {string} name
188
+ * @param {string} targetPath
189
+ * @returns {Promise<string | null>}
162
190
  */
163
191
  async function detectTemplateCollision(name, targetPath) {
164
- const {discoverTemplates} = await import('../api/template.mjs');
192
+ const {discoverTemplates} = await import('../../api/template/template.mjs');
193
+ /** @type {DiscoveredTemplate[]} */
165
194
  let templates;
166
195
  try {
167
- templates = await discoverTemplates(process.cwd());
196
+ templates = /** @type {DiscoveredTemplate[]} */ (
197
+ await discoverTemplates(process.cwd())
198
+ );
168
199
  } catch {
169
200
  return null;
170
201
  }
@@ -177,7 +208,7 @@ async function detectTemplateCollision(name, targetPath) {
177
208
  const resolved = path.resolve(process.cwd(), targetPath);
178
209
 
179
210
  // File-arg branch: targetPath looks like `./foo.tsx`.
180
- const {isFilePathArg} = await import('../utils/path-safety.mjs');
211
+ const {isFilePathArg} = await import('../../utils/path-safety.mjs');
181
212
  let dest;
182
213
  if (isFilePathArg(targetPath)) {
183
214
  dest = resolved;
@@ -18,7 +18,7 @@ let templateApi;
18
18
 
19
19
  beforeEach(async () => {
20
20
  tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-template-paths-'));
21
- templateApi = (await import('../api/template.mjs')).template;
21
+ templateApi = (await import('../../api/template/template.mjs')).template;
22
22
  });
23
23
  afterEach(() => {
24
24
  fs.rmSync(tmpDir, {recursive: true, force: true});
@@ -57,7 +57,7 @@ describe('template path safety', () => {
57
57
  fs.mkdirSync(cwd, {recursive: true});
58
58
 
59
59
  // Use a real template name from the discovered set.
60
- const {discoverTemplates} = await import('../api/template.mjs');
60
+ const {discoverTemplates} = await import('../../api/template/template.mjs');
61
61
  const all = await discoverTemplates();
62
62
  const page = all.find(t => t.type === 'page');
63
63
  if (!page) {
@@ -26,7 +26,7 @@ let errCalls;
26
26
  let exitCode;
27
27
 
28
28
  const codemodModuleUrl = pathToFileURL(
29
- path.resolve(process.cwd(), 'packages/cli/src/codemod.mjs'),
29
+ path.resolve(process.cwd(), 'packages/cli/authoring/codemod.mjs'),
30
30
  ).href;
31
31
 
32
32
  beforeEach(() => {