@astryxdesign/cli 0.6.4-canary.f0355e3 → 0.6.4

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 (331) hide show
  1. package/README.md +96 -99
  2. package/api/build/build.doc.mjs +1 -6
  3. package/api/build/build.test.mjs +0 -22
  4. package/api/build/kit/kit.mjs +5 -44
  5. package/api/component/_adapter.d.mts +0 -25
  6. package/api/component/_adapter.mjs +5 -59
  7. package/api/component/component.d.mts +3 -6
  8. package/api/component/component.doc.mjs +17 -37
  9. package/api/component/component.mjs +9 -249
  10. package/api/component/component.type.d.mts +0 -25
  11. package/api/component/component.type.mjs +0 -44
  12. package/api/discover/_adapter.d.mts +6 -114
  13. package/api/discover/_adapter.mjs +17 -372
  14. package/api/discover/detail/detail.d.mts +6 -18
  15. package/api/discover/detail/detail.mjs +13 -67
  16. package/api/discover/detail/detail.test.mjs +0 -85
  17. package/api/discover/discover.d.mts +9 -3
  18. package/api/discover/discover.doc.mjs +18 -61
  19. package/api/discover/discover.mjs +36 -220
  20. package/api/discover/discover.test.mjs +2 -11
  21. package/api/discover/discover.type.d.mts +8 -147
  22. package/api/discover/discover.type.mjs +12 -102
  23. package/api/discover/list/list.d.mts +6 -20
  24. package/api/discover/list/list.mjs +12 -45
  25. package/api/discover/list/list.test.mjs +0 -46
  26. package/api/discover/search/search.d.mts +16 -18
  27. package/api/discover/search/search.mjs +56 -102
  28. package/api/discover/search/search.test.mjs +10 -144
  29. package/api/docs/_adapter.d.mts +3 -8
  30. package/api/docs/_adapter.mjs +6 -14
  31. package/api/docs/docOverlays.test.mjs +1 -27
  32. package/api/docs/docs.doc.mjs +2 -2
  33. package/api/docs/docs.test.mjs +243 -0
  34. package/api/docs/integration-tree.test.mjs +555 -0
  35. package/api/docs/integrationDocs.test.mjs +314 -0
  36. package/api/doctor/doctor.d.mts +3 -8
  37. package/api/doctor/doctor.doc.mjs +8 -17
  38. package/api/doctor/doctor.mjs +9 -90
  39. package/api/doctor/doctor.test.mjs +10 -122
  40. package/api/doctor/doctor.type.d.mts +1 -1
  41. package/api/doctor/doctor.type.mjs +1 -1
  42. package/api/gap-report/gap-report.doc.mjs +10 -19
  43. package/api/hook/hook.doc.mjs +3 -6
  44. package/api/index.d.mts +2 -1
  45. package/api/index.mjs +5 -5
  46. package/api/init/init.doc.mjs +12 -17
  47. package/api/integration/add-helpers.d.mts +2 -5
  48. package/api/integration/add-helpers.mjs +9 -36
  49. package/api/integration/add-theme.mjs +1 -22
  50. package/api/integration/add-theme.test.mjs +0 -34
  51. package/api/integration/authoring-checks.mjs +2 -2
  52. package/api/integration/integrationPackCheck.doc.mjs +3 -3
  53. package/api/integration/pack-check.mjs +9 -82
  54. package/api/integration/pack-check.test.mjs +0 -90
  55. package/api/integration/pack-check.type.mjs +1 -1
  56. package/api/json/assertResponse.doc.mjs +1 -1
  57. package/api/json/index.ts +1 -0
  58. package/api/json/isError.doc.mjs +1 -1
  59. package/api/layout/_adapter.d.mts +34 -0
  60. package/api/layout/_adapter.mjs +148 -0
  61. package/api/layout/check/check.d.mts +16 -0
  62. package/api/layout/check/check.mjs +40 -0
  63. package/api/layout/expand/expand.d.mts +22 -0
  64. package/api/layout/expand/expand.mjs +155 -0
  65. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  66. package/api/layout/grammar/grammar.d.mts +13 -0
  67. package/api/layout/grammar/grammar.mjs +87 -0
  68. package/api/layout/layout.d.mts +6 -0
  69. package/api/layout/layout.mjs +17 -0
  70. package/api/layout/layout.test.mjs +297 -0
  71. package/api/layout/layout.type.d.mts +89 -0
  72. package/api/layout/layout.type.mjs +103 -0
  73. package/api/layout/layoutCheck.doc.d.mts +11 -0
  74. package/api/layout/layoutCheck.doc.mjs +85 -0
  75. package/api/layout/layoutExpand.doc.d.mts +11 -0
  76. package/api/layout/layoutExpand.doc.mjs +107 -0
  77. package/api/layout/layoutGrammar.doc.d.mts +11 -0
  78. package/api/layout/layoutGrammar.doc.mjs +57 -0
  79. package/api/search/search.d.mts +1 -27
  80. package/api/search/search.doc.mjs +2 -2
  81. package/api/search/search.mjs +16 -228
  82. package/api/search/search.test.mjs +512 -0
  83. package/api/swizzle/swizzle.doc.mjs +5 -7
  84. package/api/template/copy/copy.mjs +1 -1
  85. package/api/template/copy/copy.test.mjs +0 -9
  86. package/api/template/template-integration.test.mjs +65 -1
  87. package/api/template/template.doc.mjs +1 -2
  88. package/api/template/template.mjs +1 -1
  89. package/api/theme/add/add.mjs +25 -17
  90. package/api/theme/add/add.staging.test.mjs +23 -40
  91. package/api/theme/build/build.family.test.mjs +12 -7
  92. package/api/theme/build/build.mjs +18 -8
  93. package/api/theme/generateTonalPalette.doc.mjs +2 -1
  94. package/api/theme/listThemes.doc.mjs +1 -1
  95. package/api/theme/themeAdd.doc.mjs +10 -9
  96. package/api/theme/themeBuild.doc.mjs +13 -13
  97. package/api/theme/themeList.doc.mjs +1 -1
  98. package/api/theme/themeListAvailable.doc.mjs +1 -2
  99. package/api/theme/themePaletteGenerate.doc.mjs +8 -15
  100. package/api/theme/themeTargets.doc.mjs +2 -3
  101. package/api/theme/themeTemplate.doc.mjs +1 -2
  102. package/api/upgrade/run/run.mjs +4 -6
  103. package/api/upgrade/upgrade.doc.mjs +22 -24
  104. package/api/upgrade/upgrade.type.mjs +2 -2
  105. package/assets/codemods/__tests__/runner.test.mjs +1 -3
  106. package/assets/codemods/integration-runner.mjs +3 -3
  107. package/assets/codemods/runner.mjs +4 -5
  108. package/assets/docs/README.md +2 -4
  109. package/assets/docs/browser-support.doc.mjs +11 -11
  110. package/assets/docs/color.doc.mjs +2 -8
  111. package/assets/docs/elevation.doc.mjs +4 -6
  112. package/assets/docs/getting-started.doc.mjs +16 -5
  113. package/assets/docs/icons.doc.mjs +21 -2
  114. package/assets/docs/illustrations.doc.mjs +15 -7
  115. package/assets/docs/internationalization.doc.mjs +5 -7
  116. package/assets/docs/layout.doc.dense.mjs +82 -130
  117. package/assets/docs/layout.doc.mjs +77 -133
  118. package/assets/docs/migration.doc.mjs +21 -19
  119. package/assets/docs/motion.doc.mjs +3 -16
  120. package/assets/docs/principles.doc.dense.mjs +5 -5
  121. package/assets/docs/principles.doc.mjs +0 -8
  122. package/assets/docs/principles.doc.zh.mjs +6 -6
  123. package/assets/docs/shape.doc.mjs +3 -8
  124. package/assets/docs/spacing.doc.mjs +2 -7
  125. package/assets/docs/styling-libraries.doc.mjs +2 -6
  126. package/assets/docs/styling.doc.mjs +23 -19
  127. package/assets/docs/theme.doc.dense.mjs +18 -58
  128. package/assets/docs/theme.doc.mjs +46 -56
  129. package/assets/docs/theme.doc.zh.mjs +8 -9
  130. package/assets/docs/tokens.doc.dense.mjs +2 -2
  131. package/assets/docs/tokens.doc.mjs +8 -389
  132. package/assets/docs/tokens.doc.zh.mjs +2 -2
  133. package/assets/docs/tree/integrations.doc.mjs +451 -25
  134. package/assets/docs/tree/integrations.test.mjs +62 -0
  135. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  136. package/assets/docs/typography.doc.mjs +4 -24
  137. package/assets/docs/working-with-ai.doc.mjs +22 -30
  138. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  139. package/authoring/config/config.doc.mjs +2 -10
  140. package/authoring/config/parse.d.mts +0 -2
  141. package/authoring/config/parse.mjs +0 -19
  142. package/authoring/config/parse.test.mjs +0 -8
  143. package/authoring/config/type.ts +2 -13
  144. package/authoring/doctypes/_schema.d.mts +2 -3
  145. package/authoring/doctypes/_schema.mjs +0 -6
  146. package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
  147. package/authoring/doctypes/base/type.ts +2 -4
  148. package/authoring/doctypes/command/command.doc.mjs +1 -1
  149. package/authoring/doctypes/command/type.ts +1 -1
  150. package/authoring/doctypes/component/component.doc.mjs +0 -6
  151. package/authoring/doctypes/component/type.ts +0 -8
  152. package/authoring/doctypes/reference/reference.doc.mjs +0 -7
  153. package/authoring/doctypes/reference/type.ts +0 -5
  154. package/authoring/doctypes/schema/schema.doc.mjs +2 -2
  155. package/authoring/doctypes/template/template.doc.mjs +1 -1
  156. package/authoring/doctypes/template/type.ts +2 -2
  157. package/authoring/index.d.mts +0 -1
  158. package/authoring/index.d.ts +0 -10
  159. package/authoring/index.mjs +0 -1
  160. package/authoring/integration/integration.doc.mjs +10 -12
  161. package/clients/cli/command-result-coverage.test.mjs +7 -7
  162. package/clients/cli/commands/component/index.mjs +55 -152
  163. package/clients/cli/commands/component-ownership.test.mjs +0 -89
  164. package/clients/cli/commands/component.doc.mjs +9 -27
  165. package/clients/cli/commands/debug-result-summary.test.mjs +2 -2
  166. package/clients/cli/commands/discover.doc.mjs +9 -53
  167. package/clients/cli/commands/discover.mjs +118 -393
  168. package/clients/cli/commands/docs.doc.mjs +1 -1
  169. package/clients/cli/commands/docs.mjs +17 -60
  170. package/clients/cli/commands/docs.test.mjs +294 -0
  171. package/clients/cli/commands/doctor-integration-docs.doc.mjs +2 -3
  172. package/clients/cli/commands/doctor-integration.test.mjs +0 -53
  173. package/clients/cli/commands/doctor.doc.mjs +1 -3
  174. package/clients/cli/commands/doctor.mjs +5 -49
  175. package/clients/cli/commands/gap-report.doc.mjs +9 -10
  176. package/clients/cli/commands/init.doc.mjs +6 -9
  177. package/clients/cli/commands/integration-add.doc.mjs +9 -9
  178. package/clients/cli/commands/integration-authoring.test.mjs +10 -61
  179. package/clients/cli/commands/integration-pack.doc.mjs +9 -5
  180. package/clients/cli/commands/integration-real-world.test.mjs +1 -1
  181. package/clients/cli/commands/integration.doc.mjs +4 -4
  182. package/clients/cli/commands/integration.mjs +43 -74
  183. package/clients/cli/commands/layout-check.doc.mjs +65 -0
  184. package/clients/cli/commands/layout-expand.doc.mjs +83 -0
  185. package/clients/cli/commands/layout-grammar.doc.mjs +30 -0
  186. package/clients/cli/commands/layout.doc.mjs +34 -0
  187. package/clients/cli/commands/layout.error-codes.test.mjs +66 -0
  188. package/clients/cli/commands/layout.exit-parity.test.mjs +41 -0
  189. package/clients/cli/commands/layout.mjs +275 -0
  190. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  191. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  192. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  193. package/clients/cli/commands/manifest.doc.mjs +1 -1
  194. package/clients/cli/commands/search.doc.mjs +3 -10
  195. package/clients/cli/commands/search.mjs +2 -21
  196. package/clients/cli/commands/search.test.mjs +4 -21
  197. package/clients/cli/commands/swizzle.doc.mjs +1 -1
  198. package/clients/cli/commands/template.doc.mjs +1 -1
  199. package/clients/cli/commands/text-json-parity.test.mjs +16 -5
  200. package/clients/cli/commands/theme-add.doc.mjs +1 -1
  201. package/clients/cli/commands/theme-palette-generate.doc.mjs +2 -3
  202. package/clients/cli/commands/theme-palette.doc.mjs +2 -1
  203. package/clients/cli/commands/theme-targets.doc.mjs +2 -2
  204. package/clients/cli/commands/theme.doc.mjs +1 -2
  205. package/clients/cli/commands/upgrade.doc.mjs +3 -62
  206. package/clients/cli/index.mjs +10 -28
  207. package/clients/cli/lib/define-command.mjs +4 -28
  208. package/clients/cli/lib/define-command.test.mjs +0 -54
  209. package/clients/cli/lib/exit-codes.test.mjs +9 -18
  210. package/clients/cli/lib/json-shim.mjs +14 -24
  211. package/clients/cli/lib/json-shim.test.mjs +20 -6
  212. package/clients/cli/lib/manifest.mjs +13 -18
  213. package/clients/cli/lib/manifest.test.mjs +2 -5
  214. package/foundation/agent-docs/agent-docs.mjs +1 -1
  215. package/foundation/agent-docs/agent-docs.test.mjs +1159 -0
  216. package/foundation/discovery/authoring-self-docs.mjs +0 -1
  217. package/foundation/discovery/authoring-self-docs.test.mjs +2 -6
  218. package/foundation/discovery/cli-self-docs.mjs +2 -16
  219. package/foundation/discovery/cli-self-docs.test.mjs +0 -20
  220. package/foundation/discovery/docs-discovery.mjs +1 -5
  221. package/foundation/discovery/docs-discovery.test.mjs +0 -21
  222. package/foundation/discovery/docs-section-key.d.mts +1 -1
  223. package/foundation/discovery/docs-section-key.mjs +1 -1
  224. package/foundation/discovery/template-adapter.mjs +1 -1
  225. package/foundation/doc-compiler/doc-loads.test.mjs +14 -3
  226. package/foundation/doc-compiler/tree.d.mts +0 -4
  227. package/foundation/doc-compiler/tree.mjs +1 -6
  228. package/foundation/doc-compiler/tree.test.mjs +598 -0
  229. package/foundation/integrations/cli-requirement.d.mts +6 -26
  230. package/foundation/integrations/cli-requirement.mjs +11 -46
  231. package/foundation/integrations/cli-requirement.test.mjs +2 -7
  232. package/foundation/integrations/contribution-inventory.mjs +1 -1
  233. package/foundation/integrations/integrations.d.mts +1 -14
  234. package/foundation/integrations/integrations.mjs +1 -41
  235. package/foundation/integrations/integrations.test.mjs +0 -31
  236. package/foundation/response/error-codes.doc.mjs +8 -6
  237. package/foundation/response/error-codes.test.mjs +5 -30
  238. package/foundation/response/response-types.doc.d.mts +3 -4
  239. package/foundation/response/response-types.doc.mjs +27 -40
  240. package/foundation/response/response-types.doc.test.mjs +0 -23
  241. package/foundation/response/response.doc.mjs +10 -11
  242. package/foundation/xle/browser.d.mts +3 -3
  243. package/foundation/xle/browser.mjs +3 -3
  244. package/foundation/xle/expand.mjs +2 -2
  245. package/foundation/xle/parse.mjs +1 -1
  246. package/foundation/xle/print.mjs +2 -2
  247. package/foundation/xle/splice.mjs +1 -1
  248. package/package.json +9 -9
  249. package/api/discover/_adapter.test.mjs +0 -215
  250. package/api/discover/_catalog-view.d.mts +0 -115
  251. package/api/discover/_catalog-view.mjs +0 -203
  252. package/api/discover/_catalog-view.test.mjs +0 -128
  253. package/api/discover/detail/item/item.d.mts +0 -26
  254. package/api/discover/detail/item/item.mjs +0 -78
  255. package/api/discover/detail/item/item.test.mjs +0 -73
  256. package/api/integration/pack-check.lifecycle-output.test.mjs +0 -107
  257. package/api/theme/add/add.rollback.test.mjs +0 -158
  258. package/api/theme/build/build.rollback.test.mjs +0 -148
  259. package/api/upgrade/run/files-changed.test.mjs +0 -111
  260. package/assets/codemods/file-count.test.mjs +0 -163
  261. package/assets/docs/tree/add-a-component.doc.mjs +0 -75
  262. package/assets/docs/tree/add-a-theme.doc.mjs +0 -85
  263. package/assets/docs/tree/add-a-topic.doc.mjs +0 -144
  264. package/assets/docs/tree/agent-guidance.doc.mjs +0 -138
  265. package/assets/docs/tree/block-template.doc.mjs +0 -130
  266. package/assets/docs/tree/build-the-template.doc.mjs +0 -28
  267. package/assets/docs/tree/building-blocks.doc.mjs +0 -46
  268. package/assets/docs/tree/check-your-docs.doc.mjs +0 -137
  269. package/assets/docs/tree/checks.doc.mjs +0 -119
  270. package/assets/docs/tree/codemods.doc.mjs +0 -147
  271. package/assets/docs/tree/component-family.doc.mjs +0 -113
  272. package/assets/docs/tree/component-imports.doc.mjs +0 -69
  273. package/assets/docs/tree/component-lookups.doc.mjs +0 -149
  274. package/assets/docs/tree/components.doc.mjs +0 -23
  275. package/assets/docs/tree/configuration.doc.mjs +0 -23
  276. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +0 -182
  277. package/assets/docs/tree/define-the-theme.doc.mjs +0 -118
  278. package/assets/docs/tree/describe-the-component.doc.mjs +0 -57
  279. package/assets/docs/tree/docs.doc.mjs +0 -21
  280. package/assets/docs/tree/document-the-template.doc.mjs +0 -28
  281. package/assets/docs/tree/document-the-theme.doc.mjs +0 -68
  282. package/assets/docs/tree/export-template-assets.doc.mjs +0 -147
  283. package/assets/docs/tree/extend-or-replace.doc.mjs +0 -103
  284. package/assets/docs/tree/fonts-and-assets.doc.mjs +0 -106
  285. package/assets/docs/tree/generate-a-palette.doc.mjs +0 -66
  286. package/assets/docs/tree/grade-template-with-agent.doc.mjs +0 -105
  287. package/assets/docs/tree/help.doc.mjs +0 -16
  288. package/assets/docs/tree/links.doc.mjs +0 -98
  289. package/assets/docs/tree/package-and-test.doc.mjs +0 -32
  290. package/assets/docs/tree/page-template.doc.mjs +0 -71
  291. package/assets/docs/tree/publishing.doc.mjs +0 -111
  292. package/assets/docs/tree/quick-start.doc.mjs +0 -272
  293. package/assets/docs/tree/replace-a-core-component.doc.mjs +0 -104
  294. package/assets/docs/tree/replace-a-core-template.doc.mjs +0 -172
  295. package/assets/docs/tree/sections-and-placement.doc.mjs +0 -108
  296. package/assets/docs/tree/see-it-in-an-app.doc.mjs +0 -59
  297. package/assets/docs/tree/ship.doc.mjs +0 -16
  298. package/assets/docs/tree/short-and-findable.doc.mjs +0 -108
  299. package/assets/docs/tree/single-component.doc.mjs +0 -165
  300. package/assets/docs/tree/start-a-template.doc.mjs +0 -143
  301. package/assets/docs/tree/subcomponent.doc.mjs +0 -115
  302. package/assets/docs/tree/template-assets.doc.mjs +0 -64
  303. package/assets/docs/tree/template-doc-overview.doc.mjs +0 -109
  304. package/assets/docs/tree/template-fonts.doc.mjs +0 -102
  305. package/assets/docs/tree/template-grading-rubric.doc.mjs +0 -452
  306. package/assets/docs/tree/template-icons.doc.mjs +0 -97
  307. package/assets/docs/tree/template-images-media.doc.mjs +0 -127
  308. package/assets/docs/tree/template-styles.doc.mjs +0 -93
  309. package/assets/docs/tree/templates.doc.mjs +0 -34
  310. package/assets/docs/tree/test-in-an-app.doc.mjs +0 -115
  311. package/assets/docs/tree/test-template-in-app.doc.mjs +0 -128
  312. package/assets/docs/tree/themes.doc.mjs +0 -39
  313. package/assets/docs/tree/troubleshooting.doc.mjs +0 -149
  314. package/assets/docs/tree/upgrading.doc.mjs +0 -103
  315. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +0 -51
  316. package/assets/docs/tree/verify-packed-template.doc.mjs +0 -77
  317. package/assets/docs/tree/versioning.doc.mjs +0 -161
  318. package/assets/docs/tree/write-good-templates.doc.mjs +0 -64
  319. package/assets/docs/tree/write-the-template-file.doc.mjs +0 -154
  320. package/authoring/discover/discover.doc.d.mts +0 -13
  321. package/authoring/discover/discover.doc.mjs +0 -138
  322. package/authoring/discover/parse.d.mts +0 -24
  323. package/authoring/discover/parse.mjs +0 -128
  324. package/authoring/discover/parse.test.mjs +0 -124
  325. package/authoring/discover/type.ts +0 -87
  326. package/clients/cli/commands/component-batch.test.mjs +0 -341
  327. package/clients/cli/commands/discover.sources.test.mjs +0 -267
  328. package/clients/cli/commands/integration-verify.doc.mjs +0 -22
  329. package/clients/cli/lib/parse-error-format.test.mjs +0 -81
  330. package/foundation/response/batch.type.d.mts +0 -33
  331. package/foundation/response/batch.type.mjs +0 -34
