@astryxdesign/cli 0.1.8-canary.4cc4d7a → 0.1.8-canary.68afe69

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 (300) hide show
  1. package/{src/api → api/blog}/blog.mjs +3 -3
  2. package/{src/api → api/blog}/blog.test.mjs +2 -2
  3. package/api/build/build.mjs +92 -0
  4. package/api/build/build.test.mjs +92 -0
  5. package/{src/api → api/component}/component.mjs +12 -12
  6. package/{src/api → api/discover}/discover.mjs +14 -14
  7. package/{src/api → api/docs}/docs.mjs +10 -10
  8. package/{src/api → api/doctor}/doctor.mjs +5 -5
  9. package/{src/api → api/hook}/hook.mjs +6 -6
  10. package/{src/api → api}/index.mjs +16 -9
  11. package/{src/api → api/integration}/validate-integration.mjs +38 -10
  12. package/{src/api → api/integration}/validate-integration.test.mjs +1 -1
  13. package/{src/api → api/layout}/layout.mjs +21 -21
  14. package/{src/api → api/layout}/layout.test.mjs +1 -1
  15. package/{src/api → api/search}/search.mjs +6 -6
  16. package/api/swizzle/swizzle.mjs +283 -0
  17. package/{src/commands → api/swizzle}/swizzle.test.mjs +26 -1
  18. package/{src/api → api/template}/template-integration.test.mjs +2 -2
  19. package/{src/api → api/template}/template-suffix.test.mjs +3 -3
  20. package/{src/api → api/template}/template.mjs +8 -8
  21. package/{src/api → api/theme}/theme-add.mjs +4 -4
  22. package/{src → authoring}/codemod.mjs +6 -6
  23. package/{src → authoring}/config.test.mjs +1 -1
  24. package/{src → authoring}/doc.mjs +1 -1
  25. package/{src → authoring}/doc.test.mjs +1 -1
  26. package/{src → authoring}/template.mjs +1 -1
  27. package/bin/astryx.mjs +10 -10
  28. package/{src → cli}/commands/blog.mjs +5 -5
  29. package/{src → cli}/commands/build-theme.mjs +12 -12
  30. package/{src → cli}/commands/build.mjs +26 -60
  31. package/{src → cli}/commands/component/index.mjs +27 -27
  32. package/{src → cli}/commands/component-ownership.test.mjs +3 -3
  33. package/{src → cli}/commands/component-package.test.mjs +1 -1
  34. package/{src → cli}/commands/component-resolution.test.mjs +2 -2
  35. package/{src → cli}/commands/discover.mjs +6 -6
  36. package/{src → cli}/commands/docs.mjs +5 -5
  37. package/{src → cli}/commands/docs.test.mjs +1 -1
  38. package/{src → cli}/commands/doctor.mjs +3 -3
  39. package/{src → cli}/commands/doctor.test.mjs +2 -2
  40. package/{src → cli}/commands/external-showcase.test.mjs +1 -1
  41. package/{src → cli}/commands/hook/index.mjs +17 -17
  42. package/{src → cli}/commands/import-hint-correctness.test.mjs +1 -1
  43. package/{src → cli}/commands/init.mjs +7 -7
  44. package/{src → cli}/commands/layout.mjs +9 -9
  45. package/{src → cli}/commands/search.mjs +9 -9
  46. package/{src → cli}/commands/search.test.mjs +1 -1
  47. package/{src → cli}/commands/setup-nudge.test.mjs +1 -1
  48. package/cli/commands/swizzle.mjs +103 -0
  49. package/{src → cli}/commands/template.mjs +17 -17
  50. package/{src → cli}/commands/template.path-safety.test.mjs +2 -2
  51. package/{src → cli}/commands/upgrade.integration-policy.test.mjs +1 -1
  52. package/{src → cli}/commands/upgrade.mjs +30 -30
  53. package/{src → cli}/commands/upgrade.test.mjs +1 -1
  54. package/{src → cli}/commands/validate-integration.mjs +17 -37
  55. package/{src → cli}/index.mjs +11 -10
  56. package/{src/codemods → codemods}/integration-discovery.mjs +1 -1
  57. package/{src/codemods → codemods}/integration-discovery.test.mjs +1 -1
  58. package/docs/internationalization.doc.mjs +89 -47
  59. package/{src/commands → lib/agent-docs}/agent-docs.mjs +7 -7
  60. package/{src/commands → lib/agent-docs}/agent-docs.path-safety.test.mjs +1 -1
  61. package/{src/lib → lib}/component-format.mjs +5 -5
  62. package/{src/lib → lib}/componentDocOverlay.test.mjs +0 -1
  63. package/{src/lib → lib}/error-codes.test.mjs +1 -1
  64. package/{src/lib → lib}/integration-warnings.mjs +1 -1
  65. package/{src/lib → lib}/integrations.test.mjs +1 -1
  66. package/{src/lib → lib}/json-contract.test.mjs +1 -1
  67. package/{src/lib → lib}/json-shim.test.mjs +1 -1
  68. package/{src/lib → lib}/manifest.mjs +2 -0
  69. package/{src/lib → lib}/manifest.test.mjs +2 -2
  70. package/{src/lib → lib}/project.mjs +2 -2
  71. package/{src/lib → lib}/project.test.mjs +1 -1
  72. package/{src/lib → lib}/term-log.mjs +1 -1
  73. package/package.json +33 -26
  74. package/scripts/postinstall.mjs +1 -1
  75. package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.doc.mjs +19 -0
  76. package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +46 -0
  77. package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider02Overrides.doc.mjs +14 -0
  78. package/templates/blocks/components/InternationalizationProvider/InternationalizationProvider02Overrides.tsx +33 -0
  79. package/{src/types → types}/api.contract.assert.ts +17 -8
  80. package/{src/types → types}/api.d.ts +106 -0
  81. package/{src/types → types}/base.d.ts +2 -1
  82. package/types/build.d.ts +53 -0
  83. package/{src/types → types}/component.d.ts +1 -1
  84. package/{src/types → types}/discover.d.ts +1 -1
  85. package/{src/types → types}/docs.d.ts +1 -4
  86. package/{src/types → types}/hook.d.ts +1 -1
  87. package/{src/utils → utils}/paths.mjs +1 -1
  88. package/src/commands/swizzle.mjs +0 -424
  89. package/src/types/build.d.ts +0 -23
  90. /package/{src/api → api/docs}/docOverlays.test.mjs +0 -0
  91. /package/{src/api → api}/error.mjs +0 -0
  92. /package/{src/api → api/integration}/integration-block-exports.test.mjs +0 -0
  93. /package/{src/api → api/template}/template.test.mjs +0 -0
  94. /package/{src → authoring}/codemod.test.mjs +0 -0
  95. /package/{src → authoring}/config.mjs +0 -0
  96. /package/{src → authoring}/integration.mjs +0 -0
  97. /package/{src → authoring}/template.test.mjs +0 -0
  98. /package/{src → cli}/cli-exit-codes.test.mjs +0 -0
  99. /package/{src → cli}/commands/build-theme.color-scheme.test.mjs +0 -0
  100. /package/{src → cli}/commands/build-theme.import-path.test.mjs +0 -0
  101. /package/{src → cli}/commands/build-theme.path-safety.test.mjs +0 -0
  102. /package/{src → cli}/commands/build-theme.prose.test.mjs +0 -0
  103. /package/{src → cli}/commands/build-theme.variants.test.mjs +0 -0
  104. /package/{src → cli}/commands/build-theme.watch.test.mjs +0 -0
  105. /package/{src → cli}/commands/cli-postinstall.test.mjs +0 -0
  106. /package/{src → cli}/commands/component.test.mjs +0 -0
  107. /package/{src → cli}/commands/detail-levels.test.mjs +0 -0
  108. /package/{src → cli}/commands/ensure-core-built.mjs +0 -0
  109. /package/{src → cli}/commands/init.next-steps.test.mjs +0 -0
  110. /package/{src → cli}/commands/interactive-guard.test.mjs +0 -0
  111. /package/{src → cli}/commands/json-contract.test.mjs +0 -0
  112. /package/{src → cli}/commands/swizzle.path-safety.test.mjs +0 -0
  113. /package/{src → cli}/commands/swizzle.routing.test.mjs +0 -0
  114. /package/{src → cli}/commands/template.test.mjs +0 -0
  115. /package/{src → cli}/commands/upgrade.config-ordering.test.mjs +0 -0
  116. /package/{src → cli}/commands/validate-integration.test.mjs +0 -0
  117. /package/{src → cli}/update-hint-commands.test.mjs +0 -0
  118. /package/{src/codemods → codemods}/__tests__/registry.test.mjs +0 -0
  119. /package/{src/codemods → codemods}/__tests__/rename-imperative-ref-to-handleRef.test.mjs +0 -0
  120. /package/{src/codemods → codemods}/__tests__/rename-isStreaming-to-isStopShown.test.mjs +0 -0
  121. /package/{src/codemods → codemods}/__tests__/rename-section-wash-to-muted.test.mjs +0 -0
  122. /package/{src/codemods → codemods}/__tests__/runner.test.mjs +0 -0
  123. /package/{src/codemods → codemods}/__tests__/toolbar-density-to-size.test.mjs +0 -0
  124. /package/{src/codemods → codemods}/__tests__/validation.test.mjs +0 -0
  125. /package/{src/codemods → codemods}/ensure-jscodeshift.mjs +0 -0
  126. /package/{src/codemods → codemods}/integration-runner.mjs +0 -0
  127. /package/{src/codemods → codemods}/registry.mjs +0 -0
  128. /package/{src/codemods → codemods}/run-codemod.mjs +0 -0
  129. /package/{src/codemods → codemods}/runner.mjs +0 -0
  130. /package/{src/codemods → codemods}/transforms/v0.0.10/__tests__/remove-size-props.test.mjs +0 -0
  131. /package/{src/codemods → codemods}/transforms/v0.0.10/index.mjs +0 -0
  132. /package/{src/codemods → codemods}/transforms/v0.0.10/remove-size-props.mjs +0 -0
  133. /package/{src/codemods → codemods}/transforms/v0.0.12/__tests__/add-is-icon-only.test.mjs +0 -0
  134. /package/{src/codemods → codemods}/transforms/v0.0.12/add-is-icon-only.mjs +0 -0
  135. /package/{src/codemods → codemods}/transforms/v0.0.12/index.mjs +0 -0
  136. /package/{src/codemods → codemods}/transforms/v0.0.13/__tests__/icon-name-deprecations.test.mjs +0 -0
  137. /package/{src/codemods → codemods}/transforms/v0.0.13/__tests__/rename-attachments-to-drawer.test.mjs +0 -0
  138. /package/{src/codemods → codemods}/transforms/v0.0.13/icon-name-deprecations.mjs +0 -0
  139. /package/{src/codemods → codemods}/transforms/v0.0.13/index.mjs +0 -0
  140. /package/{src/codemods → codemods}/transforms/v0.0.13/rename-attachments-to-drawer.mjs +0 -0
  141. /package/{src/codemods → codemods}/transforms/v0.0.13/toolbar-density-to-size.mjs +0 -0
  142. /package/{src/codemods → codemods}/transforms/v0.0.14/__tests__/rename-action-props.test.mjs +0 -0
  143. /package/{src/codemods → codemods}/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +0 -0
  144. /package/{src/codemods → codemods}/transforms/v0.0.14/index.mjs +0 -0
  145. /package/{src/codemods → codemods}/transforms/v0.0.14/rename-action-props.mjs +0 -0
  146. /package/{src/codemods → codemods}/transforms/v0.0.14/rename-section-wash-to-muted.mjs +0 -0
  147. /package/{src/codemods → codemods}/transforms/v0.0.14/rename-status-variants.mjs +0 -0
  148. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-item-children-to-endcontent.test.mjs +0 -0
  149. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-selector-children-to-render-option.test.mjs +0 -0
  150. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/migrate-theme-selectors-to-data-attrs.test.mjs +0 -0
  151. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/rename-date-picker-to-input.test.mjs +0 -0
  152. /package/{src/codemods → codemods}/transforms/v0.0.15/__tests__/rename-stack-element-to-as.test.mjs +0 -0
  153. /package/{src/codemods → codemods}/transforms/v0.0.15/index.mjs +0 -0
  154. /package/{src/codemods → codemods}/transforms/v0.0.15/migrate-item-children-to-endcontent.mjs +0 -0
  155. /package/{src/codemods → codemods}/transforms/v0.0.15/migrate-selector-children-to-render-option.mjs +0 -0
  156. /package/{src/codemods → codemods}/transforms/v0.0.15/migrate-theme-selectors-to-data-attrs.mjs +0 -0
  157. /package/{src/codemods → codemods}/transforms/v0.0.15/rename-date-picker-to-input.mjs +0 -0
  158. /package/{src/codemods → codemods}/transforms/v0.0.15/rename-imperative-ref-to-handleRef.mjs +0 -0
  159. /package/{src/codemods → codemods}/transforms/v0.0.15/rename-isStreaming-to-isStopShown.mjs +0 -0
  160. /package/{src/codemods → codemods}/transforms/v0.0.15/rename-stack-element-to-as.mjs +0 -0
  161. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-badge-dot-to-statusdot.test.mjs +0 -0
  162. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-gap-to-numeric.test.mjs +0 -0
  163. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-isFullBleed-to-padding.test.mjs +0 -0
  164. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/migrate-useXDSIcon-to-getIcon.test.mjs +0 -0
  165. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-banner-endButton-to-endContent.test.mjs +0 -0
  166. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-form-tooltip-startIcon.test.mjs +0 -0
  167. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-isShown-to-isOpen.test.mjs +0 -0
  168. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-selector-items-to-options.test.mjs +0 -0
  169. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-sidenav-header-to-heading.test.mjs +0 -0
  170. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/rename-topnav-title-to-heading.test.mjs +0 -0
  171. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/unify-uncontrolled-to-defaultX.test.mjs +0 -0
  172. /package/{src/codemods → codemods}/transforms/v0.0.2/__tests__/unify-visibility-to-onOpenChange.test.mjs +0 -0
  173. /package/{src/codemods → codemods}/transforms/v0.0.2/index.mjs +0 -0
  174. /package/{src/codemods → codemods}/transforms/v0.0.2/migrate-badge-dot-to-statusdot.mjs +0 -0
  175. /package/{src/codemods → codemods}/transforms/v0.0.2/migrate-gap-to-numeric.mjs +0 -0
  176. /package/{src/codemods → codemods}/transforms/v0.0.2/migrate-isFullBleed-to-padding.mjs +0 -0
  177. /package/{src/codemods → codemods}/transforms/v0.0.2/migrate-useXDSIcon-to-getIcon.mjs +0 -0
  178. /package/{src/codemods → codemods}/transforms/v0.0.2/rename-banner-endButton-to-endContent.mjs +0 -0
  179. /package/{src/codemods → codemods}/transforms/v0.0.2/rename-form-tooltip-startIcon.mjs +0 -0
  180. /package/{src/codemods → codemods}/transforms/v0.0.2/rename-isShown-to-isOpen.mjs +0 -0
  181. /package/{src/codemods → codemods}/transforms/v0.0.2/rename-selector-items-to-options.mjs +0 -0
  182. /package/{src/codemods → codemods}/transforms/v0.0.2/rename-sidenav-header-to-heading.mjs +0 -0
  183. /package/{src/codemods → codemods}/transforms/v0.0.2/rename-topnav-title-to-heading.mjs +0 -0
  184. /package/{src/codemods → codemods}/transforms/v0.0.2/unify-uncontrolled-to-defaultX.mjs +0 -0
  185. /package/{src/codemods → codemods}/transforms/v0.0.2/unify-visibility-to-onOpenChange.mjs +0 -0
  186. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-collapse-to-collapsible.test.mjs +0 -0
  187. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-radius-tokens.test.mjs +0 -0
  188. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-shadow-tokens.test.mjs +0 -0
  189. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-skeleton-radius.test.mjs +0 -0
  190. /package/{src/codemods → codemods}/transforms/v0.0.6/__tests__/migrate-token-names.test.mjs +0 -0
  191. /package/{src/codemods → codemods}/transforms/v0.0.6/index.mjs +0 -0
  192. /package/{src/codemods → codemods}/transforms/v0.0.6/migrate-badge-children-to-label.mjs +0 -0
  193. /package/{src/codemods → codemods}/transforms/v0.0.6/migrate-collapse-to-collapsible.mjs +0 -0
  194. /package/{src/codemods → codemods}/transforms/v0.0.6/migrate-radius-tokens.mjs +0 -0
  195. /package/{src/codemods → codemods}/transforms/v0.0.6/migrate-shadow-tokens.mjs +0 -0
  196. /package/{src/codemods → codemods}/transforms/v0.0.6/migrate-skeleton-radius.mjs +0 -0
  197. /package/{src/codemods → codemods}/transforms/v0.0.6/migrate-token-names.mjs +0 -0
  198. /package/{src/codemods → codemods}/transforms/v0.0.7/__tests__/rename-banner-variant-to-container.test.mjs +0 -0
  199. /package/{src/codemods → codemods}/transforms/v0.0.7/index.mjs +0 -0
  200. /package/{src/codemods → codemods}/transforms/v0.0.7/rename-banner-variant-to-container.mjs +0 -0
  201. /package/{src/codemods → codemods}/transforms/v0.0.8/__tests__/migrate-token-renames.test.mjs +0 -0
  202. /package/{src/codemods → codemods}/transforms/v0.0.8/__tests__/rename-endslot-to-endcontent.test.mjs +0 -0
  203. /package/{src/codemods → codemods}/transforms/v0.0.8/index.mjs +0 -0
  204. /package/{src/codemods → codemods}/transforms/v0.0.8/migrate-token-renames.mjs +0 -0
  205. /package/{src/codemods → codemods}/transforms/v0.0.8/rename-endslot-to-endcontent.mjs +0 -0
  206. /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/drop-xds-prefix-imports.test.mjs +0 -0
  207. /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-css-surfaces.test.mjs +0 -0
  208. /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-declare-module.test.mjs +0 -0
  209. /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/migrate-xds-module-specifiers.test.mjs +0 -0
  210. /package/{src/codemods → codemods}/transforms/v0.1.0/__tests__/v0.1.0-ordering.test.mjs +0 -0
  211. /package/{src/codemods → codemods}/transforms/v0.1.0/drop-xds-prefix-imports.mjs +0 -0
  212. /package/{src/codemods → codemods}/transforms/v0.1.0/index.mjs +0 -0
  213. /package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-css-surfaces.mjs +0 -0
  214. /package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-declare-module.mjs +0 -0
  215. /package/{src/codemods → codemods}/transforms/v0.1.0/migrate-xds-module-specifiers.mjs +0 -0
  216. /package/{src/codemods → codemods}/transforms/v0.1.2/__tests__/rename-text-color-active-to-accent.test.mjs +0 -0
  217. /package/{src/codemods → codemods}/transforms/v0.1.2/index.mjs +0 -0
  218. /package/{src/codemods → codemods}/transforms/v0.1.2/rename-text-color-active-to-accent.mjs +0 -0
  219. /package/{src/codemods → codemods}/transforms/v0.1.3/__tests__/migrate-layout-components-to-experimental.test.mjs +0 -0
  220. /package/{src/codemods → codemods}/transforms/v0.1.3/index.mjs +0 -0
  221. /package/{src/codemods → codemods}/transforms/v0.1.3/migrate-layout-components-to-experimental.mjs +0 -0
  222. /package/{src/codemods → codemods}/transforms/v0.1.5/__tests__/rename-switch-label-spacing-default-to-hug.test.mjs +0 -0
  223. /package/{src/codemods → codemods}/transforms/v0.1.5/index.mjs +0 -0
  224. /package/{src/codemods → codemods}/transforms/v0.1.5/rename-switch-label-spacing-default-to-hug.mjs +0 -0
  225. /package/{src/codemods → codemods}/transforms/v0.1.7/__tests__/migrate-table-tableprops-to-direct-props.test.mjs +0 -0
  226. /package/{src/codemods → codemods}/transforms/v0.1.7/__tests__/rename-table-renderprops-styles-to-xstyle.test.mjs +0 -0
  227. /package/{src/codemods → codemods}/transforms/v0.1.7/index.mjs +0 -0
  228. /package/{src/codemods → codemods}/transforms/v0.1.7/migrate-table-tableprops-to-direct-props.mjs +0 -0
  229. /package/{src/codemods → codemods}/transforms/v0.1.7/rename-table-renderprops-styles-to-xstyle.mjs +0 -0
  230. /package/{src/codemods → codemods}/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +0 -0
  231. /package/{src/codemods → codemods}/transforms/v0.1.8/index.mjs +0 -0
  232. /package/{src/codemods → codemods}/transforms/v0.1.8/rename-avatar-size-scale.mjs +0 -0
  233. /package/{src/commands → lib/agent-docs}/agent-docs.test.mjs +0 -0
  234. /package/{src/lib → lib}/cli-error.mjs +0 -0
  235. /package/{src/lib → lib}/cli-error.test.mjs +0 -0
  236. /package/{src/lib → lib}/component-discovery.importpath.test.mjs +0 -0
  237. /package/{src/lib → lib}/component-discovery.mjs +0 -0
  238. /package/{src/lib → lib}/component-format.test.mjs +0 -0
  239. /package/{src/lib → lib}/component-loader.mjs +0 -0
  240. /package/{src/lib → lib}/component-loader.test.mjs +0 -0
  241. /package/{src/lib → lib}/config-cache.mjs +0 -0
  242. /package/{src/lib → lib}/config-cache.test.mjs +0 -0
  243. /package/{src/lib → lib}/config-schema.mjs +0 -0
  244. /package/{src/lib → lib}/error-codes.mjs +0 -0
  245. /package/{src/lib → lib}/hook-discovery.mjs +0 -0
  246. /package/{src/lib → lib}/hook-format.mjs +0 -0
  247. /package/{src/lib → lib}/integration-warnings.test.mjs +0 -0
  248. /package/{src/lib → lib}/integrations.mjs +0 -0
  249. /package/{src/lib → lib}/json-shim.mjs +0 -0
  250. /package/{src/lib → lib}/json.mjs +0 -0
  251. /package/{src/lib → lib}/levenshtein.mjs +0 -0
  252. /package/{src/lib → lib}/module-loader.mjs +0 -0
  253. /package/{src/lib → lib}/module-loader.test.mjs +0 -0
  254. /package/{src/lib → lib}/node-version.mjs +0 -0
  255. /package/{src/lib → lib}/node-version.test.mjs +0 -0
  256. /package/{src/lib → lib}/package-scanner.mjs +0 -0
  257. /package/{src/lib → lib}/parse.mjs +0 -0
  258. /package/{src/lib → lib}/resolve-theme.mjs +0 -0
  259. /package/{src/lib → lib}/site.mjs +0 -0
  260. /package/{src/lib → lib}/string-utils.mjs +0 -0
  261. /package/{src/lib → lib}/xle/browser.d.ts +0 -0
  262. /package/{src/lib → lib}/xle/browser.mjs +0 -0
  263. /package/{src/lib → lib}/xle/expand.mjs +0 -0
  264. /package/{src/lib → lib}/xle/parse.mjs +0 -0
  265. /package/{src/lib → lib}/xle/print.mjs +0 -0
  266. /package/{src/lib → lib}/xle/registry-core.mjs +0 -0
  267. /package/{src/lib → lib}/xle/registry.mjs +0 -0
  268. /package/{src/lib → lib}/xle/splice.mjs +0 -0
  269. /package/{src/lib → lib}/xle/validate.mjs +0 -0
  270. /package/{src/lib → lib}/xle/xle-ast.d.ts +0 -0
  271. /package/{src/lib → lib}/xle/xle.test.mjs +0 -0
  272. /package/{src/schemas → schemas}/doc-schema.mjs +0 -0
  273. /package/{src/schemas → schemas}/template-schema.mjs +0 -0
  274. /package/{src/types → types}/codemod.d.ts +0 -0
  275. /package/{src/types → types}/config.d.ts +0 -0
  276. /package/{src/types → types}/doc.d.ts +0 -0
  277. /package/{src/types → types}/doctor.d.ts +0 -0
  278. /package/{src/types → types}/error-codes.d.ts +0 -0
  279. /package/{src/types → types}/index.d.ts +0 -0
  280. /package/{src/types → types}/integration.d.ts +0 -0
  281. /package/{src/types → types}/jscodeshift.d.ts +0 -0
  282. /package/{src/types → types}/layout.d.ts +0 -0
  283. /package/{src/types → types}/manifest.d.ts +0 -0
  284. /package/{src/types → types}/search.d.ts +0 -0
  285. /package/{src/types → types}/swizzle.d.ts +0 -0
  286. /package/{src/types → types}/template-api.d.ts +0 -0
  287. /package/{src/types → types}/template.d.ts +0 -0
  288. /package/{src/types → types}/theme.d.ts +0 -0
  289. /package/{src/types → types}/upgrade.d.ts +0 -0
  290. /package/{src/types → types}/validate-integration.d.ts +0 -0
  291. /package/{src/utils → utils}/github.mjs +0 -0
  292. /package/{src/utils → utils}/package-manager.mjs +0 -0
  293. /package/{src/utils → utils}/package-manager.test.mjs +0 -0
  294. /package/{src/utils → utils}/path-safety.mjs +0 -0
  295. /package/{src/utils → utils}/path-safety.test.mjs +0 -0
  296. /package/{src/utils → utils}/paths.test.mjs +0 -0
  297. /package/{src/utils → utils}/semver.mjs +0 -0
  298. /package/{src/utils → utils}/semver.test.mjs +0 -0
  299. /package/{src/utils → utils}/update-check.mjs +0 -0
  300. /package/{src/utils → utils}/update-check.test.mjs +0 -0
