@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
@@ -0,0 +1,172 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file build command — thin wrapper around api/build.
5
+ *
6
+ * astryx build → the PLAYBOOK (how to build a page)
7
+ * astryx build "<what>" → a COMPOSITION KIT (closest page template,
8
+ * blocks, components) with a recommended START.
9
+ *
10
+ * All grouping/scoring lives in api/build; this file only parses flags and
11
+ * renders. Command strings are prefixed for the caller's package manager here
12
+ * (never in the API payload) via formatCliCommand/getCliInvocation.
13
+ */
14
+
15
+ import {getCliInvocation, formatCliCommand} from '../../utils/package-manager.mjs';
16
+ import {jsonOut, humanLog} from '../../lib/json.mjs';
17
+ import {cliError} from '../../lib/cli-error.mjs';
18
+ import {build as buildApi} from '../../api/build/build.mjs';
19
+
20
+ /**
21
+ * Print the build playbook (shown when `build` is run with no query).
22
+ * @param {string} run - The CLI invocation prefix (e.g. `npx astryx`).
23
+ */
24
+ function printPlaybook(run) {
25
+ const lines = [
26
+ '',
27
+ 'How to build a page with Astryx',
28
+ '',
29
+ "1. Find a starting point for what you're building:",
30
+ ` ${run} build "<what you're building>"`,
31
+ ' → returns the closest [page] template, the [block]s that cover parts,',
32
+ ' and the [component]s to fill the gaps, with a "Compose:" suggestion.',
33
+ '',
34
+ '2. If a [page] template matches → scaffold it and adapt:',
35
+ ` ${run} template <name> [path]`,
36
+ '',
37
+ '3. If nothing matches exactly → compose:',
38
+ ` ${run} template <name> --skeleton # study a close page's layout`,
39
+ ` ${run} template <BlockName> # drop in each block from the kit`,
40
+ ` ${run} component <Name> # fill remaining gaps (read props)`,
41
+ '',
42
+ '4. Rules (keep it on-system):',
43
+ ' - No <div>/raw HTML for layout — use VStack/HStack/Grid/Stack/Card etc.',
44
+ ` - No style={{}} — use component props; design tokens via \`${run} docs tokens\`.`,
45
+ ' - Wrap the app in <Theme theme={...}> and import core reset.css + astryx.css.',
46
+ '',
47
+ `Tip: \`${run} build "<idea>"\` is the fastest way in. For a neutral`,
48
+ `lookup of any component/doc/template, use \`${run} search <query>\`.`,
49
+ '',
50
+ ];
51
+ for (const l of lines) humanLog(l);
52
+ }
53
+
54
+ /**
55
+ * @param {import('commander').Command} program
56
+ */
57
+ export function registerBuild(program) {
58
+ program
59
+ .command('build [query]')
60
+ .description('Build a page: composition kit for an idea, or the workflow playbook (no args)')
61
+ .option('--type <domain>', 'Filter the kit to one domain (component|hook|template)')
62
+ .option('--limit <n>', 'Max candidates to draw from (default 60)')
63
+ .option('--detail', 'Verbose output (include import paths and match reason)')
64
+ .action(async (/** @type {string | undefined} */ query, /** @type {{type?: import('../../types/search').SearchDomain, limit?: string, detail?: boolean}} */ options) => {
65
+ const run = getCliInvocation();
66
+ const json = program.opts().json || false;
67
+
68
+ // No query → the playbook. Still routed through the API for the envelope.
69
+ if (!query || !String(query).trim()) {
70
+ const result = await buildApi(undefined, {cwd: process.cwd()});
71
+ if (json) return jsonOut(result.type, result.data);
72
+ printPlaybook(run);
73
+ return;
74
+ }
75
+
76
+ // Arg validation stays in the CLI.
77
+ let limit = 60;
78
+ if (options.limit != null) {
79
+ const parsed = Number.parseInt(options.limit, 10);
80
+ if (!Number.isFinite(parsed) || parsed <= 0) {
81
+ cliError(`Invalid --limit value "${options.limit}". Must be a positive integer.`);
82
+ return;
83
+ }
84
+ limit = parsed;
85
+ }
86
+
87
+ /** @type {import('../../types/build').BuildKitResponse} */
88
+ let result;
89
+ try {
90
+ result = /** @type {import('../../types/build').BuildKitResponse} */ (
91
+ await buildApi(query, {cwd: process.cwd(), type: options.type, limit})
92
+ );
93
+ } catch (e) {
94
+ const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
95
+ cliError(err.message, {suggestions: err.suggestions});
96
+ return;
97
+ }
98
+
99
+ if (json) return jsonOut(result.type, result.data);
100
+
101
+ const {query: q, hasResults, directMatch, pages, blocks, domain, frame, foundation} =
102
+ result.data;
103
+
104
+ if (!hasResults) {
105
+ humanLog('');
106
+ humanLog(`No matches for "${q}".`);
107
+ humanLog(`Try a broader term, or browse: ${run} component --list`);
108
+ humanLog('');
109
+ return;
110
+ }
111
+
112
+ const printItem = (/** @type {import('../../types/search').SearchResultEntry} */ r, /** @type {string} */ label) => {
113
+ const display = r.domain === 'template' && r.displayName ? r.displayName : r.name;
114
+ humanLog('');
115
+ humanLog(` [${label}] ${display}`);
116
+ if (r.description) humanLog(` ${r.description}`);
117
+ humanLog(` → ${formatCliCommand(r.command)}`);
118
+ if (options.detail) {
119
+ if (r.import) humanLog(` import: ${r.import}`);
120
+ humanLog(` match: ${r.reason} (score ${r.score})`);
121
+ }
122
+ };
123
+
124
+ humanLog('');
125
+ humanLog(`Building "${q}":`);
126
+
127
+ // START — the single recommended path.
128
+ humanLog('');
129
+ if (directMatch) {
130
+ humanLog(`START → Scaffold the \`${pages[0].name}\` page template, then adapt: ${run} template ${pages[0].name} ./src/App.tsx`);
131
+ } else if (pages.length) {
132
+ humanLog(`START → No exact page template. Use \`${pages[0].name}\` as a layout reference (${run} template ${pages[0].name} --skeleton) and compose the pieces below.`);
133
+ } else {
134
+ humanLog(`START → No page template fits. Frame with AppShell and compose the blocks + components below.`);
135
+ }
136
+
137
+ // PAGE
138
+ if (pages.length) {
139
+ humanLog('');
140
+ humanLog(directMatch ? 'PAGE TEMPLATE — direct match:' : 'CLOSEST PAGE TEMPLATES — layout reference:');
141
+ pages.forEach(p => printItem(p, directMatch ? 'page' : 'closest'));
142
+ }
143
+
144
+ // FRAME — always (the page shell).
145
+ humanLog('');
146
+ humanLog(`FRAME — page shell (always): ${frame.join(', ')}`);
147
+ humanLog(` full-page → AppShell; or Layout + SideNav/TopNav. ${run} component AppShell`);
148
+
149
+ // BLOCKS — idea-specific composed patterns.
150
+ if (blocks.length) {
151
+ humanLog('');
152
+ humanLog('BLOCKS — drop-in patterns that cover parts of it:');
153
+ blocks.forEach(b => printItem(b, 'block'));
154
+ }
155
+
156
+ // DOMAIN COMPONENTS — idea-specific atoms.
157
+ if (domain.length) {
158
+ humanLog('');
159
+ humanLog('DOMAIN COMPONENTS — specific to this idea:');
160
+ domain.forEach(c => printItem(c, c.domain === 'hook' ? 'hook' : 'component'));
161
+ }
162
+
163
+ // FOUNDATION — always (layout/typography/actions).
164
+ humanLog('');
165
+ humanLog(`FOUNDATION — always available (layout/text/actions): ${foundation.join(' ')}`);
166
+
167
+ // SETUP — so it renders / stays on-system.
168
+ humanLog('');
169
+ humanLog('SETUP — import "@astryxdesign/core/reset.css" + "astryx.css". No <div>/style for layout — use Stack/Grid + tokens.');
170
+ humanLog('');
171
+ });
172
+ }
@@ -0,0 +1,42 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Guardrail tests for the @astryxdesign/cli postinstall nudge (layer 2).
5
+ *
6
+ * Tests the pure decision matrix (shouldNudge) — nudges for a real dependency
7
+ * install when not set up; stays quiet in the monorepo/source, during npx's
8
+ * transient fetch (path _npx or npm_command=exec), and once set up.
9
+ */
10
+
11
+ import {describe, it, expect} from 'vitest';
12
+ import {shouldNudge} from '../../scripts/postinstall.mjs';
13
+
14
+ const DEP = '/proj/node_modules/@astryxdesign/cli/scripts/postinstall.mjs'; // real dep install
15
+ const NPX = '/Users/x/.npm/_npx/a1b2/node_modules/@astryxdesign/cli/scripts/postinstall.mjs';
16
+ const REPO = '/repo/packages/cli/scripts/postinstall.mjs'; // monorepo/source
17
+
18
+ describe('cli postinstall — shouldNudge', () => {
19
+ it('nudges for a real dependency install when not set up', () => {
20
+ expect(shouldNudge({scriptPath: DEP, npmCommand: 'install', isSetUp: false})).toBe(true);
21
+ });
22
+
23
+ it('quiet in the monorepo/source (not under node_modules)', () => {
24
+ expect(shouldNudge({scriptPath: REPO, npmCommand: 'install', isSetUp: false})).toBe(false);
25
+ });
26
+
27
+ it('quiet during npx transient install (path contains _npx)', () => {
28
+ expect(shouldNudge({scriptPath: NPX, npmCommand: 'install', isSetUp: false})).toBe(false);
29
+ });
30
+
31
+ it('quiet during npx (npm_command=exec) — avoids double-nudge before init', () => {
32
+ expect(shouldNudge({scriptPath: DEP, npmCommand: 'exec', isSetUp: false})).toBe(false);
33
+ });
34
+
35
+ it('quiet once the project is already set up', () => {
36
+ expect(shouldNudge({scriptPath: DEP, npmCommand: 'install', isSetUp: true})).toBe(false);
37
+ });
38
+
39
+ it('quiet with no script path (defensive)', () => {
40
+ expect(shouldNudge({})).toBe(false);
41
+ });
42
+ });
@@ -6,27 +6,47 @@
6
6
  * Global options: --detail full|compact|brief, --lang en|zh|dense