@@ -1,87 +1,33 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
3
  /**
4
- * @file discover.detail leaf — one package: what it adds, and, when a discover
5
- * source knows it, every version and the latest one.
4
+ * @file discover.detail leaf — browse one external package (@scope/name).
6
5
  *
7
- * @position api/discover/detail — pure projection over the packages and catalog
8
- * entry resolved by ../_adapter; throws AstryxError (ERR_UNKNOWN_PACKAGE) for
9
- * a package neither the project nor any source knows.
6
+ * @position api/discover/detail — pure projection over the packages resolved by
7
+ * ../_adapter; throws AstryxError (ERR_UNKNOWN_PACKAGE) for an unknown scope.
10
8
  */
11
9
 
12
10
  import {toEntry} from '../_adapter.mjs';
13
- import {catalogEntry, defaultVersion} from '../_catalog-view.mjs';
14
11
  import {AstryxError} from '../../error.mjs';
15
12
  import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
16
13
 
17
14
  /**
18
- * Build the discover.detail response for one package. The project's installed
19
- * copy describes itself; any other version is described by its source. For a
20
- * package the project does not have, `install` is the package-manager command
21
- * that adds it — printed, never run.
15
+ * Build the discover.detail response for a scoped package name. Throws
16
+ * AstryxError (ERR_UNKNOWN_PACKAGE) — with the available packages as
17
+ * suggestions — when no package matches.
22
18
  *
23
- * @param {import('../_adapter.mjs').InstalledPackage[]} packages
24
- * @param {string} name package name, e.g. `@scope/name`
25
- * @param {{
26
- * catalog?: import('../_catalog-view.mjs').CatalogPackage,
27
- * version?: string,
28
- * add?: (name: string, version?: string) => string,
29
- * installedAs?: string,
30
- * }} [options]
19
+ * @param {import('../_package-scanner.mjs').ScannedPackage[]} packages
20
+ * @param {string} query scoped package name, e.g. `@scope/name`
31
21
  * @returns {import('../discover.type.mjs').DiscoverDetailResponse}
32
22
  */