@@ -10,9 +10,9 @@
10
10
  * blog's structure can change freely without touching the CLI.
11
11
  */
12
12
 
13
- import {AstryxError} from './error.mjs';
14
- import {ERROR_CODES} from '../lib/error-codes.mjs';
15
- import {SITE_URL, SITE_ORIGIN} from '../lib/site.mjs';
13
+ import {AstryxError} from '../error.mjs';
14
+ import {ERROR_CODES} from '../../lib/error-codes.mjs';
15
+ import {SITE_URL, SITE_ORIGIN} from '../../lib/site.mjs';
16
16
 
17
17
  /** Abort a feed/post fetch that hangs, and cap how much we'll read. */
18
18
  const FETCH_TIMEOUT_MS = 15000;
@@ -9,8 +9,8 @@
9
9
 
10
10
  import {describe, it, expect, beforeEach, afterEach, vi} from 'vitest';
11
11
  import {blog} from './blog.mjs';
12
- import {AstryxError} from './error.mjs';
13
- import {SITE_URL} from '../lib/site.mjs';
12
+ import {AstryxError} from '../error.mjs';
13
+ import {SITE_URL} from '../../lib/site.mjs';
14
14
 
15
15
  const FEED = `<?xml version="1.0" encoding="UTF-8"?>
16
16
  <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
@@ -0,0 +1,92 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file build API — the "assemble a page" assistant, as data.
5
+ *
6
+ * `build()` with no query signals the workflow playbook (`build.help`). With a
7
+ * query it runs the unified search and groups the results into a composition
8
+ * KIT (`build.kit`): the closest page templates, the blocks that cover parts,
9
+ * and the domain components to fill gaps, plus the always-on frame + foundation.
10
+ *
11
+ * The kit carries RAW `SearchResultEntry` objects and static name arrays only —
12
+ * never pre-formatted command strings. All CLI prefixing (formatCliCommand /
13
+ * getCliInvocation) and the section prose live in the command renderer, so the
14
+ * JSON shape stays package-manager-agnostic and stable across environments.
15
+ */
16
+
17
+ import {search} from '../search/search.mjs';
18
+
19
+ /** A page at/above this score is a confident direct match. */
20
+ const PAGE_DIRECT = 95;
21
+ /** Below this a page is too weak to offer even as a layout reference. */
22
+ const PAGE_FLOOR = 50;
23
+ /** Below this a block/domain-component match is incidental noise. */
24
+ const DOMAIN_FLOOR = 55;
25
+
26
+ /**
27
+ * Always-surfaced primitives. Every page needs a shell + layout/typography/
28
+ * action atoms, but these never keyword-match an idea ("dashboard" != "Stack"),
29
+ * so search alone never returns them. Kept here (not the renderer) because they
30
+ * are ALSO used to exclude these names from the idea-specific `domain` group.
31
+ */
32
+ const FRAME = ['AppShell', 'TopNav', 'SideNav', 'Layout'];
33
+ const FOUNDATION = [
34
+ 'VStack', 'HStack', 'Grid', 'StackItem', 'Card', 'Section',
35
+ 'Text', 'Heading', 'Button', 'Icon', 'Badge', 'Divider',
36
+ ];
37
+ const ALWAYS = new Set([...FRAME, ...FOUNDATION]);
38
+
39
+ /**
40
+ * The page-building assistant. No query → the playbook signal; a query → the
41
+ * grouped composition kit.
42
+ *
43
+ * @param {string} [query] what you're building (e.g. "analytics dashboard")
44
+ * @param {{cwd?: string, type?: import('../../types/search').SearchDomain, limit?: number}} [options]
45
+ * @returns {Promise<import('../../types/build').BuildHelpResponse | import('../../types/build').BuildKitResponse>}
46
+ */
47
+ export async function build(query, options = {}) {
48
+ if (!query || !String(query).trim()) {
49
+ return {type: 'build.help', data: {playbook: true}};
50
+ }
51
+
52
+ const {cwd = process.cwd(), type, limit = 60} = options;
53
+ // search()'s JSDoc @returns widens results to object[]; the SearchResponse
54
+ // shape is the contract (api.d.ts). Cast locally rather than tightening the
55
+ // search @returns (a separate follow-up).
56
+ const result = /** @type {import('../../types/search').SearchResponse} */ (
57
+ await search(query, {cwd, type, limit})
58
+ );
59
+ const results = result.data.results;
60
+
61
+ const pages = results
62
+ .filter(r => r.domain === 'template' && r.kind !== 'block' && r.score >= PAGE_FLOOR)
63
+ .slice(0, 3);
64
+ const blocks = results
65
+ .filter(r => r.domain === 'template' && r.kind === 'block' && r.score >= DOMAIN_FLOOR)
66
+ .slice(0, 5);
67
+ const domain = results
68
+ .filter(
69
+ r =>
70
+ (r.domain === 'component' || r.domain === 'hook') &&
71
+ r.score >= DOMAIN_FLOOR &&
72
+ !ALWAYS.has(r.name),
73
+ )
74
+ .slice(0, 6);
75
+ const directMatch = pages.length > 0 && pages[0].score >= PAGE_DIRECT;
76
+
77
+ return {
78
+ type: 'build.kit',
79
+ data: {
80
+ query: result.data.query,
81
+ // Distinguishes "search found nothing" (renderer shows "No matches")
82
+ // from a weak-but-non-empty result set (renderer still shows the kit).
83
+ hasResults: results.length > 0,
84
+ directMatch,
85
+ pages,
86
+ blocks,
87
+ domain,
88
+ frame: FRAME,
89
+ foundation: FOUNDATION,
90
+ },
91
+ };
92
+ }
@@ -0,0 +1,92 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Tests for the build API (playbook signal + composition kit).
5
+ */
6
+
7
+ import {describe, it, expect, vi} from 'vitest';
8
+ import * as path from 'node:path';
9
+ import {fileURLToPath} from 'node:url';
10
+ import {build} from './build.mjs';
11
+
12
+ // api/build/ -> up 3 = packages/cli, up 4 = repo root (has packages/core).
13
+ const REPO = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../..');
14
+
15
+ // build() delegates to search(), whose first (cold) call is slow under vitest.
16
+ vi.setConfig({testTimeout: 30000});
17
+
18
+ describe('build API', () => {
19
+ it('no query → build.help playbook signal', async () => {
20
+ const r = await build();
21
+ expect(r.type).toBe('build.help');
22
+ expect(r.data).toEqual({playbook: true});
23
+ });
24
+
25
+ it('query → build.kit with raw entries + static frame/foundation', async () => {
26
+ const r = await build('dashboard', {cwd: REPO});
27
+ expect(r.type).toBe('build.kit');
28
+ if (r.type !== 'build.kit') return;
29
+ expect(r.data.query).toBe('dashboard');
30
+ expect(r.data.hasResults).toBe(true);
31
+ expect(r.data.frame).toContain('AppShell');
32
+ expect(r.data.foundation).toContain('Button');
33
+ expect(Array.isArray(r.data.pages)).toBe(true);
34
+
35
+ // Entries are RAW SearchResultEntry objects — never package-manager-prefixed
36
+ // command strings (that formatting is the CLI renderer's job).
37
+ for (const e of [...r.data.pages, ...r.data.blocks, ...r.data.domain]) {
38
+ expect(typeof e.name).toBe('string');
39
+ expect(typeof e.score).toBe('number');
40
+ expect(e.command).not.toMatch(/^(pnpm|npm|yarn|bun|npx)\b/);
41
+ }
42
+ });
43
+
44
+ it('excludes always-on frame/foundation names from the domain group', async () => {
45
+ const r = await build('dashboard', {cwd: REPO});
46
+ if (r.type !== 'build.kit') throw new Error('expected build.kit');
47
+ const names = r.data.domain.map(d => d.name);
48
+ expect(names).not.toContain('Button');
49
+ expect(names).not.toContain('AppShell');
50
+ });
51
+
52
+ it('applies grouping caps, score floors, and directMatch threshold', async () => {
53
+ const r = await build('dashboard', {cwd: REPO});
54
+ if (r.type !== 'build.kit') throw new Error('expected build.kit');
55
+ const {pages, blocks, domain, directMatch} = r.data;
56
+
57
+ // Caps: pages ≤ 3, blocks ≤ 5, domain ≤ 6.
58
+ expect(pages.length).toBeLessThanOrEqual(3);
59
+ expect(blocks.length).toBeLessThanOrEqual(5);
60
+ expect(domain.length).toBeLessThanOrEqual(6);
61
+
62
+ // Score floors: pages ≥ PAGE_FLOOR(50); blocks/domain ≥ DOMAIN_FLOOR(55).
63
+ for (const p of pages) expect(p.score).toBeGreaterThanOrEqual(50);
64
+ for (const b of blocks) expect(b.score).toBeGreaterThanOrEqual(55);
65
+ for (const d of domain) expect(d.score).toBeGreaterThanOrEqual(55);
66
+
67
+ // directMatch iff the top page is a confident match (PAGE_DIRECT = 95).
68
+ expect(directMatch).toBe(pages.length > 0 && pages[0].score >= 95);
69
+
70
+ // Domain partitioning: pages = non-block templates, blocks = block templates,
71
+ // domain = components/hooks.
72
+ for (const p of pages) {
73
+ expect(p.domain).toBe('template');
74
+ expect(p.kind).not.toBe('block');
75
+ }
76
+ for (const b of blocks) {
77
+ expect(b.domain).toBe('template');
78
+ expect(b.kind).toBe('block');
79
+ }
80
+ for (const d of domain) expect(['component', 'hook']).toContain(d.domain);
81
+ });
82
+
83
+ it('no matches → build.kit with hasResults=false and empty groups', async () => {
84
+ const r = await build('zzznomatch99', {cwd: REPO});
85
+ expect(r.type).toBe('build.kit');
86
+ if (r.type !== 'build.kit') return;
87
+ expect(r.data.hasResults).toBe(false);
88
+ expect(r.data.pages).toHaveLength(0);
89
+ expect(r.data.blocks).toHaveLength(0);
90
+ expect(r.data.domain).toHaveLength(0);
91
+ });
92
+ });
@@ -9,8 +9,8 @@
9
9
 
10
10
  import * as fs from 'node:fs';
11
11
  import * as path from 'node:path';
12
- import {ERROR_CODES} from '../lib/error-codes.mjs';
13
- import {findCoreDir, discoverExternalPackages} from '../utils/paths.mjs';
12
+ import {ERROR_CODES} from '../../lib/error-codes.mjs';
13
+ import {findCoreDir, discoverExternalPackages} from '../../utils/paths.mjs';
14
14
  import {
15
15
  CORE_PACKAGE,
16
16
  discoverComponents,
@@ -22,12 +22,12 @@ import {
22
22
  findIntegrationComponentDoc,
23
23
  findIntegrationComponentSource,
24
24
  resolveImportPath,
25
- } from '../lib/component-discovery.mjs';
26
- import {Project} from '../lib/project.mjs';
27
- import {loadDocs} from '../lib/component-loader.mjs';
28
- import {searchComponents} from '../lib/string-utils.mjs';
29
- import {AstryxError} from './error.mjs';
30
- import {findShowcase, findRelatedBlocks} from './template.mjs';
25
+ } from '../../lib/component-discovery.mjs';
26
+ import {Project} from '../../lib/project.mjs';
27
+ import {loadDocs} from '../../lib/component-loader.mjs';
28
+ import {searchComponents} from '../../lib/string-utils.mjs';
29
+ import {AstryxError} from '../error.mjs';
30
+ import {findShowcase, findRelatedBlocks} from '../template/template.mjs';
31
31
 
32
32
  /**
33
33
  * A loaded component doc. `loadDocs` returns the authored `.doc.mjs` shape,
@@ -54,12 +54,12 @@ import {findShowcase, findRelatedBlocks} from './template.mjs';
54
54
  * component discovery never hard-fails on a malformed/absent integration. An
55
55
  * empty list means "core only".
56
56
  * @param {string} cwd
57
- * @returns {Promise<import('../lib/integrations.mjs').LoadedIntegration[]>}
57
+ * @returns {Promise<import('../../lib/integrations.mjs').LoadedIntegration[]>}
58
58
  */
59
59
  async function loadIntegrationsSafely(cwd) {
60
60
  try {
61
61
  const project = await Project.load(cwd);
62
- return /** @type {import('../lib/integrations.mjs').LoadedIntegration[]} */ (
62
+ return /** @type {import('../../lib/integrations.mjs').LoadedIntegration[]} */ (
63
63
  project.loadedIntegrations
64
64
  );
65
65
  } catch {
@@ -69,7 +69,7 @@ async function loadIntegrationsSafely(cwd) {
69
69
 
70
70
  /**
71
71
  * Resolve a loaded integration by package name.
72
- * @param {import('../lib/integrations.mjs').LoadedIntegration[]} loadedIntegrations
72
+ * @param {import('../../lib/integrations.mjs').LoadedIntegration[]} loadedIntegrations
73
73
  * @param {string} packageName
74
74
  */
75
75
  function findLoadedIntegration(loadedIntegrations, packageName) {
@@ -195,7 +195,7 @@ export async function component(name, options = {}) {
195
195
 
196
196
  // All components — merge core + external packages with grouped subcategories
197
197
  if (detail === 'compact') {
198
- /** @type {Record<string, Array<import('../types/component').ComponentBriefEntry>>} */
198
+ /** @type {Record<string, Array<import('../../types/component').ComponentBriefEntry>>} */
199
199
  const result = {};
200
200
  for (const [cat, comps] of Object.entries(components)) {
201
201
  result[cat] = [];
@@ -4,18 +4,18 @@
4
4
  * @file Programmatic API for the discover command.
5
5
  */
6
6
 
7
- import {Project} from '../lib/project.mjs';
7
+ import {Project} from '../../lib/project.mjs';
8
8
  import {
9
9
  scanAllPackages,
10
10
  findComponentInPackages,
11
- } from '../lib/package-scanner.mjs';
12
- import {loadDocs} from '../lib/component-loader.mjs';
13
- import {levenshteinDistance} from '../lib/string-utils.mjs';
14
- import {AstryxError} from './error.mjs';
15
- import {ERROR_CODES} from '../lib/error-codes.mjs';
11
+ } from '../../lib/package-scanner.mjs';
12
+ import {loadDocs} from '../../lib/component-loader.mjs';
13
+ import {levenshteinDistance} from '../../lib/string-utils.mjs';
14
+ import {AstryxError} from '../error.mjs';
15
+ import {ERROR_CODES} from '../../lib/error-codes.mjs';
16
16
 
17
17
  /**
18
- * @typedef {import('../lib/package-scanner.mjs').ScannedPackage} ScannedPackage
18
+ * @typedef {import('../../lib/package-scanner.mjs').ScannedPackage} ScannedPackage
19
19
  */
20
20
 
21
21
  /**
@@ -46,17 +46,17 @@ function validateDocs(docs) {
46
46
  * @param {string} [options.lang]
47
47
  * @param {boolean} [options.zh]
48
48
  * @returns {Promise<
49
- * import('../types/discover').DiscoverListResponse |
50
- * import('../types/discover').DiscoverDetailResponse |
51
- * import('../types/discover').DiscoverDetailDocResponse |
52
- * import('../types/discover').DiscoverSearchResponse
49
+ * import('../../types/discover').DiscoverListResponse |
50
+ * import('../../types/discover').DiscoverDetailResponse |
51
+ * import('../../types/discover').DiscoverDetailDocResponse |
52
+ * import('../../types/discover').DiscoverSearchResponse
53
53
  * >}
54
54
  */
55
55
  export async function discover(query, options = {}) {
56
56
  const {lang = null, zh = false} = options;
57
57
  const project = await Project.load();
58
58
  const loadedIntegrations =
59
- /** @type {import('../lib/integrations.mjs').LoadedIntegration[]} */ (
59
+ /** @type {import('../../lib/integrations.mjs').LoadedIntegration[]} */ (
60
60
  project.loadedIntegrations
61
61
  );
62
62
  /** @param {ScannedPackage} pkg */
@@ -194,7 +194,7 @@ export async function discover(query, options = {}) {
194
194
  * @param {string} compName
195
195
  * @param {string} pkgName
196
196
  * @param {{lang?: string|null, zh?: boolean}} opts
197
- * @returns {Promise<import('../types/discover').DiscoverDetailDocResponse>}
197
+ * @returns {Promise<import('../../types/discover').DiscoverDetailDocResponse>}
198
198
  */
199
199
  async function resolveComponentDocs(packages, compName, pkgName, {lang, zh}) {
200
200
  const pkg = packages.find(p => p.name === pkgName);
@@ -234,7 +234,7 @@ async function resolveComponentDocs(packages, compName, pkgName, {lang, zh}) {
234
234
  /**
235
235
  * @param {{docPath: string, componentName: string, pkg: ScannedPackage}} result
236
236
  * @param {{lang?: string|null, zh?: boolean}} opts
237
- * @returns {Promise<import('../types/discover').DiscoverDetailDocResponse>}
237
+ * @returns {Promise<import('../../types/discover').DiscoverDetailDocResponse>}
238
238
  */
239
239
  async function loadAndValidate(result, {lang, zh}) {
240
240
  let docs;
@@ -7,9 +7,9 @@
7
7
  import * as fs from 'node:fs';
8
8
  import * as path from 'node:path';
9
9
  import {pathToFileURL} from 'node:url';
10
- import {CLI_ROOT} from '../utils/paths.mjs';
11
- import {AstryxError} from './error.mjs';
12
- import {ERROR_CODES} from '../lib/error-codes.mjs';
10
+ import {CLI_ROOT} from '../../utils/paths.mjs';
11
+ import {AstryxError} from '../error.mjs';
12
+ import {ERROR_CODES} from '../../lib/error-codes.mjs';
13
13
 
14
14
  const DOCS_DIR = path.join(CLI_ROOT, 'docs');
15
15
 
@@ -30,7 +30,7 @@ function discoverTopics() {
30
30
  /**
31
31
  * @param {string} docPath
32
32
  * @param {{lang?: string|null}} [opts]
33
- * @returns {Promise<import('../types/docs').DocsDetailResponse['data']>}
33
+ * @returns {Promise<import('../../types/docs').DocsDetailResponse['data']>}
34
34
  */
35
35
  async function loadReferenceDocs(docPath, {lang} = {}) {
36
36
  const mod = await import(pathToFileURL(docPath).href);
@@ -91,9 +91,9 @@ async function loadReferenceDocs(docPath, {lang} = {}) {
91
91
  /**
92
92
  * Resolve token-ref blocks by inlining the referenced section's table.
93
93
  * This allows section docs to reference token tables without duplicating data.
94
- * @param {import('../types/docs').DocsDetailResponse['data']} docsData
94
+ * @param {import('../../types/docs').DocsDetailResponse['data']} docsData
95
95
  * @param {Record<string, string>} topics
96
- * @returns {Promise<import('../types/docs').DocsDetailResponse['data']>}
96
+ * @returns {Promise<import('../../types/docs').DocsDetailResponse['data']>}
97
97
  */
98
98
  async function resolveTokenRefs(docsData, topics) {
99
99
  const resolved = {...docsData, sections: [...docsData.sections]};
@@ -148,9 +148,9 @@ async function resolveTokenRefs(docsData, topics) {
148
148
  * @param {boolean} [options.zh]
149
149
  * @param {boolean} [options.dense]
150
150
  * @returns {Promise<
151
- * import('../types/docs').DocsListResponse |
152
- * import('../types/docs').DocsDetailResponse |
153
- * import('../types/docs').DocsDetailSectionResponse
151
+ * import('../../types/docs').DocsListResponse |
152
+ * import('../../types/docs').DocsDetailResponse |
153
+ * import('../../types/docs').DocsDetailSectionResponse
154
154
  * >}
155
155
  */
156
156
  export async function docs(topic, section, options = {}) {
@@ -159,7 +159,7 @@ export async function docs(topic, section, options = {}) {
159
159
  const topics = discoverTopics();
160
160
 
161
161
  if (!topic) {
162
- /** @type {Array<import('../types/docs').DocsListEntry>} */
162
+ /** @type {Array<import('../../types/docs').DocsListEntry>} */
163
163
  const entries = [];
164
164
  for (const [name, docPath] of Object.entries(topics)) {
165
165
  try {
@@ -24,11 +24,11 @@ import * as fs from 'node:fs';
24
24
  import * as path from 'node:path';
25
25
  import {createRequire} from 'node:module';
26
26
 
27
- import {MIN_NODE_VERSION, isNodeVersionSupported} from '../lib/node-version.mjs';
28
- import {CLI_ROOT, findCoreDir} from '../utils/paths.mjs';
29
- import {detectPackageManager, getCliInvocation} from '../utils/package-manager.mjs';
30
- import {findConfigPath, Project} from '../lib/project.mjs';
31
- import {semverCompare} from '../utils/semver.mjs';
27
+ import {MIN_NODE_VERSION, isNodeVersionSupported} from '../../lib/node-version.mjs';
28
+ import {CLI_ROOT, findCoreDir} from '../../utils/paths.mjs';
29
+ import {detectPackageManager, getCliInvocation} from '../../utils/package-manager.mjs';
30
+ import {findConfigPath, Project} from '../../lib/project.mjs';
31
+ import {semverCompare} from '../../utils/semver.mjs';
32
32
 
33
33
  const _require = createRequire(import.meta.url);
34
34
 
@@ -7,12 +7,12 @@
7
7
  * The CLI command handler is a thin wrapper around this function.
8
8
  */
9
9
 
10
- import {findCoreDir} from '../utils/paths.mjs';
11
- import {discoverHooks, findHookDoc, getAllHookNames} from '../lib/hook-discovery.mjs';
12
- import {loadDocs} from '../lib/component-loader.mjs';
13
- import {levenshteinDistance} from '../lib/string-utils.mjs';
14
- import {AstryxError} from './error.mjs';
15
- import {ERROR_CODES} from '../lib/error-codes.mjs';
10
+ import {findCoreDir} from '../../utils/paths.mjs';
11
+ import {discoverHooks, findHookDoc, getAllHookNames} from '../../lib/hook-discovery.mjs';
12
+ import {loadDocs} from '../../lib/component-loader.mjs';
13
+ import {levenshteinDistance} from '../../lib/string-utils.mjs';
14
+ import {AstryxError} from '../error.mjs';
15
+ import {ERROR_CODES} from '../../lib/error-codes.mjs';
16
16
 
17
17
  /**
18
18
  * @param {string} [name]
@@ -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
  /**
@@ -94,7 +94,7 @@ function checkRoots(resolved, issues) {
94
94
  * Validate the integration's codemods via the landed discovery. Discovery is
95
95
  * strict (throws on bad export / duplicate id); we convert any throw into an
96
96
  * `invalid_codemod` error.
97
- * @param {import('../lib/integrations.mjs').LoadedIntegration} integration loaded-integration-shaped object
97
+ * @param {import('../../lib/integrations.mjs').LoadedIntegration} integration loaded-integration-shaped object
98
98
  * @param {Issue[]} issues
99
99
  */
100
100
  async function checkCodemods(integration, issues) {
@@ -109,7 +109,7 @@ async function checkCodemods(integration, issues) {
109
109
  /**
110
110
  * Validate the integration's templates via the landed discovery. Per-template
111
111
  * problems are reported as `invalid_template` errors.
112
- * @param {import('../lib/integrations.mjs').LoadedIntegration} integration loaded-integration-shaped object
112
+ * @param {import('../../lib/integrations.mjs').LoadedIntegration} integration loaded-integration-shaped object
113
113
  * @param {Issue[]} issues
114
114
  */
115
115
  async function checkTemplates(integration, issues) {
@@ -133,7 +133,7 @@ async function checkTemplates(integration, issues) {
133
133
  * `discoverIntegrationComponents` returns ownership records and does not throw
134
134
  * on a missing same-stem source — it records `sourcePath: null`. We surface
135
135
  * each such record as an `invalid_component` error.
136
- * @param {import('../lib/integrations.mjs').LoadedIntegration} integration loaded-integration-shaped object
136
+ * @param {import('../../lib/integrations.mjs').LoadedIntegration} integration loaded-integration-shaped object
137
137
  * @param {Issue[]} issues
138
138
  */
139
139
  async function checkComponents(integration, issues) {
@@ -159,7 +159,7 @@ async function checkComponents(integration, issues) {
159
159
 
160
160
  /**
161
161
  * Run every contribution validator against a loaded-integration-shaped object.
162
- * @param {import('../lib/integrations.mjs').LoadedIntegration} integration
162
+ * @param {import('../../lib/integrations.mjs').LoadedIntegration} integration
163
163
  * @param {Issue[]} issues
164
164
  */
165
165
  async function runContributionChecks(integration, issues) {
@@ -182,7 +182,7 @@ async function runContributionChecks(integration, issues) {
182
182
  * contribution checks (roots + codemods/templates/components) because those can
183
183
  * regress independently of the manifest (a deleted directory, a broken template).
184
184
  *
185
- * @param {import('../lib/integrations.mjs').LoadedIntegration} loaded loaded-integration-shaped object
185
+ * @param {import('../../lib/integrations.mjs').LoadedIntegration} loaded loaded-integration-shaped object
186
186
  * @returns {Promise<Issue[]>}
187
187
  */
188
188
  export async function validateLoadedIntegration(loaded) {
@@ -351,6 +351,34 @@ export async function validateInstalledIntegration(spec, cwd = process.cwd()) {
351
351
  });
352
352
  }
353
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
+
354
382
  /**
355
383
  * Summarize issues by severity.
356
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(() => {