@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
@@ -19,13 +19,20 @@
19
19
  * // { type: 'hook.detail', data: { name: 'useMediaQuery', ... } }
20
20
  */
21
21
 
22
- export {component} from './component.mjs';
23
- export {docs} from './docs.mjs';
24
- export {blog} from './blog.mjs';
25
- export {discover} from './discover.mjs';
26
- export {template} from './template.mjs';
27
- export {themeAdd, listThemes} from './theme-add.mjs';
28
- export {hook} from './hook.mjs';
29
- export {search} from './search.mjs';
30
- export {doctor} from './doctor.mjs';
22
+ export {component} from './component/component.mjs';
23
+ export {docs} from './docs/docs.mjs';
24
+ export {blog} from './blog/blog.mjs';
25
+ export {discover} from './discover/discover.mjs';
26
+ export {template} from './template/template.mjs';
27
+ export {themeAdd, listThemes} from './theme/theme-add.mjs';
28
+ export {hook} from './hook/hook.mjs';
29
+ export {search} from './search/search.mjs';
30
+ export {build} from './build/build.mjs';
31
+ export {swizzle} from './swizzle/swizzle.mjs';
32
+ export {doctor} from './doctor/doctor.mjs';
33
+ export {layoutExpand, layoutCheck, layoutGrammar} from './layout/layout.mjs';
34
+ export {
35
+ validateIntegration,
36
+ summarizeIssues,
37
+ } from './integration/validate-integration.mjs';
31
38
  export {AstryxError} from './error.mjs';
@@ -28,13 +28,13 @@ import {
28
28
  findManifestPaths,
29
29
  loadManifestObject,
30
30
  resolvePackageDir,
31
- } from '../lib/integrations.mjs';
32
- import {discoverIntegrationCodemods} from '../codemods/integration-discovery.mjs';
33
- import {discoverIntegrationTemplatesForOne} from './template.mjs';
34
- import * as componentDiscovery from '../lib/component-discovery.mjs';
31
+ } from '../../lib/integrations.mjs';
32
+ import {discoverIntegrationCodemods} from '../../codemods/integration-discovery.mjs';
33
+ import {discoverIntegrationTemplatesForOne} from '../template/template.mjs';
34
+ import * as componentDiscovery from '../../lib/component-discovery.mjs';
35
35
 
36
36
  /**
37
- * @typedef {import('../types/integration').AstryxIntegrationIssue} Issue
37
+ * @typedef {import('../../types/integration').AstryxIntegrationIssue} Issue
38
38
  */
39
39
 
40
40
  /**
@@ -75,7 +75,8 @@ function error(code, message) {
75
75
  * @param {Issue[]} issues
76
76
  */