7
7
  */
8
8
 
9
- import {findCoreDir} from '../../utils/paths.mjs';
9
+ import {findCoreDir} from '../../../utils/paths.mjs';
10
10
  import {
11
11
  resolveImportPath,
12
- } from '../../lib/component-discovery.mjs';
12
+ } from '../../../lib/component-discovery.mjs';
13
13
  import {
14
14
  formatFull,
15
15
  formatCompact,
16
16
  formatBrief,
17
17
  formatProps,
18
18
  formatBriefAll,
19
- } from '../../lib/component-format.mjs';
20
- import {resolveTheme} from '../../lib/resolve-theme.mjs';
21
- import {getRunPrefix} from '../../utils/package-manager.mjs';
22
- import {jsonOut, humanLog} from '../../lib/json.mjs';
23
- import {cliError} from '../../lib/cli-error.mjs';
24
- import {ERROR_CODES} from '../../lib/error-codes.mjs';
25
- import {component as componentApi} from '../../api/component.mjs';
26
- import {findRelatedBlocks} from '../../api/template.mjs';
27
- import {Project} from '../../lib/project.mjs';
28
- import {warnOnIntegrationIssues} from '../../lib/integration-warnings.mjs';
19
+ } from '../../../lib/component-format.mjs';
20
+ import {resolveTheme} from '../../../lib/resolve-theme.mjs';
21
+ import {getCliInvocation} from '../../../utils/package-manager.mjs';
22
+ import {jsonOut, humanLog} from '../../../lib/json.mjs';
23
+ import {cliError} from '../../../lib/cli-error.mjs';
24
+ import {ERROR_CODES} from '../../../lib/error-codes.mjs';
25
+ import {component as componentApi} from '../../../api/component/component.mjs';
26
+ import {findRelatedBlocks} from '../../../api/template/template.mjs';
27
+ import {Project} from '../../../lib/project.mjs';
28
+ import {warnOnIntegrationIssues} from '../../../lib/integration-warnings.mjs';
29
29
 