33
- export function detail(packages, name, options = {}) {
34
- const {catalog, version, add, installedAs} = options;
35
- const pkg = packages.find(p => p.name === name);
36
- if (!pkg && !catalog) {
23
+ export function detail(packages, query) {
24
+ const pkg = packages.find(p => p.name === query);
25
+ if (!pkg) {
37
26
  throw new AstryxError(
38
- `Package "${name}" not found`,
27
+ `Package "${query}" not found`,
39
28
  packages.map(p => ({name: p.name, reason: 'available package'})),
40
29
  ERROR_CODES.ERR_UNKNOWN_PACKAGE,
41
30
  );
42
31
  }
43
-
44
- const known = new Set([
45
- ...(catalog?.versions.map(v => v.version) ?? []),
46
- ...(pkg?.version ? [pkg.version] : []),
47
- ]);
48
- if (version && !known.has(version)) {
49
- const releases = catalog?.versions.filter(v => !v.prerelease) ?? [];
50
- throw new AstryxError(
51
- `Version "${version}" of ${name} not found`,
52
- (releases.length > 0 ? releases.map(v => v.version) : [...known])
53
- .slice(0, 5)
54
- .map(v => ({name: `${name}@${v}`, reason: 'published version'})),
55
- ERROR_CODES.ERR_NOT_FOUND,
56
- );
57
- }
58
-
59
- const local = pkg != null && (!version || version === pkg.version);
60
- /** @type {Record<string, unknown>} */
61
- const data = local
62
- ? {...toEntry(pkg), installed: true}
63
- : {
64
- ...catalogEntry(
65
- /** @type {NonNullable<typeof catalog>} */ (catalog),
66
- version ?? defaultVersion(/** @type {NonNullable<typeof catalog>} */ (catalog)),
67
- ),
68
- installed: pkg != null,
69
- ...(pkg?.version ? {installedVersion: pkg.version} : {}),
70
- };
71
- if (catalog) {
72
- if (catalog.latest) data.latest = catalog.latest;
73
- if (catalog.aliases.length > 0) data.aliases = catalog.aliases;
74
- data.source = catalog.source;
75
- }
76
- if (!pkg) {
77
- if (installedAs) data.installedAs = installedAs;
78
- else if (add) data.install = add(name, version);
79
- }
80
- if (catalog) data.versions = catalog.versions;
81
- return {
82
- type: 'discover.detail',
83
- data: /** @type {import('../discover.type.mjs').DiscoverDetailResponse['data']} */ (
84
- data
85
- ),
86
- };
32
+ return {type: 'discover.detail', data: toEntry(pkg)};
87
33
  }
@@ -36,7 +36,6 @@ describe('discover.detail leaf', () => {
36
36
  category: '@acme/widgets',
37
37
  components: ['Alpha', 'Beta'],
38
38
  version: '1.2.3',
39
- installed: true,
40
39
  });
41
40
  });