77
77
  function checkRoots(resolved, issues) {
78
- for (const kind of ['components', 'templates', 'codemods']) {
78
+ const kinds = /** @type {const} */ (['components', 'templates', 'codemods']);
79
+ for (const kind of kinds) {
79
80
  const root = resolved[kind];
80
81
  if (root == null) continue;
81
82
  if (!fs.existsSync(root)) {
@@ -93,7 +94,7 @@ function checkRoots(resolved, issues) {
93
94
  * Validate the integration's codemods via the landed discovery. Discovery is
94
95
  * strict (throws on bad export / duplicate id); we convert any throw into an
95
96
  * `invalid_codemod` error.
96
- * @param {object} integration loaded-integration-shaped object
97
+ * @param {import('../../lib/integrations.mjs').LoadedIntegration} integration loaded-integration-shaped object
97
98
  * @param {Issue[]} issues
98
99
  */
99
100
  async function checkCodemods(integration, issues) {
@@ -101,14 +102,14 @@ async function checkCodemods(integration, issues) {
101
102
  try {
102
103
  await discoverIntegrationCodemods([integration]);
103
104
  } catch (err) {
104
- issues.push(error('invalid_codemod', err.message));
105
+ issues.push(error('invalid_codemod', /** @type {any} */ (err).message));
105
106
  }
106
107
  }
107
108
 
108
109
  /**
109
110
  * Validate the integration's templates via the landed discovery. Per-template
110
111
  * problems are reported as `invalid_template` errors.
111
- * @param {object} integration loaded-integration-shaped object
112
+ * @param {import('../../lib/integrations.mjs').LoadedIntegration} integration loaded-integration-shaped object
112
113
  * @param {Issue[]} issues
113
114
  */
114
115
  async function checkTemplates(integration, issues) {
@@ -119,7 +120,7 @@ async function checkTemplates(integration, issues) {
119
120
  issues.push(error('invalid_template', e.message));
120
121
  }
121
122
  } catch (err) {
122
- issues.push(error('invalid_template', err.message));
123
+ issues.push(error('invalid_template', /** @type {any} */ (err).message));
123
124
  }
124
125
  }
125
126
 
@@ -132,7 +133,7 @@ async function checkTemplates(integration, issues) {
132
133
  * `discoverIntegrationComponents` returns ownership records and does not throw
133
134
  * on a missing same-stem source — it records `sourcePath: null`. We surface
134
135
  * each such record as an `invalid_component` error.
135
- * @param {object} integration loaded-integration-shaped object
136
+ * @param {import('../../lib/integrations.mjs').LoadedIntegration} integration loaded-integration-shaped object
136
137
  * @param {Issue[]} issues
137
138
  */
138
139
  async function checkComponents(integration, issues) {
@@ -152,13 +153,13 @@ async function checkComponents(integration, issues) {
152
153
  }
153
154
  }
154
155
  } catch (err) {
155
- issues.push(error('invalid_component', err.message));
156
+ issues.push(error('invalid_component', /** @type {any} */ (err).message));
156
157
  }
157
158
  }
158
159
 
159
160
  /**
160
161
  * Run every contribution validator against a loaded-integration-shaped object.
161
- * @param {object} integration
162
+ * @param {import('../../lib/integrations.mjs').LoadedIntegration} integration
162
163
  * @param {Issue[]} issues
163
164
  */
164
165
  async function runContributionChecks(integration, issues) {
@@ -181,7 +182,7 @@ async function runContributionChecks(integration, issues) {
181
182
  * contribution checks (roots + codemods/templates/components) because those can
182
183
  * regress independently of the manifest (a deleted directory, a broken template).
183
184
  *
184
- * @param {object} loaded loaded-integration-shaped object
185
+ * @param {import('../../lib/integrations.mjs').LoadedIntegration} loaded loaded-integration-shaped object
185
186
  * @returns {Promise<Issue[]>}
186
187
  */
187
188
  export async function validateLoadedIntegration(loaded) {
@@ -210,6 +211,7 @@ export async function validateLoadedIntegration(loaded) {
210
211
  async function validateAtPackageDir(packageDir, identity) {
211
212
  /** @type {Issue[]} */
212
213
  const issues = [];
214
+ /** @type {ValidateResult} */
213
215
  const result = {
214
216
  found: true,
215
217
  name: identity.name,
@@ -254,10 +256,11 @@ async function validateAtPackageDir(packageDir, identity) {
254
256
  `Integration manifest (${path.basename(manifestFile)})`,
255
257
  );
256
258
  } catch (err) {
257
- issues.push(error('invalid_manifest', err.message));
259
+ issues.push(error('invalid_manifest', /** @type {any} */ (err).message));
258
260
  return result;
259
261
  }
260
262
 
263
+ /** @param {string | null | undefined} value */
261
264
  const resolveRoot = value =>
262
265
  value == null ? undefined : path.resolve(packageDir, value);
263
266
 
@@ -300,6 +303,7 @@ export async function validateLocalIntegration(cwd = process.cwd()) {
300
303
  return {found: false, issues: []};
301
304
  }
302
305
 
306
+ /** @type {{name?: string, version?: string}} */
303
307
  let pkg = {};
304
308
  try {
305
309
  pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
@@ -323,6 +327,7 @@ export async function validateInstalledIntegration(spec, cwd = process.cwd()) {
323
327
  const packageDir = resolvePackageDir(spec, cwd);
324
328
  const pkgJsonPath = path.join(packageDir, 'package.json');
325
329
 
330
+ /** @type {{name?: string, version?: string}} */
326
331
  let pkg;
327
332
  try {
328
333
  pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
@@ -346,6 +351,34 @@ export async function validateInstalledIntegration(spec, cwd = process.cwd()) {
346
351
  });
347
352
  }
348
353
 
354
+ /**
355
+ * Unified entry: validate the LOCAL integration (no `pkg`) or an INSTALLED one
356
+ * (`pkg` given) and return the `integration.validate` envelope. The no-manifest
357
+ * local case is guidance, not an error — it comes back with `name: null` and no
358
+ * issues so the CLI can print a hint and stay exit-0.
359
+ *
360
+ * This is the seam that keeps the CLI a thin wrapper: the command handler calls
361
+ * this and only chooses how to render (human vs --json) + the exit code.
362
+ *
363
+ * @param {string} [pkg] installed package name; omit to validate the cwd package
364
+ * @param {{cwd?: string}} [options]
365
+ * @returns {Promise<import('../../types/validate-integration').ValidateIntegrationResponse>}
366
+ */
367
+ export async function validateIntegration(pkg, options = {}) {
368
+ const {cwd = process.cwd()} = options;
369
+ const result = pkg
370
+ ? await validateInstalledIntegration(pkg, cwd)
371
+ : await validateLocalIntegration(cwd);
372
+ return {
373
+ type: 'integration.validate',
374
+ data: {
375
+ name: result.found ? result.name ?? null : null,
376
+ version: result.found ? result.version ?? null : null,
377
+ issues: result.issues,
378
+ },
379
+ };
380
+ }
381
+
349
382
  /**
350
383
  * Summarize issues by severity.
351
384
  * @param {Issue[]} issues
@@ -24,7 +24,7 @@ let tmpDir;
24
24
  // Absolute file:// URL to the codemod helper so codemod modules in the temp
25
25
  // package can import createCodemod without node_modules wiring.
26
26
  const codemodModuleUrl = pathToFileURL(
27
- path.resolve(process.cwd(), 'packages/cli/src/codemod.mjs'),
27
+ path.resolve(process.cwd(), 'packages/cli/authoring/codemod.mjs'),
28
28
  ).href;
29
29
 
30
30
  beforeEach(() => {
@@ -16,16 +16,29 @@
16
16
 
17
17
  import * as fs from 'node:fs';
18
18
  import * as path from 'node:path';
19
- import {AstryxError} from './error.mjs';
20
- import {ERROR_CODES} from '../lib/error-codes.mjs';
21
- import {assertWithin, isFilePathArg, PathSafetyError} from '../utils/path-safety.mjs';
22
- import {parse, detectForm, XLEParseError} from '../lib/xle/parse.mjs';
23
- import {validate} from '../lib/xle/validate.mjs';
24
- import {expand} from '../lib/xle/expand.mjs';
25
- import {toCompact, toOutline} from '../lib/xle/print.mjs';
26
- import {buildRegistry, ALIAS_TABLE} from '../lib/xle/registry.mjs';
27
- import {discoverTemplates, stripTemplateAssetRefs} from './template.mjs';
28
- import {Project} from '../lib/project.mjs';
19
+ import {AstryxError} from '../error.mjs';
20
+ import {ERROR_CODES} from '../../lib/error-codes.mjs';
21
+ import {assertWithin, isFilePathArg, PathSafetyError} from '../../utils/path-safety.mjs';
22
+ import {parse, detectForm, XLEParseError} from '../../lib/xle/parse.mjs';
23
+ import {validate} from '../../lib/xle/validate.mjs';
24
+ import {expand} from '../../lib/xle/expand.mjs';
25
+ import {toCompact, toOutline} from '../../lib/xle/print.mjs';
26
+ import {buildRegistry, ALIAS_TABLE} from '../../lib/xle/registry.mjs';
27
+ import {discoverTemplates, stripTemplateAssetRefs} from '../template/template.mjs';
28
+ import {Project} from '../../lib/project.mjs';
29
+
30
+ /**
31
+ * @typedef {object} LayoutBlock
32
+ * @property {string} dirName
33
+ * @property {string} name
34
+ * @property {'template'|'component'} kind
35
+ * @property {string} [type]
36
+ * @property {string} [description]
37
+ * @property {string} [category]
38
+ * @property {string} [importPath]
39
+ * @property {string} [filePath]
40
+ * @property {boolean} [isDefault]
41
+ */
29
42
 
30
43
  /**
31
44
  * The catalog a `{hint}` can resolve to: template blocks (spliced inline) plus
@@ -33,8 +46,12 @@ import {Project} from '../lib/project.mjs';
33
46
  * `experimental.xle.components` (imported by name). App components are how XLE
34
47
  * reaches domain pieces — the KpiCard/chart/drawer set that the
35
48
  * @astryxdesign/core registry can't see.
49
+ *
50
+ * @param {string} cwd
51
+ * @returns {Promise<LayoutBlock[]>}
36
52
  */
37
53
  async function loadBlocks(cwd) {
54
+ /** @type {LayoutBlock[]} */
38
55
  const blocks = [];
39
56
  try {
40
57
  const all = await discoverTemplates(cwd);
@@ -44,6 +61,7 @@ async function loadBlocks(cwd) {
44
61
  }
45
62
  try {
46
63
  const project = await Project.load(cwd);
64
+ /** @type {Record<string, {from?: string, description?: string, default?: boolean}>} */
47
65
  const components = project.config.experimental?.xle?.components ?? {};
48
66
  for (const [name, spec] of Object.entries(components)) {
49
67
  const importPath = spec.from;
@@ -65,11 +83,17 @@ async function loadBlocks(cwd) {
65
83
  return blocks;
66
84
  }
67
85
 
86
+ /** @param {string} name */
68
87
  const normKey = (name) => name.toLowerCase().replace(/[^a-z0-9]/g, '');
69
88
 
70
- /** Collect the block names referenced by {hints} anywhere in the doc. */
89
+ /**
90
+ * Collect the block names referenced by {hints} anywhere in the doc.
91
+ * @param {import('../../lib/xle/xle-ast').XLEDoc} doc
92
+ */
71
93
  function collectHintNames(doc) {
94
+ /** @type {Set<string>} */
72
95
  const names = new Set();
96
+ /** @param {import('../../lib/xle/xle-ast').XLEItem} node */
73
97
  const visitNode = (node) => {
74
98
  if (!node || node.kind === 'group') {
75
99
  (node?.children || []).forEach(visit);
@@ -77,11 +101,17 @@ function collectHintNames(doc) {
77
101
  }
78
102
  if (node.hint?.block) names.add(node.hint.block.name);
79
103
  for (const slot of node.slots || []) {
80
- if (slot.value?.hint?.block) names.add(slot.value.hint.block.name);
81
- (slot.value?.subexpr || []).forEach(visit);
104
+ const value = slot.value;
105
+ if (value && typeof value === 'object' && 'hint' in value && value.hint?.block) {
106
+ names.add(value.hint.block.name);
107
+ }
108
+ if (value && typeof value === 'object' && 'subexpr' in value) {
109
+ (value.subexpr || []).forEach(visit);
110
+ }
82
111
  }
83
112
  (node.children || []).forEach(visit);
84
113
  };
114
+ /** @param {import('../../lib/xle/xle-ast').XLEItem} item */
85
115
  const visit = (item) => (item?.kind === 'group' ? item.children.forEach(visit) : visitNode(item));
86
116
  doc.roots.forEach(visit);
87
117
  doc.overlays.forEach(visit);
@@ -92,24 +122,30 @@ function collectHintNames(doc) {
92
122
  * Build the blockModules map expand() needs: import-mode for app components,
93
123
  * splice-mode (reading + asset-stripping the block source) for template blocks.
94
124
  * Only blocks actually referenced are read.
125
+ *
126
+ * @param {import('../../lib/xle/xle-ast').XLEDoc} doc
127
+ * @param {LayoutBlock[]} blocks
128
+ * @returns {Map<string, import('../../lib/xle/xle-ast').BlockModule>}
95
129
  */
96
130
  function buildBlockModules(doc, blocks) {
97
131
  const referenced = collectHintNames(doc);
98
132
  if (referenced.size === 0) return new Map();
99
133
  const byKey = new Map(blocks.map(b => [normKey(b.dirName), b]));
134
+ /** @type {Map<string, import('../../lib/xle/xle-ast').BlockModule>} */
100
135
  const modules = new Map();
101
136
  for (const name of referenced) {
102
137
  const block = byKey.get(normKey(name));
103
138
  if (!block) continue;
104
139
  if (block.kind === 'component') {
105
- modules.set(name, {mode: 'import', componentName: block.name, importPath: block.importPath, isDefault: block.isDefault});
140
+ modules.set(name, /** @type {import('../../lib/xle/xle-ast').BlockModule} */ (/** @type {unknown} */ ({mode: 'import', componentName: block.name, importPath: block.importPath, isDefault: block.isDefault})));
106
141
  } else if (block.filePath && fs.existsSync(block.filePath)) {
107
- modules.set(name, {mode: 'splice', componentName: block.dirName, source: stripTemplateAssetRefs(fs.readFileSync(block.filePath, 'utf-8'))});
142
+ modules.set(name, /** @type {import('../../lib/xle/xle-ast').BlockModule} */ ({mode: 'splice', componentName: block.dirName, source: stripTemplateAssetRefs(fs.readFileSync(block.filePath, 'utf-8'))}));
108
143
  }
109
144
  }
110
145
  return modules;
111
146
  }
112
147
 
148
+ /** @param {import('../../lib/xle/xle-ast').RawIssue} issue */
113
149
  function formatIssue(issue) {
114
150
  const where = issue.line != null ? `line ${issue.line}: ` : '';
115
151
  return `${where}${issue.message}`;
@@ -118,11 +154,17 @@ function formatIssue(issue) {
118
154
  /**
119
155
  * Parse + validate, throwing structured XDSErrors on failure.
120
156
  * Returns {doc, registry, blocks, warnings}.
157
+ *
158
+ * @param {string} expression
159
+ * @param {{form?: 'compact'|'outline'|'auto', loose?: boolean, cwd?: string}} [options]
121
160
  */
122
161
  async function analyze(expression, {form = 'auto', loose = false, cwd = process.cwd()} = {}) {
123
- const registry = await buildRegistry({cwd});
162
+ const registry = /** @type {import('../../lib/xle/xle-ast').Registry} */ (
163
+ /** @type {unknown} */ (await buildRegistry({cwd}))
164
+ );
124
165
  const blocks = await loadBlocks(cwd);
125
166
 
167
+ /** @type {import('../../lib/xle/xle-ast').XLEDoc} */
126
168
  let doc;
127
169
  try {
128
170
  doc = parse(expression, {form});
@@ -212,6 +254,9 @@ export async function layoutExpand(expression, options = {}) {
212
254
  /**
213
255
  * `astryx layout check "<expr>" [--form compact|outline]`
214
256
  * Validates without expanding; echoes both canonical surfaces.
257
+ *
258
+ * @param {string} expression
259
+ * @param {{form?: 'compact'|'outline'|'auto', loose?: boolean, cwd?: string}} [options]
215
260
  */
216
261
  export async function layoutCheck(expression, options = {}) {
217
262
  const {form = 'auto', loose = false, cwd = process.cwd()} = options;
@@ -233,16 +278,20 @@ export async function layoutCheck(expression, options = {}) {
233
278
  /**
234
279
  * `astryx layout grammar` — the agent cheatsheet, with the alias table
235
280
  * generated from this branch's registry (never hand-maintained).
281
+ *
282
+ * @param {{cwd?: string}} [options]
236
283
  */
237
284
  export async function layoutGrammar(options = {}) {
238
285
  const {cwd = process.cwd()} = options;
239
286
  const registry = await buildRegistry({cwd});
240
287
 
288
+ /** @type {string[]} */
241
289
  const aliasLines = [];
290
+ /** @type {Map<string, string[]>} */
242
291
  const byTarget = new Map();
243
292
  for (const [alias, target] of registry.aliases) {
244
293
  if (!byTarget.has(target)) byTarget.set(target, []);
245
- byTarget.get(target).push(alias);
294
+ byTarget.get(target)?.push(alias);
246
295
  }
247
296
  for (const [target, aliases] of [...byTarget.entries()].sort(([a], [b]) => a.localeCompare(b))) {
248
297
  aliasLines.push(`${aliases.join('/')}=${target}`);
@@ -13,7 +13,7 @@ import {tmpdir} from 'node:os';
13
13
  import {join} from 'node:path';
14
14
  import ts from 'typescript';
15
15
  import {layoutExpand, layoutCheck, layoutGrammar} from './layout.mjs';
16
- import {buildRegistry} from '../lib/xle/registry.mjs';
16
+ import {buildRegistry} from '../../lib/xle/registry.mjs';
17
17
 
18
18
  // The registry imports ~140 .doc.mjs modules on first use; under full-suite
19
19
  // parallel load that can exceed the default 5s test timeout. Warm it once.
@@ -33,19 +33,34 @@
33
33
  import * as fs from 'node:fs';
34
34
  import * as path from 'node:path';
35
35
  import {pathToFileURL} from 'node:url';
36
- import {findCoreDir, CLI_ROOT} from '../utils/paths.mjs';
36
+ import {findCoreDir, CLI_ROOT} from '../../utils/paths.mjs';
37
37
  import {
38
38
  discoverComponents,
39
39
  findComponentReadme,
40
40
  resolveImportPath,
41
- } from '../lib/component-discovery.mjs';
42
- import {discoverHooks, findHookDoc} from '../lib/hook-discovery.mjs';
43
- import {levenshteinDistance} from '../lib/string-utils.mjs';
44
- import {discoverTemplates, extractComponents} from './template.mjs';
45
- import {AstryxError} from './error.mjs';
41
+ } from '../../lib/component-discovery.mjs';
42
+ import {discoverHooks, findHookDoc} from '../../lib/hook-discovery.mjs';
43
+ import {levenshteinDistance} from '../../lib/string-utils.mjs';
44
+ import {discoverTemplates, extractComponents} from '../template/template.mjs';
45
+ import {AstryxError} from '../error.mjs';
46
46
 
47
47
  const DOCS_DIR = path.join(CLI_ROOT, 'docs');
48
48
 
49
+ /**
50
+ * A search candidate gathered from one content domain. Extra underscore-
51
+ * prefixed fields carry domain-specific payload used only by {@link toResult}.
52
+ * @typedef {object} Candidate
53
+ * @property {'component'|'hook'|'doc'|'template'} domain
54
+ * @property {string} name
55
+ * @property {string[]} [keywords]
56
+ * @property {string} [description]
57
+ * @property {string[]} [prose]
58
+ * @property {string} [_import]
59
+ * @property {string} [_title]
60
+ * @property {string} [_displayName]
61
+ * @property {'page'|'block'} [_kind]
62
+ */
63
+
49
64
  /**
50
65
  * Synonym / intent map: product-language terms an agent is likely to type,
51
66
  * expanded to the catalog's vocabulary so oblique queries still rank. Keys and
@@ -72,10 +87,19 @@ const SYNONYMS = {
72
87
 
73
88
  // Flatten into a token -> Set(expansions) lookup (bidirectional).
74
89
  const SYNONYM_INDEX = (() => {
90
+ /** @type {Map<string, Set<string>>} */
75
91
  const idx = new Map();
92
+ /**
93
+ * @param {string} a
94
+ * @param {string} b
95
+ */
76
96
  const add = (a, b) => {
77
- if (!idx.has(a)) idx.set(a, new Set());
78
- idx.get(a).add(b);
97
+ let set = idx.get(a);
98
+ if (!set) {
99
+ set = new Set();
100
+ idx.set(a, set);
101
+ }
102
+ set.add(b);
79
103
  };
80
104
  for (const [key, vals] of Object.entries(SYNONYMS)) {
81
105
  for (const v of vals) {
@@ -159,6 +183,8 @@ const MIN_TOKEN_SCORE = 50;
159
183
  /**
160
184
  * Best score for a token against a candidate, fanning out through synonyms
161
185
  * (synonym hits are discounted so a direct hit always wins).
186
+ * @param {string} tok
187
+ * @param {Candidate} candidate
162
188
  * @returns {{score: number, reason: string} | null}
163
189
  */
164
190
  function bestForToken(tok, candidate) {
@@ -176,6 +202,12 @@ function bestForToken(tok, candidate) {
176
202
  return best;
177
203
  }
178
204
 
205
+ /**
206
+ * @param {string} term - Lowercased full query.
207
+ * @param {string[]} tokens - Content tokens from tokenizeQuery(term).
208
+ * @param {Candidate} candidate
209
+ * @returns {{score: number, reason: string} | null}
210
+ */
179
211
  export function scoreQuery(term, tokens, candidate) {
180
212
  const full = scoreCandidate(term, candidate);
181
213
 
@@ -192,6 +224,7 @@ export function scoreQuery(term, tokens, candidate) {
192
224
  // strong hits, then reward coverage so candidates matching more terms win.
193
225
  let sum = 0;
194
226
  let matched = 0;
227
+ /** @type {string[]} */
195
228
  const hitTerms = [];
196
229
  for (const tok of tokens) {
197
230
  const h = bestForToken(tok, candidate);
@@ -235,6 +268,10 @@ export function scoreQuery(term, tokens, candidate) {
235
268
  export function scoreCandidate(term, {name, keywords = [], description = '', prose = []}) {
236
269
  let best = 0;
237
270
  let reason = '';
271
+ /**
272
+ * @param {number} score
273
+ * @param {string} why
274
+ */
238
275
  const consider = (score, why) => {
239
276
  if (score > best) {
240
277
  best = score;
@@ -299,7 +336,12 @@ export function scoreCandidate(term, {name, keywords = [], description = '', pro
299
336
  return best > 0 ? {score: best, reason} : null;
300
337
  }
301
338
 
302
- /** Load a doc module's `docs`/`doc` export, swallowing errors. */
339
+ /**
340
+ * Load a doc module's `docs`/`doc` export, swallowing errors.
341
+ * @param {string} docPath
342
+ * @param {string} [exportName]
343
+ * @returns {Promise<any>}
344
+ */
303
345
  async function loadModuleDoc(docPath, exportName = 'docs') {
304
346
  try {
305
347
  const mod = await import(pathToFileURL(docPath).href);
@@ -313,13 +355,16 @@ async function loadModuleDoc(docPath, exportName = 'docs') {
313
355
  * Build component candidates: name + keywords + usage/description from the
314
356
  * component's .doc.mjs.
315
357
  * @param {string} coreDir
358
+ * @returns {Promise<Candidate[]>}
316
359
  */
317
360
  async function gatherComponents(coreDir) {
318
361
  const grouped = discoverComponents(coreDir);
319
362
  const names = Object.values(grouped).flat();
363
+ /** @type {Candidate[]} */
320
364
  const candidates = [];
321
365
  for (const comp of names) {
322
366
  const readme = findComponentReadme(coreDir, comp);
367
+ /** @type {string[]} */
323
368
  let keywords = [];
324
369
  let description = '';
325
370
  if (readme && readme.endsWith('.doc.mjs')) {
@@ -344,13 +389,16 @@ async function gatherComponents(coreDir) {
344
389
  * Build hook candidates: name + keywords + usage/description from the hook's
345
390
  * .doc.mjs.
346
391
  * @param {string} coreDir
392
+ * @returns {Promise<Candidate[]>}
347
393
  */
348
394
  async function gatherHooks(coreDir) {
349
395
  const grouped = discoverHooks(coreDir);
350
396
  const names = Object.values(grouped).flat();
397
+ /** @type {Candidate[]} */
351
398
  const candidates = [];
352
399
  for (const hookName of names) {
353
400
  const docPath = findHookDoc(coreDir, hookName);
401
+ /** @type {string[]} */
354
402
  let keywords = [];
355
403
  let description = '';
356
404
  let importPath = '@astryxdesign/core/hooks';
@@ -373,9 +421,13 @@ async function gatherHooks(coreDir) {
373
421
  return candidates;
374
422
  }
375
423
 
376
- /** Build doc-topic candidates: topic name + description + section prose. */
424
+ /**
425
+ * Build doc-topic candidates: topic name + description + section prose.
426
+ * @returns {Promise<Candidate[]>}
427
+ */
377
428
  async function gatherDocs() {
378
429
  if (!fs.existsSync(DOCS_DIR)) return [];
430
+ /** @type {Candidate[]} */
379
431
  const candidates = [];
380
432
  for (const file of fs.readdirSync(DOCS_DIR)) {
381
433
  const match = file.match(/^([\w-]+)\.doc\.mjs$/);
@@ -383,6 +435,7 @@ async function gatherDocs() {
383
435
  const topic = match[1];
384
436
  const doc = await loadModuleDoc(path.join(DOCS_DIR, file));
385
437
  let description = '';
438
+ /** @type {string[]} */
386
439
  const prose = [];
387
440
  if (doc) {
388
441
  description = doc.description || '';
@@ -405,7 +458,11 @@ async function gatherDocs() {
405
458
  return candidates;
406
459
  }
407
460
 
408
- /** Build template candidates (page + block) from the template discovery API. */
461
+ /**
462
+ * Build template candidates (page + block) from the template discovery API.
463
+ * @param {string} cwd
464
+ * @returns {Promise<Candidate[]>}
465
+ */
409
466
  async function gatherTemplates(cwd) {
410
467
  let templates;
411
468
  try {
@@ -444,7 +501,7 @@ async function gatherTemplates(cwd) {
444
501
  * carries enough to act on it: the domain, name, a one-line description, and
445
502
  * the follow-up command (and import path where relevant).
446
503
  *
447
- * @param {object} c - candidate
504
+ * @param {Candidate} c - candidate
448
505
  * @param {number} score
449
506
  * @param {string} reason
450
507
  */
@@ -522,6 +579,7 @@ export async function search(query, options = {}) {
522
579
  }
523
580
 
524
581
  // Gather candidates from each requested domain in parallel.
582
+ /** @param {string} d */
525
583
  const wants = d => !type || type === d;
526
584
  const [components, hooks, docTopics, templates] = await Promise.all([
527
585
  wants('component') ? gatherComponents(coreDir) : [],
@@ -543,6 +601,7 @@ export async function search(query, options = {}) {
543
601
  }
544
602
 
545
603
  // Sort by score desc, then domain (stable order), then name.
604
+ /** @type {Record<string, number>} */
546
605
  const domainOrder = {component: 0, hook: 1, doc: 2, template: 3};
547
606
  scored.sort(
548
607
  (a, b) =>