30
+ /**
31
+ * The api layer's component() widens its return to `{type: string, data: unknown}`,
32
+ * so annotate the command-local result with the precise discriminated union from
33
+ * src/types/component to get narrowing + typed data.
34
+ *
35
+ * @typedef {(
36
+ * | import('../../../types/component').ComponentListResponse
37
+ * | import('../../../types/component').ComponentBriefResponse
38
+ * | import('../../../types/component').ComponentFullResponse
39
+ * | import('../../../types/component').ComponentDetailResponse
40
+ * | import('../../../types/component').ComponentDetailPropsResponse
41
+ * | import('../../../types/component').ComponentDetailSourceResponse
42
+ * | import('../../../types/component').ComponentDetailShowcaseResponse
43
+ * | import('../../../types/component').ComponentDetailBlocksResponse
44
+ * )} ComponentResult
45
+ */
46
+
47
+ /**
48
+ * @param {import('commander').Command} program
49
+ */
30
50
  export function registerComponent(program) {
31
51
  program
32
52
  .command('component [name]')
@@ -38,8 +58,8 @@ export function registerComponent(program) {
38
58
  .option('--showcase', 'Print showcase source code')
39
59
  .option('--blocks', 'List example blocks: showcase, examples, and related')
40
60
  .option('--package <name>', 'Scope lookup to an external package (e.g. @acme/xds-widgets)')
41
- .action(async (name, options) => {
42
- const run = getRunPrefix();
61
+ .action(async (/** @type {string | undefined} */ name, /** @type {{list?: boolean, category?: string, props?: boolean, source?: boolean, showcase?: boolean, blocks?: boolean, package?: string}} */ options) => {
62
+ const run = getCliInvocation();
43
63
  const zh = program.opts().zh || false;
44
64
  const dense = program.opts().dense || false;
45
65
  const lang = program.opts().lang || null;
@@ -67,9 +87,10 @@ export function registerComponent(program) {
67
87
  // Never let the nudge break the command.
68
88
  }
69
89
 
90
+ /** @type {ComponentResult} */
70
91
  let result;
71
92
  try {
72
- result = await componentApi(name, {
93
+ result = /** @type {ComponentResult} */ (await componentApi(name, {
73
94
  cwd: process.cwd(),
74
95
  list: options.list,
75
96
  category: options.category,
@@ -80,16 +101,19 @@ export function registerComponent(program) {
80
101
  blocks: options.blocks,
81
102
  detail,
82
103
  lang, zh, dense,
83
- });
104
+ }));
84
105
  } catch (e) {
85
- cliError(e.message, {suggestions: e.suggestions, code: e.code});
106
+ const err = /** @type {import('../../../api/error.mjs').AstryxError} */ (e);
107
+ cliError(err.message, {suggestions: err.suggestions, code: err.code});
86
108
  return;
87
109
  }
88
110
 
89
111
  if (json) return jsonOut(result.type, result.data);
90
112
 
91
113
  // ── Text output ────────────────────────────────────────────
92
- const coreDir = findCoreDir(process.cwd());
114
+ // The api layer already resolved against core (result exists), so core is
115
+ // present on this path; narrow away the null branch findCoreDir allows.
116
+ const coreDir = /** @type {string} */ (findCoreDir(process.cwd()));
93
117
  const themeData = resolveTheme(process.cwd());
94
118
 
95
119
  switch (result.type) {
@@ -101,6 +125,7 @@ export function registerComponent(program) {
101
125
  const CORE_PKG = '@astryxdesign/core';
102
126
  // Names that appear under more than one package across the whole
103
127
  // listing — these must always be package-qualified to disambiguate.
128
+ /** @type {Map<string, Set<string>>} */
104
129
  const nameCounts = new Map();
105
130
  for (const items of Object.values(result.data)) {
106
131
  for (const item of items) {
@@ -109,7 +134,9 @@ export function registerComponent(program) {
109
134
  nameCounts.set(item.name, set);
110
135
  }
111
136
  }
137
+ /** @param {string} n */
112
138
  const isCollision = n => (nameCounts.get(n)?.size ?? 0) > 1;
139
+ /** @param {import('../../../types/component').ComponentListEntry} item */
113
140
  const pkgSuffix = item => {
114
141
  if (item.package !== CORE_PKG) return ` [${item.package}]`;
115
142
  if (isCollision(item.name)) return ` [${item.package}]`;
@@ -142,7 +169,7 @@ export function registerComponent(program) {
142
169
  }
143
170
  humanLog('');
144
171
  humanLog(`Import from the path shown (e.g. import {Button} from '@astryxdesign/core/Button')`);
145
- humanLog(`Usage: ${run} astryx component <name>`);
172
+ humanLog(`Usage: ${run} component <name>`);
146
173
  humanLog('');
147
174
  }
148
175
  break;
@@ -165,7 +192,7 @@ export function registerComponent(program) {
165
192
  humanLog('');
166
193
  }
167
194
  humanLog(`Import from the path shown (e.g. import {Button} from '@astryxdesign/core/Button')`);
168
- humanLog(`Usage: ${run} astryx component <name>`);
195
+ humanLog(`Usage: ${run} component <name>`);
169
196
  humanLog('');
170
197
  break;
171
198
  }
@@ -251,8 +278,8 @@ export function registerComponent(program) {
251
278
 
252
279
  // Re-export lib functions for backward compatibility
253
280
  // (agent-docs.mjs, tests, and generate-skill-doc.sh import from here)
254
- export {discoverComponents, discoverExternalComponents, discoverExternalComponentsGrouped, findComponentReadme, findComponentSource, findExternalComponentDoc, resolveImportPath} from '../../lib/component-discovery.mjs';
255
- export {discoverExternalPackages} from '../../utils/paths.mjs';
256
- export {loadDocs} from '../../lib/component-loader.mjs';
257
- export {formatFull, formatCompact, formatBrief, formatProps, formatBriefAll} from '../../lib/component-format.mjs';
258
- export {levenshteinDistance, findClosestComponents, searchComponents} from '../../lib/string-utils.mjs';
281
+ export {discoverComponents, discoverExternalComponents, discoverExternalComponentsGrouped, findComponentReadme, findComponentSource, findExternalComponentDoc, resolveImportPath} from '../../../lib/component-discovery.mjs';
282
+ export {discoverExternalPackages} from '../../../utils/paths.mjs';
283
+ export {loadDocs} from '../../../lib/component-loader.mjs';
284
+ export {formatFull, formatCompact, formatBrief, formatProps, formatBriefAll} from '../../../lib/component-format.mjs';
285
+ export {levenshteinDistance, findClosestComponents, searchComponents} from '../../../lib/string-utils.mjs';
@@ -10,7 +10,7 @@ import {
10
10
  findIntegrationComponentDoc,
11
11
  findIntegrationComponentSource,
12
12
  CORE_PACKAGE,
13
- } from '../lib/component-discovery.mjs';
13
+ } from '../../lib/component-discovery.mjs';
14
14
 
15
15
  // The api `component()` reads integrations via Project.load(). In the vitest
16
16
  // environment, Vite's `server.fs.allow` only permits loading modules from
@@ -20,12 +20,12 @@ import {
20
20
  // produces) while keeping the integration's `components` dir on disk under
21
21
  // node_modules so its `.doc.mjs` files load normally.
22
22
  const projectLoadMock = vi.fn();
23
- vi.mock('../lib/project.mjs', () => ({
23
+ vi.mock('../../lib/project.mjs', () => ({
24
24
  Project: {load: (...args) => projectLoadMock(...args)},
25
25
  }));
26
26
 
27
27
  // Import the api AFTER the mock is registered.
28
- const {component} = await import('../api/component.mjs');
28
+ const {component} = await import('../../api/component/component.mjs');
29
29
 
30
30
  let tmpDir;
31
31
 
@@ -4,7 +4,7 @@ import {describe, it, expect, beforeEach, afterEach} from 'vitest';
4
4
  import * as fs from 'node:fs';
5
5
  import * as path from 'node:path';
6
6
  import * as os from 'node:os';
7
- import {component} from '../api/component.mjs';
7
+ import {component} from '../../api/component/component.mjs';
8
8
 
9
9
  // These tests create a minimal monorepo fixture with:
10
10
  // - packages/core (symlinked to real @astryxdesign/core for loadDocs compatibility)
@@ -1,8 +1,8 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
3
  import {describe, it, expect} from 'vitest';
4
- import {component} from '../api/component.mjs';
5
- import {findShowcase, findRelatedBlocks} from '../api/template.mjs';
4
+ import {component} from '../../api/component/component.mjs';
5
+ import {findShowcase, findRelatedBlocks} from '../../api/template/template.mjs';
6
6
 
7
7
  const CWD = {cwd: '.'};
8
8
 
@@ -10,27 +10,38 @@
10
10
  * astryx discover searchterm Search across all packages
11
11
  */
12
12
 
13
- import {formatFull, formatBrief, formatCompact} from '../lib/component-format.mjs';
14
- import {jsonOut, humanLog} from '../lib/json.mjs';
15
- import {cliError} from '../lib/cli-error.mjs';
16
- import {discover as discoverApi} from '../api/discover.mjs';
13
+ import {formatFull, formatBrief, formatCompact} from '../../lib/component-format.mjs';
14
+ import {jsonOut, humanLog} from '../../lib/json.mjs';
15
+ import {cliError} from '../../lib/cli-error.mjs';
16
+ import {discover as discoverApi} from '../../api/discover/discover.mjs';
17
+ import {getCliInvocation} from '../../utils/package-manager.mjs';
17
18
 
19
+ /**
20
+ * @param {import('commander').Command} program
21
+ */
18
22
  export function registerDiscover(program) {
19
23
  program
20
24
  .command('discover [query]')
21
25
  .description('Discover external packages and components')
22
26
  .option('--components', 'List components only')
23
- .action(async (query, options) => {
27
+ .action(
28
+ /**
29
+ * @param {string | undefined} query
30
+ * @param {{components?: boolean}} options
31
+ */
32
+ async (query, options) => {
24
33
  const detail = program.opts().detail || 'full';
25
34
  const json = program.opts().json || false;
26
35
  const lang = program.opts().lang || null;
27
36
  const zh = program.opts().zh || false;
37
+ const run = getCliInvocation();
28
38
 
29
39
  let result;
30
40
  try {
31
41
  result = await discoverApi(query, {components: options.components, lang, zh});
32
42
  } catch (e) {
33
- cliError(e.message, {suggestions: e.suggestions, code: e.code});
43
+ const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
44
+ cliError(err.message, {suggestions: err.suggestions, code: err.code});
34
45
  return;
35
46
  }
36
47
 
@@ -38,7 +49,7 @@ export function registerDiscover(program) {
38
49
  // Forward optional meta (e.g. configured flag for discover.list) as a
39
50
  // sibling of data via jsonOut, so the envelope still carries
40
51
  // apiVersion and goes through the single sanctioned emit path.
41
- return jsonOut(result.type, result.data, result.meta);
52
+ return jsonOut(result.type, result.data, 'meta' in result ? result.meta : undefined);
42
53
  }
43
54
 
44
55
  switch (result.type) {
@@ -80,9 +91,9 @@ export function registerDiscover(program) {
80
91
  humanLog('');
81
92
  }
82
93
  humanLog('Usage:');
83
- humanLog(' astryx discover <package> Browse a package');
84
- humanLog(' astryx discover <package>/Component View component docs');
85
- humanLog(' astryx discover <search> Search all packages');
94
+ humanLog(` ${run} discover <package> Browse a package`);
95
+ humanLog(` ${run} discover <package>/Component View component docs`);
96
+ humanLog(` ${run} discover <search> Search all packages`);
86
97
  humanLog('');
87
98
  }
88
99
  break;
@@ -99,7 +110,7 @@ export function registerDiscover(program) {
99
110
  humanLog('');
100
111
  for (const comp of result.data.components) humanLog(' ' + comp);
101
112
  humanLog('');
102
- humanLog('Usage: astryx discover ' + result.data.name + '/<ComponentName>');
113
+ humanLog(`Usage: ${run} discover ` + result.data.name + '/<ComponentName>');
103
114
  humanLog('');
104
115
  break;
105
116
  }
@@ -122,7 +133,7 @@ export function registerDiscover(program) {
122
133
  humanLog('Found ' + result.data.matches.length + ' matches for "' + result.data.query + '":');
123
134
  humanLog('');
124
135
  for (const m of result.data.matches) {
125
- humanLog(' astryx discover ' + m.package + '/' + m.component);
136
+ humanLog(` ${run} discover ` + m.package + '/' + m.component);
126
137
  }
127
138
  humanLog('');
128
139
  break;
@@ -12,13 +12,18 @@
12
12
  * astryx docs <topic> <section> Print one section
13
13
  */
14
14
 
15
- import {getRunPrefix} from '../utils/package-manager.mjs';
16
- import {jsonOut, humanLog} from '../lib/json.mjs';
17
- import {cliError} from '../lib/cli-error.mjs';
18
- import {docs as docsApi} from '../api/docs.mjs';
15
+ import {getCliInvocation} from '../../utils/package-manager.mjs';
16
+ import {jsonOut, humanLog} from '../../lib/json.mjs';
17
+ import {cliError} from '../../lib/cli-error.mjs';
18
+ import {docs as docsApi} from '../../api/docs/docs.mjs';
19
19
 
20
20
  // ─── Formatting ──────────────────────────────────────────────────────────────
21
21
 
22
+ /**
23
+ * @param {string[]} headers
24
+ * @param {string[][]} rows
25
+ * @returns {string}
26
+ */
22
27
  function formatTable(headers, rows) {
23
28
  const widths = headers.map((h, i) =>
24
29
  Math.max(h.length, ...rows.map(r => (r[i] || '').length)),
@@ -31,15 +36,28 @@ function formatTable(headers, rows) {
31
36
  return `${head}\n${sep}\n${body}`;
32
37
  }
33
38
 
39
+ /**
40
+ * @param {string[]} headers
41
+ * @param {string[][]} rows
42
+ * @returns {string}
43
+ */
34
44
  function formatTableCompact(headers, rows) {
35
45
  return rows.map(r => r.join(' = ')).join('\n');
36
46
  }
37
47
 
48
+ /**
49
+ * @param {import('../../../core/src/docs-types').ContentBlock} block
50
+ * @param {'full' | 'compact' | 'brief'} detail
51
+ * @returns {string | null}
52
+ */
38
53
  function formatBlock(block, detail) {
39
54
  switch (block.type) {
40
55
  case 'prose':
41
56
  return block.text;
42
57
 
58
+ case 'heading':
59
+ return `${'#'.repeat(block.level || 3)} ${block.text}`;
60
+
43
61
  case 'code':
44
62
  if (detail === 'compact' || detail === 'brief') return null;
45
63
  {
@@ -57,7 +75,7 @@ function formatBlock(block, detail) {
57
75
  return formatTable(block.headers, block.rows);
58
76
 
59
77
  case 'list': {
60
- const prefix = block.style === 'ordered' ? (i) => `${i + 1}. `
78
+ const prefix = block.style === 'ordered' ? (/** @type {number} */ i) => `${i + 1}. `
61
79
  : block.style === 'dont' ? () => '❌ '
62
80
  : block.style === 'do' ? () => '✓ '
63
81
  : () => '- ';
@@ -69,6 +87,11 @@ function formatBlock(block, detail) {
69
87
  }
70
88
  }
71
89
 
90
+ /**
91
+ * @param {import('../../../core/src/docs-types').ReferenceSection} section
92
+ * @param {'full' | 'compact' | 'brief'} detail
93
+ * @returns {string}
94
+ */
72
95
  function formatSection(section, detail) {
73
96
  const blocks = section.content
74
97
  .map(b => formatBlock(b, detail))
@@ -83,6 +106,11 @@ function formatSection(section, detail) {
83
106
  return `${heading}\n\n${blocks.join('\n\n')}`;
84
107
  }
85
108
 
109
+ /**
110
+ * @param {import('../../../core/src/docs-types').ReferenceDoc} docs
111
+ * @param {'full' | 'compact' | 'brief'} detail
112
+ * @returns {string}
113
+ */
86
114
  function formatReferenceFull(docs, detail) {
87
115
  if (detail === 'brief') {
88
116
  const header = `${docs.title}: ${docs.description}`;
@@ -100,12 +128,15 @@ function formatReferenceFull(docs, detail) {
100
128
 
101
129
  // ─── Command ─────────────────────────────────────────────────────────────────
102
130
 
131
+ /**
132
+ * @param {import('commander').Command} program
133
+ */
103
134
  export function registerDocs(program) {
104
135
  program
105
136
  .command('docs [topic] [section]')
106
137
  .description('Print reference docs')
107
- .action(async (topic, section) => {
108
- const run = getRunPrefix();
138
+ .action(async (/** @type {string | undefined} */ topic, /** @type {string | undefined} */ section) => {
139
+ const run = getCliInvocation();
109
140
  const lang = program.opts().lang || null;
110
141
  const zh = program.opts().zh || false;
111
142
  const dense = program.opts().dense || false;
@@ -118,7 +149,8 @@ export function registerDocs(program) {
118
149
  } catch (e) {
119
150
  // docs API throws structured errors with {name, reason} suggestions —
120
151
  // pass them through untouched so the CLI envelope matches the API.
121
- cliError(e.message, {suggestions: e.suggestions || [], code: e.code});
152
+ const err = /** @type {import('../../api/error.mjs').AstryxError} */ (e);
153
+ cliError(err.message, {suggestions: err.suggestions || [], code: err.code});
122
154
  return;
123
155
  }
124
156
 
@@ -130,8 +162,8 @@ export function registerDocs(program) {
130
162
  for (const entry of result.data) {
131
163
  humanLog(` ${entry.topic.padEnd(14)} ${entry.description}`);
132
164
  }
133
- humanLog(`\nUsage: ${run} astryx docs <topic>`);
134
- humanLog(` ${run} astryx docs <topic> <section>\n`);
165
+ humanLog(`\nUsage: ${run} docs <topic>`);
166
+ humanLog(` ${run} docs <topic> <section>\n`);
135
167
  break;
136
168
  }
137
169
 
@@ -71,7 +71,7 @@ describe('hyphenated doc filenames', () => {
71
71
  });
72
72
 
73
73
  it('returns docs.detail via API for hyphenated topic', async () => {
74
- const {docs: docsApi} = await import('../api/docs.mjs');
74
+ const {docs: docsApi} = await import('../../api/docs/docs.mjs');
75
75
  const result = await docsApi('getting-started');
76
76
  expect(result.type).toBe('docs.detail');
77
77
  expect(result.data).toBeDefined();
@@ -10,8 +10,8 @@
10
10
  * as a CI gate.
11
11
  */
12
12
 
13
- import {runChecks} from '../api/doctor.mjs';
14
- import {jsonOut, humanLog} from '../lib/json.mjs';
13
+ import {runChecks} from '../../api/doctor/doctor.mjs';
14
+ import {jsonOut, humanLog} from '../../lib/json.mjs';
15
15
 
16
16
  /** Status → human glyph (monochrome, matching the rest of the CLI). */
17
17
  const GLYPH = {
@@ -23,7 +23,7 @@ const GLYPH = {
23
23
 
24
24
  /**
25
25
  * Render the report as a human-readable checklist.
26
- * @param {import('../api/doctor.mjs').DoctorReport} report
26
+ * @param {import('../../api/doctor/doctor.mjs').DoctorReport} report
27
27
  */
28
28
  function printHuman(report) {
29
29
  humanLog('astryx doctor — diagnosing your setup\n');