42
41
 
@@ -56,87 +55,3 @@ describe('discover.detail leaf', () => {
56
55
  ]);
57
56
  });
58
57
  });
59
-
60
- describe('discover.detail leaf with a discover source', () => {
61
- /** @type {any} */
62
- const catalog = {
63
- package: '@acme/charts',
64
- integration: 'acme-charts',
65
- aliases: ['@acme/charts-legacy'],
66
- latest: '2.0.0',
67
- source: 'Acme',
68
- versions: [
69
- {version: '2.1.0-beta.1', publishedAt: '2026-09-30T00:00:00.000Z', prerelease: true, status: 'ok'},
70
- {version: '2.0.0', publishedAt: '2026-09-20T00:00:00.000Z', prerelease: false, status: 'ok'},
71
- {version: '1.0.0', publishedAt: null, prerelease: false, status: 'manifest_load_error'},
72
- ],
73
- contributions: [
74
- {kind: 'component', name: 'Chart'},
75
- {kind: 'template', name: 'pages/Report'},
76
- ],
77
- };
78
- /** @param {string} name @param {string} [version] */
79
- const add = (name, version) => `pnpm add ${version ? `${name}@${version}` : name}`;
80
-
81
- it('describes a package the project does not have, with the command that adds it', () => {
82
- expect(detail(PACKAGES, '@acme/charts', {catalog, add}).data).toEqual({
83
- name: '@acme/charts',
84
- category: '@acme/charts',
85
- components: ['Chart'],
86
- version: '2.0.0',
87
- templates: ['pages/Report'],
88
- installed: false,
89
- latest: '2.0.0',
90
- aliases: ['@acme/charts-legacy'],
91
- source: 'Acme',
92
- install: 'pnpm add @acme/charts',
93
- versions: catalog.versions,
94
- });
95
- });
96
-
97
- it('describes any version, prereleases included', () => {
98
- const {data} = detail(PACKAGES, '@acme/charts', {catalog, add, version: '2.1.0-beta.1'});
99
- expect(data.version).toBe('2.1.0-beta.1');
100
- expect(data.install).toBe('pnpm add @acme/charts@2.1.0-beta.1');
101
- });
102
-
103
- it('refuses a version that was never published, and suggests releases', () => {
104
- let err;
105
- try {
106
- detail(PACKAGES, '@acme/charts', {catalog, add, version: '3.0.0'});
107
- } catch (e) {
108
- err = e;
109
- }
110
- expect(err).toBeInstanceOf(AstryxError);
111
- expect(err.code).toBe('ERR_NOT_FOUND');
112
- expect(err.suggestions.map(s => s.name)).toEqual([
113
- '@acme/charts@2.0.0',
114
- '@acme/charts@1.0.0',
115
- ]);
116
- });
117
-
118
- it('names the package the project has instead of offering an alias', () => {
119
- const {data} = detail(PACKAGES, '@acme/charts', {
120
- catalog,
121
- add,
122
- installedAs: '@acme/charts-legacy',
123
- });
124
- expect(data.installedAs).toBe('@acme/charts-legacy');
125
- expect(data).not.toHaveProperty('install');
126
- });
127
-
128
- it("keeps describing the installed copy from the project, with the source's versions", () => {
129
- const {data} = detail(PACKAGES, '@acme/widgets', {
130
- catalog: {...catalog, package: '@acme/widgets', latest: '1.3.0'},
131
- add,
132
- });
133
- expect(data).toMatchObject({
134
- name: '@acme/widgets',
135
- components: ['Alpha', 'Beta'],
136
- version: '1.2.3',
137
- installed: true,
138
- latest: '1.3.0',
139
- });
140
- expect(data).not.toHaveProperty('install');
141
- });
142
- });
@@ -3,13 +3,19 @@
3
3
 
4
4
  /**
5
5
  * @param {string} [query]
6
- * @param {import('./discover.type.mjs').DiscoverOptions} [options]
6
+ * @param {object} [options]
7
+ * @param {boolean} [options.components]
8
+ * @param {string} [options.lang]
9
+ * @param {boolean} [options.zh]
7
10
  * @returns {Promise<
8
11
  * import('./discover.type.mjs').DiscoverListResponse |
9
12
  * import('./discover.type.mjs').DiscoverDetailResponse |
10
13
  * import('./discover.type.mjs').DiscoverDetailDocResponse |
11
- * import('./discover.type.mjs').DiscoverItemResponse |
12
14
  * import('./discover.type.mjs').DiscoverSearchResponse
13
15
  * >}
14
16
  */
15
- export function discover(query?: string, options?: import("./discover.type.mjs").DiscoverOptions): Promise<import("./discover.type.mjs").DiscoverListResponse | import("./discover.type.mjs").DiscoverDetailResponse | import("./discover.type.mjs").DiscoverDetailDocResponse | import("./discover.type.mjs").DiscoverItemResponse | import("./discover.type.mjs").DiscoverSearchResponse>;
17
+ export function discover(query?: string, options?: {
18
+ components?: boolean | undefined;
19
+ lang?: string | undefined;
20
+ zh?: boolean | undefined;
21
+ }): Promise<import("./discover.type.mjs").DiscoverListResponse | import("./discover.type.mjs").DiscoverDetailResponse | import("./discover.type.mjs").DiscoverDetailDocResponse | import("./discover.type.mjs").DiscoverSearchResponse>;
@@ -13,25 +13,22 @@ export const doc = {
13
13
  name: 'discover',
14
14
  namespace: 'cli/api',
15
15
  displayName: 'discover()',
16
- summary:
17
- 'Browse and search integrations: the ones a project has and, through discover sources, the ones it could add.',
16
+ summary: 'Browse and search components from configured external packages.',
18
17
  description:
19
- 'Lists the integrations a project loads and, when the project or an integration provides a discover source, ' +
20
- 'the packages it could add, with what each one adds per kind. An @scope/name query shows one package with every ' +
21
- 'version its source knows; @scope/name@version shows one version; @scope/name/Component returns an installed ' +
22
- "component's validated doc, and any other item path returns that item. A free-text term searches every item and " +
23
- 'package. Discover only reads: it prints the command that adds a package and never runs it.',
18
+ 'Explores components contributed by configured external packages and integrations ' +
19
+ 'the ones that declare a components root. With no query it lists those packages; ' +
20
+ 'an @scope/name query browses one package; @scope/name/Component (or a free-text ' +
21
+ "term that resolves to a single component) returns that component's validated doc; " +
22
+ 'a free-text term with several matches returns the candidate list.',
24
23
  importPath: '@astryxdesign/cli/api',
25
24
  signature:
26
- 'discover(query?: string, options?: DiscoverOptions): Promise<DiscoverListResponse | DiscoverDetailResponse | DiscoverDetailDocResponse | DiscoverItemResponse | DiscoverSearchResponse>',
25
+ 'discover(query?: string, options?: DiscoverOptions): Promise<DiscoverListResponse | DiscoverDetailResponse | DiscoverDetailDocResponse | DiscoverSearchResponse>',
27
26
  keywords: [
28
27
  'discover',
29
28
  'packages',
30
29
  'integrations',
31
30
  'external',
32
31
  'components',
33
- 'catalog',
34
- 'versions',
35
32
  'search',
36
33
  ],
37
34
  params: [
@@ -39,39 +36,13 @@ export const doc = {
39
36
  name: 'query',
40
37
  type: 'string',
41
38
  description:
42
- 'A package (@scope/name, optionally @version), an item path (@scope/name/<item>), or a free-text term. Omit to list packages.',
39
+ 'An @scope/name package, an @scope/name/Component path, or a free-text term. Omit to list all configured packages.',
43
40
  },
44
41
  {
45
42
  name: 'options.components',
46
43
  type: 'boolean',
47
44
  description:
48
- 'In the CLI package list, print every component, and every other item, of each package instead of the first 10. A display flag for the CLI renderer; the programmatic response is unchanged.',
49
- },
50
- {
51
- name: 'options.type',
52
- type: "'component' | 'template' | 'doc' | 'theme' | 'codemod' | 'agent-doc'",
53
- description:
54
- 'Only one kind: in the list, packages that add it; in a search, items of that kind.',
55
- },
56
- {
57
- name: 'options.installed',
58
- type: 'boolean',
59
- description:
60
- 'Only what the project has. Cannot be set with options.available.',
61
- default: 'false',
62
- },
63
- {
64
- name: 'options.available',
65
- type: 'boolean',
66
- description:
67
- 'Only what the project could add. Cannot be set with options.installed.',
68
- default: 'false',
69
- },
70
- {
71
- name: 'options.limit',
72
- type: 'number',
73
- description: 'Max number of search results, a positive integer.',
74
- default: '20',
45
+ 'In the CLI package list, print every component of each package instead of the first 10. A display flag for the CLI renderer; the programmatic response is unchanged.',
75
46
  },
76
47
  {
77
48
  name: 'options.lang',
@@ -89,27 +60,21 @@ export const doc = {
89
60
  {
90
61
  type: 'discover.list',
91
62
  description:
92
- 'The installed integrations (name, category, components, version, and a list per other kind they add). With a discover source, meta.available lists what the project could add and meta.sources reports each source. When the list is empty it carries meta.configured.',
63
+ 'The configured external packages (name, category, components, version, description). When empty it carries meta.configured to distinguish "nothing configured" from "configured but nothing discovered".',
93
64
  },
94
65
  {
95
66
  type: 'discover.detail',
96
- description:
97
- 'One package: what the shown version adds, whether the project has it, its versions and latest release when a source knows them, and the command that adds it when the project does not have it.',
67
+ description: 'A single package entry, for an @scope/name query.',
98
68
  },
99
69
  {
100
70
  type: 'discover.detail.doc',
101
71
  description:
102
- 'The validated ComponentDoc for one installed component, for an @scope/name/Component query.',
103
- },
104
- {
105
- type: 'discover.item',
106
- description:
107
- 'One item that is not an installed component: its kind, name, the package and version that add it, and whether the project has the package.',
72
+ 'The validated ComponentDoc for one external component: an @scope/name/Component query, or a free-text term that resolves to exactly one component.',
108
73
  },
109
74
  {
110
75
  type: 'discover.search',
111
76
  description:
112
- 'The query echoed back plus every matching item and package, each with its kind and whether the project has it, even when one name matches exactly or only one item matches; total is set when the limit cut the list.',
77
+ 'The query echoed back plus the matching {package, component} pairs, when a free-text term matches several components.',
113
78
  },
114
79
  ],
115
80
  throws: [
@@ -117,21 +82,17 @@ export const doc = {
117
82
  code: 'ERR_INVALID_ARGUMENT',
118
83
  when: 'the query is a non-string value, or a free-text search is run with an empty query',
119
84
  },
120
- {
121
- code: 'ERR_INVALID_OPTION',
122
- when: 'options.type is not a known kind, options.limit is not a positive integer, or options.installed and options.available are both set',
123
- },
124
85
  {
125
86
  code: 'ERR_UNKNOWN_PACKAGE',
126
- when: 'neither the project nor any discover source has the package',
87
+ when: 'the @scope/name package is not among the configured packages',
127
88
  },
128
89
  {
129
90
  code: 'ERR_UNKNOWN_COMPONENT',
130
- when: 'the item is not in the named package',
91
+ when: 'the component is not found in the named @scope/name package',
131
92
  },
132
93
  {
133
94
  code: 'ERR_NOT_FOUND',
134
- when: 'a free-text term matches nothing, or the requested version is not published',
95
+ when: 'a free-text term matches no component in any package',
135
96
  },
136
97
  {
137
98
  code: 'ERR_INVALID_DOC',
@@ -139,14 +100,10 @@ export const doc = {
139
100
  },
140
101
  ],
141
102
  examples: [
142
- {label: 'List packages', code: 'const {data, meta} = await discover();'},
103
+ {label: 'List packages', code: 'const {data} = await discover();'},
143
104
  {label: 'Browse a package', code: "await discover('@acme/ui');"},
144
- {label: 'One version', code: "await discover('@acme/ui@2.1.0');"},
145
105
  {label: 'Show a component doc', code: "await discover('@acme/ui/Button');"},
146
- {
147
- label: 'Search templates to add',
148
- code: "await discover('dashboard', {type: 'template', available: true});",
149
- },
106
+ {label: 'Free-text search', code: "await discover('button');"},
150
107
  ],
151
108
  command: 'discover',
152
109
  related: ['component', 'search', 'template'],
@@ -3,193 +3,55 @@
3
3
  /**
4
4
  * @file Programmatic API for the discover command — dispatcher + barrel.
5
5
  *
6
- * `discover()` browses the integrations a project has and, through discover
7
- * sources, the ones it could add. It only reads: the package manager installs.
8
- * Its job is to resolve the project and its sources (via ./_adapter) and route
9
- * to the leaf that owns each response shape:
6
+ * `discover()` keeps the exact same signature and response union it always had,
7
+ * so `api/index.mjs` and the CLI consumer are untouched. Its only job now is to
8
+ * discover the external packages (via ./_adapter) and route to the leaf that
9
+ * owns each response shape:
10
10
  *
11
- * discover -> ./list/list.mjs discover.list
12
- * discover <package>[@<version>] -> ./detail/detail.mjs discover.detail
13
- * discover <package>/<Component> -> ./detail/doc/doc.mjs discover.detail.doc
14
- * discover <package>/<item> -> ./detail/item/item.mjs discover.item
15
- * discover <words> -> ./search/search.mjs discover.search (always a list)
11
+ * discover.list -> ./list/list.mjs
12
+ * discover.detail -> ./detail/detail.mjs
13
+ * discover.detail.doc -> ./detail/doc/doc.mjs
14
+ * discover.search -> ./search/search.mjs
16
15
  *
17
- * Source results are additive: they ride in `meta.available`/`meta.sources`,
18
- * in extra fields, or as extra search matches, so every existing field keeps
19
- * its meaning.
20
- *
21
- * @position api/discover — thin router over ./_adapter, ./_catalog-view, and
22
- * the discover leaves.
16
+ * @position api/discover — thin router over ./_adapter + the discover leaves.
23
17
  */
24
18
 
25
- import {
26
- addCommand,
27
- callSources,
28
- declaredDependencies,
29
- describeInstalled,
30
- discoverPackages,
31
- findComponent,
32
- hasSources,
33
- } from './_adapter.mjs';
34
- import {
35
- availableEntries,
36
- catalogState,
37
- searchItems,
38
- withLatest,
39
- } from './_catalog-view.mjs';
19
+ import {discoverPackages} from './_adapter.mjs';
40
20
  import {list} from './list/list.mjs';
41
21
  import {detail} from './detail/detail.mjs';
42
- import {doc, docFromResult} from './detail/doc/doc.mjs';
43
- import {item} from './detail/item/item.mjs';
22
+ import {doc} from './detail/doc/doc.mjs';
44
23
  import {search} from './search/search.mjs';
45
24
  import {AstryxError} from '../error.mjs';
46
25
  import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
47
- import {levenshteinDistance} from '../../foundation/text/string-utils.mjs';
48
- import {DISCOVER_KINDS} from '../../authoring/discover/parse.mjs';
49
-
50
- const DEFAULT_LIMIT = 20;
51
-
52
- /** @type {import('./_adapter.mjs').CatalogResult} */
53
- const NO_CATALOG = {sources: [], packages: []};
54
-
55
- /**
56
- * Split a package-shaped query: `name`, `name@version`, or `name/item`, with an
57
- * optional `@scope/` prefix on the name.
58
- * @param {string} query
59
- * @returns {{scoped: boolean, name: string, version?: string, item?: string}}
60
- */
61
- function splitTarget(query) {
62
- const scoped = query.startsWith('@');
63
- const firstSlash = query.indexOf('/');
64
- let head = query;
65
- /** @type {string | undefined} */
66
- let rest;
67
- const split = scoped
68
- ? firstSlash < 0
69
- ? -1
70
- : query.indexOf('/', firstSlash + 1)
71
- : firstSlash;
72
- if (split > 0) {
73
- head = query.slice(0, split);
74
- rest = query.slice(split + 1) || undefined;
75
- }
76
- const at = head.indexOf('@', 1);
77
- return {
78
- scoped,
79
- name: at > 0 ? head.slice(0, at) : head,
80
- ...(at > 0 && head.slice(at + 1) ? {version: head.slice(at + 1)} : {}),
81
- ...(rest ? {item: rest} : {}),
82
- };
83
- }
84
-
85
- /**
86
- * @param {{type?: unknown, installed?: boolean, available?: boolean, limit?: unknown}} options
87
- */
88
- function checkOptions({type, installed, available, limit}) {
89
- if (
90
- type != null &&
91
- !(/** @type {readonly unknown[]} */ (DISCOVER_KINDS).includes(type))
92
- ) {
93
- throw new AstryxError(
94
- `Unknown --type "${String(type)}"`,
95
- DISCOVER_KINDS.map(kind => ({name: kind, reason: 'item kind'})),
96
- ERROR_CODES.ERR_INVALID_OPTION,
97
- );
98
- }
99
- if (installed && available) {
100
- throw new AstryxError(
101
- '--installed and --available cannot be used together',
102
- undefined,
103
- ERROR_CODES.ERR_INVALID_OPTION,
104
- );
105
- }
106
- if (
107
- limit != null &&
108
- !(typeof limit === 'number' && Number.isInteger(limit) && limit > 0)
109
- ) {
110
- throw new AstryxError(
111
- `--limit must be a positive integer, not "${String(limit)}"`,
112
- undefined,
113
- ERROR_CODES.ERR_INVALID_OPTION,
114
- );
115
- }
116
- }
117
-
118
- /**
119
- * Items a source lists for a package that look like the one asked for: names
120
- * that contain it, else the closest few by spelling.
121
- * @param {import('../../authoring/discover/type.js').DiscoverPackage} entry
122
- * @param {string} wanted
123
- * @returns {Array<{name: string, reason: string}>}
124
- */
125
- function similarItems(entry, wanted) {
126
- const lower = wanted.toLowerCase();
127
- const names = [...new Set(entry.contributions.map(c => c.name))];
128
- const hits = names.filter(name => name.toLowerCase().includes(lower));
129
- const picked =
130
- hits.length > 0
131
- ? hits.slice(0, 5)
132
- : names
133
- .map(name => ({
134
- name,
135
- distance: levenshteinDistance(lower, name.toLowerCase()),
136
- }))
137
- .filter(m => m.distance <= 3)
138
- .sort((a, b) => a.distance - b.distance)
139
- .slice(0, 5)
140
- .map(m => m.name);
141
- return picked.map(name => ({
142
- name: `${entry.package}/${name}`,
143
- reason: 'similar name',
144
- }));
145
- }
146
26
 
147
27
  /**
148
28
  * @param {string} [query]
149
- * @param {import('./discover.type.mjs').DiscoverOptions} [options]
29
+ * @param {object} [options]
30
+ * @param {boolean} [options.components]
31
+ * @param {string} [options.lang]
32
+ * @param {boolean} [options.zh]
150
33
  * @returns {Promise<
151
34
  * import('./discover.type.mjs').DiscoverListResponse |
152
35
  * import('./discover.type.mjs').DiscoverDetailResponse |
153
36
  * import('./discover.type.mjs').DiscoverDetailDocResponse |
154
- * import('./discover.type.mjs').DiscoverItemResponse |
155
37
  * import('./discover.type.mjs').DiscoverSearchResponse
156
38
  * >}
157
39
  */
158
40
  export async function discover(query, options = {}) {
159
- const {lang = null, zh = false, type, limit} = options;
160
- checkOptions(options);
161
- const only = options.installed
162
- ? /** @type {const} */ ('installed')
163
- : options.available
164
- ? /** @type {const} */ ('available')
165
- : undefined;
166
-
167
- const {packages: scanned, configured, project} = await discoverPackages();
168
- const withSources = hasSources(project);
169
- const packages = await describeInstalled(project, scanned);
170
- const declared = declaredDependencies(project);
171
- const add = addCommand(project);
41
+ const {lang = null, zh = false} = options;
42
+ const {packages, configured} = await discoverPackages();
172
43
 
173
- /** @param {{package?: string, version?: string}} [request] */
174
- const catalogFor = async request =>
175
- withSources ? await callSources(project, request) : NO_CATALOG;
44
+ // No discoverable packages — either nothing configured, or configured but
45
+ // empty. The list leaf owns the empty envelope + `configured` flag. This
46
+ // short-circuits before query parsing, exactly as the flat command did.
47
+ if (packages.length === 0) return list(packages, {configured});
176
48
 
177
- // No query, or nothing to look through: the list.
178
- if (!query || (packages.length === 0 && !withSources)) {
179
- if (!withSources) return list(packages, {configured, type, only});
180
- const catalog = await catalogFor();
181
- return list(withLatest(packages, catalog), {
182
- configured,
183
- type,
184
- only,
185
- available: availableEntries(catalog, packages, declared),
186
- sources: catalog.sources,
187
- });
188
- }
49
+ // No query: the full package list.
50
+ if (!query) return list(packages, {configured});
189
51
 
190
- // A non-string (truthy) query would crash the parsing below with a raw
191
- // TypeError (no ERR_* code → downgrades to ERR_UNKNOWN). The CLI only ever
192
- // passes a string, but the public API must fail with a code.
52
+ // A non-string (truthy) query would crash `.startsWith`/`.indexOf` below
53
+ // with a raw TypeError (no ERR_* code → downgrades to ERR_UNKNOWN). The CLI
54
+ // only ever passes a string, but the public API must fail with a code.
193
55
  if (typeof query !== 'string') {
194
56
  throw new AstryxError(
195
57
  `Invalid query "${String(query)}"`,
@@ -198,63 +60,17 @@ export async function discover(query, options = {}) {
198
60
  );
199
61
  }
200
62
 
201
- const target = splitTarget(query);
202
- const installedNames = new Set(packages.map(p => p.name));
203
-
204
- /**
205
- * One package, one version, or one item, once `target.name` is known to be
206
- * a package the project or a source has.
207
- * @param {import('./_adapter.mjs').CatalogResult} catalog
208
- */
209
- const packageView = async catalog => {
210
- const entry = catalog.packages.find(p => p.package === target.name);
211
- const installedAs = entry
212
- ? catalogState(entry, installedNames, declared).installedAs
213
- : undefined;
214
- const context = {catalog: entry, version: target.version, add, installedAs};
215
- if (!target.item) return detail(packages, target.name, context);
216
- const found = item(packages, target.name, target.item, context);
217
- if (found) return found;
218
- // Only an installed package has docs to fall back to. For one that is
219
- // only in a source, the item is what is unknown, not the package.
220
- if (entry && !packages.some(p => p.name === target.name)) {
221
- throw new AstryxError(
222
- `"${target.item}" not found in ${target.name}`,
223
- similarItems(entry, target.item),
224
- ERROR_CODES.ERR_UNKNOWN_COMPONENT,
225
- );
63
+ // Scoped package query: @scope/name or @scope/name/Component
64
+ if (query.startsWith('@')) {
65
+ const slashIdx = query.indexOf('/', query.indexOf('/') + 1);
66
+ if (slashIdx > 0) {
67
+ const pkgName = query.slice(0, slashIdx);
68
+ const compName = query.slice(slashIdx + 1);
69
+ return await doc(packages, pkgName, compName, {lang, zh});
226
70
  }
227
- return await doc(packages, target.name, target.item, {lang, zh});
228
- };
229
-
230
- // An installed component keeps resolving to its full doc, before any source
231
- // is asked anything.
232
- const installedPkg = packages.find(p => p.name === target.name);
233
- if (installedPkg && target.item && !target.version) {
234
- const resolved = findComponent([installedPkg], target.item);
235
- if (resolved) return await docFromResult(resolved, {lang, zh});
236
- }
237
-
238
- if (target.scoped) {
239
- return await packageView(
240
- await catalogFor({package: target.name, version: target.version}),
241
- );
242
- }
243
-
244
- const listing = await catalogFor();
245
- const isPackage =
246
- installedPkg != null ||
247
- listing.packages.some(p => p.package === target.name);
248
- if (isPackage && (target.version || target.item || target.name === query)) {
249
- return await packageView(
250
- await catalogFor({package: target.name, version: target.version}),
251
- );
71
+ return detail(packages, query);
252
72
  }
253
73
 
254
- return await search(packages, query, {
255
- items: searchItems(packages, listing, declared),
256
- type,
257
- only,
258
- limit: limit ?? DEFAULT_LIMIT,
259
- });
74
+ // Free-text search across all packages.
75
+ return await search(packages, query, {lang, zh});
260
76
  }