@astryxdesign/cli 0.7.2-canary.fe2c655 → 0.7.3-canary.02f5fe4

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 (694) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/README.md +216 -162
  3. package/api/build/_adapter.d.mts +66 -0
  4. package/api/build/_adapter.mjs +139 -4
  5. package/api/build/blocks/blocks.d.mts +92 -0
  6. package/api/build/blocks/blocks.mjs +528 -0
  7. package/api/build/blocks/blocks.test.mjs +238 -0
  8. package/api/build/blocks/blocks.weights.json +1 -0
  9. package/api/build/build.doc.mjs +4 -0
  10. package/api/build/build.mjs +25 -6
  11. package/api/build/build.type.mjs +1 -1
  12. package/api/build/help/help.mjs +1 -1
  13. package/api/build/kit/answer.d.mts +18 -0
  14. package/api/build/kit/answer.mjs +195 -0
  15. package/api/build/kit/answer.test.mjs +108 -0
  16. package/api/build/kit/kind.d.mts +25 -0
  17. package/api/build/kit/kind.mjs +170 -0
  18. package/api/build/kit/kit.d.mts +2 -4
  19. package/api/build/kit/kit.mjs +8 -406
  20. package/api/build/kit/rank.d.mts +3 -32
  21. package/api/build/kit/rank.mjs +25 -342
  22. package/api/build/kit/rank.test.mjs +2 -1
  23. package/api/build/kit/signals.d.mts +79 -0
  24. package/api/build/kit/signals.mjs +295 -0
  25. package/api/build/kit/start.d.mts +32 -0
  26. package/api/build/kit/start.mjs +163 -0
  27. package/api/build/kit/words.d.mts +72 -0
  28. package/api/build/kit/words.mjs +202 -0
  29. package/api/build/tree.d.mts +20 -0
  30. package/api/build/tree.mjs +53 -0
  31. package/api/build/tree.test.mjs +185 -0
  32. package/api/build/tree.weights.json +1 -0
  33. package/api/component/_adapter.d.mts +72 -1
  34. package/api/component/_adapter.mjs +251 -23
  35. package/api/component/component-replacement.test.mjs +1 -0
  36. package/api/component/component.doc.mjs +6 -1
  37. package/api/component/component.mjs +97 -16
  38. package/api/component/component.test.mjs +95 -0
  39. package/api/component/doc-links.test.mjs +386 -0
  40. package/api/component/integration-export-name.test.mjs +644 -0
  41. package/api/component/list/list.mjs +42 -4
  42. package/api/discover/_adapter.d.mts +131 -12
  43. package/api/discover/_adapter.mjs +520 -34
  44. package/api/discover/_adapter.test.mjs +641 -17
  45. package/api/discover/_catalog-view.d.mts +16 -5
  46. package/api/discover/_catalog-view.mjs +32 -8
  47. package/api/discover/detail/doc/doc.mjs +9 -1
  48. package/api/discover/discover.d.mts +11 -0
  49. package/api/discover/discover.doc.mjs +9 -7
  50. package/api/discover/discover.mjs +120 -19
  51. package/api/discover/discover.type.d.mts +20 -7
  52. package/api/discover/discover.type.mjs +17 -7
  53. package/api/discover/list/list.d.mts +4 -3
  54. package/api/discover/list/list.mjs +17 -10
  55. package/api/docs/_adapter.d.mts +76 -2
  56. package/api/docs/_adapter.mjs +630 -34
  57. package/api/docs/docs-homes.test.mjs +127 -0
  58. package/api/docs/docs.doc.mjs +5 -4
  59. package/api/docs/docs.mjs +2 -1
  60. package/api/docs/docs.test.mjs +39 -20
  61. package/api/docs/integration-tree.test.mjs +42 -20
  62. package/api/docs/integrationDocs.test.mjs +125 -1
  63. package/api/docs/list/list.mjs +12 -2
  64. package/api/docs/namespace-section.test.mjs +6 -6
  65. package/api/docs/reference-blocks.test.mjs +3 -5
  66. package/api/doctor/_adapter.d.mts +128 -0
  67. package/api/doctor/_adapter.mjs +253 -4
  68. package/api/doctor/doctor.d.mts +217 -0
  69. package/api/doctor/doctor.doc.mjs +3 -2
  70. package/api/doctor/doctor.mjs +691 -52
  71. package/api/doctor/doctor.test.mjs +267 -18
  72. package/api/doctor/release-checks.test.mjs +156 -0
  73. package/api/doctor/theme-checks.mjs +17 -4
  74. package/api/doctor/theme-checks.test.mjs +223 -7
  75. package/api/error.d.mts +10 -0
  76. package/api/error.mjs +25 -0
  77. package/api/gap-report/gap-report.d.mts +3 -0
  78. package/api/gap-report/gap-report.doc.mjs +11 -3
  79. package/api/gap-report/gap-report.mjs +219 -52
  80. package/api/gap-report/gap-report.test.mjs +233 -0
  81. package/api/gap-report/gap-report.type.d.mts +41 -0
  82. package/api/gap-report/gap-report.type.mjs +18 -0
  83. package/api/hook/_adapter.mjs +3 -11
  84. package/api/hook/hook.doc.mjs +4 -0
  85. package/api/hook/hook.mjs +1 -1
  86. package/api/hook/list/list.d.mts +1 -1
  87. package/api/index.d.mts +2 -0
  88. package/api/index.mjs +2 -0
  89. package/api/init/_adapter.d.mts +22 -0
  90. package/api/init/_adapter.mjs +59 -0
  91. package/api/init/init.d.mts +7 -5
  92. package/api/init/init.doc.mjs +45 -10
  93. package/api/init/init.mjs +28 -4
  94. package/api/init/init.test.mjs +18 -2
  95. package/api/init/init.type.d.mts +50 -5
  96. package/api/init/init.type.mjs +39 -5
  97. package/api/init/remove/remove.mjs +17 -4
  98. package/api/init/remove/remove.test.mjs +114 -2
  99. package/api/init/run/run.d.mts +1 -1
  100. package/api/init/run/run.mjs +86 -12
  101. package/api/init/user/user.d.mts +14 -0
  102. package/api/init/user/user.mjs +87 -0
  103. package/api/init/user/user.test.mjs +232 -0
  104. package/api/integration/_adapter.d.mts +53 -0
  105. package/api/integration/_adapter.mjs +132 -0
  106. package/api/integration/add-contribution.component-names.test.mjs +66 -0
  107. package/api/integration/add-contribution.mjs +8 -4
  108. package/api/integration/add-contribution.test.mjs +4 -2
  109. package/api/integration/authoring-checks.mjs +192 -14
  110. package/api/integration/authoring-checks.test.mjs +1028 -0
  111. package/api/integration/authoring-checks.type.d.mts +143 -0
  112. package/api/integration/authoring-checks.type.mjs +74 -2
  113. package/api/integration/check/check.d.mts +96 -0
  114. package/api/integration/check/check.mjs +357 -0
  115. package/api/integration/check/check.test.mjs +489 -0
  116. package/api/integration/integration-check.type.d.mts +118 -0
  117. package/api/integration/integration-check.type.mjs +84 -0
  118. package/api/integration/integrationCheck.doc.d.mts +10 -0
  119. package/api/integration/integrationCheck.doc.mjs +73 -0
  120. package/api/integration/integrationComponentConflicts.doc.mjs +45 -6
  121. package/api/integration/integrationDocConflicts.doc.mjs +22 -5
  122. package/api/integration/pack-check.mjs +486 -123
  123. package/api/integration/pack-check.test.mjs +817 -10
  124. package/api/integration/validate-integration-case-disk.test.mjs +111 -0
  125. package/api/integration/validate-integration-fixes.test.mjs +73 -5
  126. package/api/integration/validate-integration-gaps.test.mjs +1975 -0
  127. package/api/integration/validate-integration.d.mts +23 -2
  128. package/api/integration/validate-integration.mjs +358 -45
  129. package/api/integration/validate-integration.test.mjs +88 -8
  130. package/api/integration/validate-integration.type.d.mts +105 -0
  131. package/api/integration/validate-integration.type.mjs +79 -1
  132. package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
  133. package/api/integration/validateIntegration.doc.mjs +19 -3
  134. package/api/search/ORDERING.md +28 -0
  135. package/api/search/_adapter.d.mts +91 -0
  136. package/api/search/_adapter.mjs +172 -0
  137. package/api/search/_adapter.test.mjs +173 -0
  138. package/api/search/_candidate-score.d.mts +40 -0
  139. package/api/search/_candidate-score.mjs +238 -0
  140. package/api/search/_cards.json +6098 -0
  141. package/api/search/_compound.d.mts +50 -0
  142. package/api/search/_compound.mjs +170 -0
  143. package/api/search/_doc-searcher.d.mts +4 -0
  144. package/api/search/_doc-searcher.mjs +23 -0
  145. package/api/search/_doc-searcher.test.mjs +36 -0
  146. package/api/search/_doc-searcher.weights.json +1 -0
  147. package/api/search/_doc-text.d.mts +30 -0
  148. package/api/search/_doc-text.mjs +87 -0
  149. package/api/search/_entries.d.mts +63 -0
  150. package/api/search/_entries.mjs +232 -0
  151. package/api/search/_entries.test.mjs +48 -0
  152. package/api/search/_features.d.mts +35 -0
  153. package/api/search/_features.mjs +155 -0
  154. package/api/search/_gather-components.d.mts +26 -0
  155. package/api/search/_gather-components.mjs +284 -0
  156. package/api/search/_gather-docs.d.mts +20 -0
  157. package/api/search/_gather-docs.mjs +254 -0
  158. package/api/search/_gather-hooks.d.mts +12 -0
  159. package/api/search/_gather-hooks.mjs +52 -0
  160. package/api/search/_gather-templates.d.mts +25 -0
  161. package/api/search/_gather-templates.mjs +107 -0
  162. package/api/search/_lexical.d.mts +135 -0
  163. package/api/search/_lexical.mjs +351 -0
  164. package/api/search/_main-searcher.d.mts +19 -0
  165. package/api/search/_main-searcher.mjs +115 -0
  166. package/api/search/_main-searcher.test.mjs +106 -0
  167. package/api/search/_main-searcher.weights.json +1 -0
  168. package/api/search/_module-doc.d.mts +32 -0
  169. package/api/search/_module-doc.mjs +78 -0
  170. package/api/search/_order.d.mts +32 -0
  171. package/api/search/_order.mjs +162 -0
  172. package/api/search/_order.test.mjs +72 -0
  173. package/api/search/_priority.d.mts +50 -0
  174. package/api/search/_priority.mjs +139 -0
  175. package/api/search/_query-words.d.mts +25 -0
  176. package/api/search/_query-words.mjs +92 -0
  177. package/api/search/_query.d.mts +65 -0
  178. package/api/search/_query.mjs +176 -0
  179. package/api/search/_result.d.mts +97 -0
  180. package/api/search/_result.mjs +150 -0
  181. package/api/search/_score.d.mts +60 -0
  182. package/api/search/_score.mjs +283 -0
  183. package/api/search/_synonyms.d.mts +21 -0
  184. package/api/search/_synonyms.mjs +67 -0
  185. package/api/search/_template-searcher.d.mts +4 -0
  186. package/api/search/_template-searcher.mjs +23 -0
  187. package/api/search/_template-searcher.test.mjs +40 -0
  188. package/api/search/_template-searcher.weights.json +1 -0
  189. package/api/search/_titles.d.mts +33 -0
  190. package/api/search/_titles.mjs +65 -0
  191. package/api/search/_words.d.mts +64 -0
  192. package/api/search/_words.mjs +157 -0
  193. package/api/search/search.d.mts +22 -236
  194. package/api/search/search.doc.mjs +14 -7
  195. package/api/search/search.domain-priority.test.mjs +108 -18
  196. package/api/search/search.integration-check.test.mjs +24 -0
  197. package/api/search/search.mjs +59 -1904
  198. package/api/search/search.test.mjs +193 -15
  199. package/api/search/search.type.d.mts +20 -2
  200. package/api/search/search.type.mjs +12 -2
  201. package/api/search/tree.d.mts +15 -0
  202. package/api/search/tree.mjs +40 -0
  203. package/api/search/tree.test.mjs +66 -0
  204. package/api/search/tree.weights.json +1 -0
  205. package/api/swizzle/_adapter.mjs +2 -2
  206. package/api/swizzle/copy/copy.mjs +29 -15
  207. package/api/template/template-integration.test.mjs +1 -1
  208. package/api/template/template.mjs +5 -1
  209. package/api/template/template.test.mjs +120 -3
  210. package/api/theme/_adapter.d.mts +16 -0
  211. package/api/theme/_adapter.mjs +32 -5
  212. package/api/theme/build/build.d.mts +2 -1
  213. package/api/theme/build/build.family.test.mjs +64 -0
  214. package/api/theme/build/build.mjs +250 -38
  215. package/api/theme/build/build.packed-old-core.test.mjs +21 -3
  216. package/api/theme/build/font-warning.mjs +5 -3
  217. package/api/theme/build/font-warning.test.mjs +2 -1
  218. package/api/theme/remove/remove.test.mjs +2 -2
  219. package/api/theme/targets/targets.mjs +3 -10
  220. package/api/theme/themeBuild.doc.mjs +4 -4
  221. package/api/theme/themeTargets.doc.mjs +4 -0
  222. package/api/theme/use/use.test.mjs +1 -1
  223. package/api/upgrade/_adapter.d.mts +97 -11
  224. package/api/upgrade/_adapter.mjs +315 -32
  225. package/api/upgrade/registry/registry.d.mts +10 -4
  226. package/api/upgrade/registry/registry.mjs +33 -16
  227. package/api/upgrade/registry/registry.test.mjs +85 -0
  228. package/api/upgrade/run/cli-behind-core.test.mjs +438 -0
  229. package/api/upgrade/run/run.d.mts +4 -2
  230. package/api/upgrade/run/run.mjs +48 -4
  231. package/api/upgrade/run/run.test.mjs +417 -3
  232. package/api/upgrade/status/status.d.mts +21 -5
  233. package/api/upgrade/status/status.mjs +45 -8
  234. package/api/upgrade/upgrade.doc.mjs +16 -8
  235. package/api/upgrade/upgrade.mjs +18 -3
  236. package/api/upgrade/upgrade.test.mjs +194 -0
  237. package/api/upgrade/upgrade.type.d.mts +28 -3
  238. package/api/upgrade/upgrade.type.mjs +24 -7
  239. package/assets/codemods/__tests__/registry.test.mjs +1 -0
  240. package/assets/codemods/registry.mjs +1 -0
  241. package/assets/codemods/runner.mjs +7 -1
  242. package/assets/codemods/transforms/v0.7.0/__tests__/validate-data-token-ownership.test.mjs +11 -0
  243. package/assets/codemods/transforms/v0.7.0/validate-data-token-ownership.mjs +3 -3
  244. package/assets/codemods/transforms/v0.7.2/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +120 -0
  245. package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
  246. package/assets/codemods/transforms/v0.7.2/migrate-list-edge-compensation-to-edge.mjs +198 -0
  247. package/assets/discover/official-packages.json +367 -0
  248. package/assets/docs/README.md +10 -0
  249. package/assets/docs/author-a-theme.doc.mjs +5 -5
  250. package/assets/docs/browser-support.doc.mjs +1 -1
  251. package/assets/docs/getting-started.doc.mjs +26 -6
  252. package/assets/docs/is-my-code-good.doc.mjs +287 -0
  253. package/assets/docs/styling-overview.doc.mjs +1 -1
  254. package/assets/docs/theme.doc.dense.mjs +1 -1
  255. package/assets/docs/theme.doc.mjs +2 -2
  256. package/assets/docs/theme.doc.zh.mjs +1 -1
  257. package/assets/docs/tree/add-a-component.doc.mjs +22 -2
  258. package/assets/docs/tree/add-a-theme.doc.mjs +14 -4
  259. package/assets/docs/tree/add-a-topic.doc.mjs +54 -9
  260. package/assets/docs/tree/agent-guidance.doc.mjs +19 -5
  261. package/assets/docs/tree/api.doc.mjs +6 -0
  262. package/assets/docs/tree/authoring.doc.mjs +61 -0
  263. package/assets/docs/tree/block-template.doc.mjs +8 -20
  264. package/assets/docs/tree/build-the-template.doc.mjs +1 -1
  265. package/assets/docs/tree/building-blocks.doc.mjs +6 -2
  266. package/assets/docs/tree/check-the-props.doc.mjs +201 -0
  267. package/assets/docs/tree/check-your-docs.doc.mjs +69 -11
  268. package/assets/docs/tree/checks.doc.mjs +32 -24
  269. package/assets/docs/tree/ci-and-containers.doc.mjs +101 -0
  270. package/assets/docs/tree/cli-command.doc.mjs +142 -0
  271. package/assets/docs/tree/cli.doc.mjs +7 -1
  272. package/assets/docs/tree/codemods.doc.mjs +17 -7
  273. package/assets/docs/tree/commands.doc.mjs +7 -1
  274. package/assets/docs/tree/component-family.doc.mjs +8 -6
  275. package/assets/docs/tree/component-imports.doc.mjs +21 -3
  276. package/assets/docs/tree/components.doc.mjs +7 -1
  277. package/assets/docs/tree/computer-agent-guide.doc.mjs +160 -0
  278. package/assets/docs/tree/computer-integrations.doc.mjs +93 -0
  279. package/assets/docs/tree/configuration.doc.mjs +8 -4
  280. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +41 -22
  281. package/assets/docs/tree/define-the-theme.doc.mjs +7 -6
  282. package/assets/docs/tree/describe-the-component.doc.mjs +3 -3
  283. package/assets/docs/tree/docs.doc.mjs +9 -3
  284. package/assets/docs/tree/document-the-template.doc.mjs +1 -1
  285. package/assets/docs/tree/document-the-theme.doc.mjs +4 -4
  286. package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
  287. package/assets/docs/tree/extend-or-replace.doc.mjs +19 -9
  288. package/assets/docs/{authoring.doc.mjs → tree/field-reference.doc.mjs} +4 -3
  289. package/assets/docs/tree/fonts-and-assets.doc.mjs +3 -3
  290. package/assets/docs/tree/generate-a-palette.doc.mjs +8 -6
  291. package/assets/docs/tree/global-integrations.doc.mjs +124 -0
  292. package/assets/docs/tree/global.doc.mjs +131 -0
  293. package/assets/docs/tree/grade-template-with-agent.doc.mjs +5 -5
  294. package/assets/docs/tree/help.doc.mjs +2 -2
  295. package/assets/docs/tree/host-entry.doc.mjs +128 -0
  296. package/assets/docs/tree/install-once.doc.mjs +105 -0
  297. package/assets/docs/tree/layout-spacing.doc.mjs +2 -3
  298. package/assets/docs/tree/layout.doc.mjs +6 -6
  299. package/assets/docs/tree/links.doc.mjs +7 -6
  300. package/assets/docs/tree/migration-setup.doc.mjs +3 -2
  301. package/assets/docs/tree/migration-verification.doc.mjs +0 -1
  302. package/assets/docs/tree/migration.doc.mjs +0 -1
  303. package/assets/docs/tree/monorepos.doc.mjs +84 -0
  304. package/assets/docs/tree/package-and-test.doc.mjs +1 -1
  305. package/assets/docs/tree/page-template.doc.mjs +4 -8
  306. package/assets/docs/tree/problems.doc.mjs +205 -0
  307. package/assets/docs/tree/project-global-or-both.doc.mjs +131 -0
  308. package/assets/docs/tree/publishing.doc.mjs +6 -6
  309. package/assets/docs/tree/quick-start.doc.mjs +54 -28
  310. package/assets/docs/tree/reference.doc.mjs +192 -0
  311. package/assets/docs/tree/replace-a-core-component.doc.mjs +15 -7
  312. package/assets/docs/tree/replace-a-core-template.doc.mjs +10 -12
  313. package/assets/docs/tree/scaffold.doc.mjs +1 -1
  314. package/assets/docs/tree/sections-and-placement.doc.mjs +9 -11
  315. package/assets/docs/tree/see-it-in-an-app.doc.mjs +17 -5
  316. package/assets/docs/tree/ship.doc.mjs +2 -2
  317. package/assets/docs/tree/short-and-findable.doc.mjs +9 -8
  318. package/assets/docs/tree/single-component.doc.mjs +15 -6
  319. package/assets/docs/tree/start-a-template.doc.mjs +18 -8
  320. package/assets/docs/tree/subcomponent.doc.mjs +6 -6
  321. package/assets/docs/tree/template-assets.doc.mjs +2 -2
  322. package/assets/docs/tree/template-doc-overview.doc.mjs +6 -17
  323. package/assets/docs/tree/template-fonts.doc.mjs +1 -1
  324. package/assets/docs/tree/template-grading-rubric.doc.mjs +17 -38
  325. package/assets/docs/tree/template-icons.doc.mjs +1 -1
  326. package/assets/docs/tree/template-images-media.doc.mjs +1 -1
  327. package/assets/docs/tree/template-styles.doc.mjs +2 -2
  328. package/assets/docs/tree/templates.doc.mjs +7 -1
  329. package/assets/docs/tree/test-in-an-app.doc.mjs +7 -7
  330. package/assets/docs/tree/test-template-in-app.doc.mjs +5 -5
  331. package/assets/docs/tree/themes.doc.mjs +5 -1
  332. package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
  333. package/assets/docs/tree/tokens-data.doc.mjs +2 -2
  334. package/assets/docs/tree/troubleshooting.doc.mjs +29 -13
  335. package/assets/docs/tree/type-scale.doc.mjs +3 -3
  336. package/assets/docs/tree/uninstall.doc.mjs +109 -0
  337. package/assets/docs/tree/updates.doc.mjs +92 -0
  338. package/assets/docs/tree/upgrading.doc.mjs +6 -6
  339. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +15 -3
  340. package/assets/docs/tree/verify-packed-template.doc.mjs +3 -3
  341. package/assets/docs/tree/versioning.doc.mjs +14 -9
  342. package/assets/docs/tree/who-answers.doc.mjs +119 -0
  343. package/assets/docs/tree/write-good-templates.doc.mjs +1 -1
  344. package/assets/docs/tree/write-the-template-file.doc.mjs +7 -6
  345. package/assets/docs/use-a-theme.doc.mjs +2 -2
  346. package/assets/docs/use-integrations.doc.mjs +120 -0
  347. package/assets/docs/working-with-ai.doc.mjs +70 -13
  348. package/assets/templates/themes/butter/butterTheme.ts +4 -2
  349. package/assets/templates/themes/stone/stoneTheme.ts +4 -2
  350. package/assets/templates/themes/y2k/y2kTheme.ts +4 -2
  351. package/assets/theme.template.ts +1 -1
  352. package/authoring/codemod/codemod.doc.mjs +7 -3
  353. package/authoring/config/config.doc.mjs +9 -6
  354. package/authoring/config/type.ts +4 -2
  355. package/authoring/debug/parse.d.mts +5 -5
  356. package/authoring/discover/discover.doc.mjs +7 -1
  357. package/authoring/doctypes/_schema.d.mts +8 -3
  358. package/authoring/doctypes/_schema.mjs +1 -0
  359. package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
  360. package/authoring/doctypes/command/command.doc.mjs +20 -12
  361. package/authoring/doctypes/command/type.ts +14 -0
  362. package/authoring/doctypes/component/component.doc.mjs +30 -27
  363. package/authoring/doctypes/component/type.ts +21 -8
  364. package/authoring/doctypes/enum/enum.doc.mjs +7 -4
  365. package/authoring/doctypes/function/function.doc.mjs +9 -8
  366. package/authoring/doctypes/hook/hook.doc.mjs +5 -4
  367. package/authoring/doctypes/hook/type.ts +4 -0
  368. package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
  369. package/authoring/doctypes/reference/reference.doc.mjs +12 -11
  370. package/authoring/doctypes/schema/schema.doc.mjs +10 -10
  371. package/authoring/doctypes/template/integration-template.doc.d.mts +11 -0
  372. package/authoring/doctypes/template/integration-template.doc.mjs +49 -0
  373. package/authoring/doctypes/template/parse.d.mts +6 -2
  374. package/authoring/doctypes/template/parse.mjs +3 -1
  375. package/authoring/doctypes/template/template.doc.mjs +3 -3
  376. package/authoring/doctypes/template/type.ts +22 -0
  377. package/authoring/doctypes/theme/theme.doc.mjs +2 -2
  378. package/authoring/gap-report/gap-report.doc.mjs +2 -2
  379. package/authoring/identity/identity.doc.mjs +3 -3
  380. package/authoring/index.d.ts +2 -0
  381. package/authoring/integration/integration.doc.mjs +30 -6
  382. package/authoring/integration/parse.test.mjs +21 -0
  383. package/authoring/integration/schema.d.mts +16 -3
  384. package/authoring/integration/schema.mjs +34 -2
  385. package/authoring/integration/type.ts +13 -1
  386. package/clients/cli/bin/astryx.mjs +11 -65
  387. package/clients/cli/cli-command.test.mjs +166 -0
  388. package/clients/cli/command-result-coverage.test.mjs +6 -5
  389. package/clients/cli/commands/blog.doc.mjs +1 -0
  390. package/clients/cli/commands/build-theme.batch-report.test.mjs +17 -3
  391. package/clients/cli/commands/build-theme.color-scheme.test.mjs +1 -1
  392. package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
  393. package/clients/cli/commands/build-theme.path-safety.test.mjs +224 -6
  394. package/clients/cli/commands/build-theme.registry.test.mjs +5 -2
  395. package/clients/cli/commands/build.doc.mjs +1 -0
  396. package/clients/cli/commands/build.exit-codes-doc.test.mjs +4 -0
  397. package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
  398. package/clients/cli/commands/component.doc.mjs +1 -0
  399. package/clients/cli/commands/{component/index.mjs → component.mjs} +37 -37
  400. package/clients/cli/commands/component.test.mjs +6 -6
  401. package/clients/cli/commands/discover.broken-integration.test.mjs +11 -7
  402. package/clients/cli/commands/discover.doc.mjs +9 -1
  403. package/clients/cli/commands/discover.mjs +144 -93
  404. package/clients/cli/commands/discover.no-source.test.mjs +448 -33
  405. package/clients/cli/commands/discover.sources.test.mjs +20 -1
  406. package/clients/cli/commands/docs.doc.mjs +3 -2
  407. package/clients/cli/commands/docs.mjs +50 -20
  408. package/clients/cli/commands/docs.test.mjs +16 -16
  409. package/clients/cli/commands/doctor-integration-components.doc.mjs +19 -4
  410. package/clients/cli/commands/doctor-integration-docs.doc.mjs +20 -5
  411. package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -0
  412. package/clients/cli/commands/doctor-integration-validate.doc.mjs +22 -2
  413. package/clients/cli/commands/doctor-integration.test.mjs +936 -3
  414. package/clients/cli/commands/doctor.doc.mjs +12 -2
  415. package/clients/cli/commands/doctor.mjs +332 -7
  416. package/clients/cli/commands/doctor.test.mjs +75 -4
  417. package/clients/cli/commands/gap-report.doc.mjs +15 -2
  418. package/clients/cli/commands/gap-report.mjs +24 -2
  419. package/clients/cli/commands/gap-report.test.mjs +79 -0
  420. package/clients/cli/commands/hook.doc.mjs +1 -0
  421. package/clients/cli/commands/{hook/index.mjs → hook.mjs} +22 -22
  422. package/clients/cli/commands/import-hint-correctness.test.mjs +1 -1
  423. package/clients/cli/commands/init.behavior.test.mjs +235 -1
  424. package/clients/cli/commands/init.doc.mjs +55 -10
  425. package/clients/cli/commands/init.flag-help.test.mjs +1 -0
  426. package/clients/cli/commands/init.mjs +2 -2
  427. package/clients/cli/commands/integration-add.doc.mjs +7 -0
  428. package/clients/cli/commands/integration-authoring.test.mjs +49 -3
  429. package/clients/cli/commands/integration-check.doc.mjs +93 -0
  430. package/clients/cli/commands/integration-check.test.mjs +489 -0
  431. package/clients/cli/commands/integration-pack.doc.mjs +8 -1
  432. package/clients/cli/commands/integration-verify.doc.mjs +8 -1
  433. package/clients/cli/commands/integration.doc.mjs +6 -2
  434. package/clients/cli/commands/integration.mjs +119 -7
  435. package/clients/cli/commands/json-contract.test.mjs +11 -2
  436. package/clients/cli/commands/manifest.doc.mjs +2 -1
  437. package/clients/cli/commands/manifest.mjs +67 -0
  438. package/clients/cli/commands/outside-project.test.mjs +874 -0
  439. package/clients/cli/commands/postinstall.doc.mjs +23 -0
  440. package/clients/cli/commands/postinstall.mjs +31 -0
  441. package/clients/cli/commands/search.doc.mjs +1 -0
  442. package/clients/cli/commands/search.mjs +16 -11
  443. package/clients/cli/commands/search.test.mjs +429 -296
  444. package/clients/cli/commands/setup-nudge.test.mjs +180 -2
  445. package/clients/cli/commands/swizzle.doc.mjs +7 -0
  446. package/clients/cli/commands/swizzle.mjs +5 -3
  447. package/clients/cli/commands/swizzle.routing.test.mjs +19 -2
  448. package/clients/cli/commands/template.doc.mjs +1 -0
  449. package/clients/cli/commands/text-json-parity.test.mjs +5 -0
  450. package/clients/cli/commands/theme-add-lifecycle.test.mjs +3 -3
  451. package/clients/cli/commands/theme-add.doc.mjs +8 -1
  452. package/clients/cli/commands/theme-build.doc.mjs +3 -2
  453. package/clients/cli/commands/theme-eject.doc.mjs +1 -0
  454. package/clients/cli/commands/theme-list.behavior.test.mjs +6 -0
  455. package/clients/cli/commands/theme-list.doc.mjs +1 -0
  456. package/clients/cli/commands/theme-palette-generate.doc.mjs +1 -0
  457. package/clients/cli/commands/theme-remove.doc.mjs +7 -0
  458. package/clients/cli/commands/theme-targets.doc.mjs +1 -0
  459. package/clients/cli/commands/theme-template.doc.mjs +1 -0
  460. package/clients/cli/commands/theme-use.doc.mjs +7 -0
  461. package/clients/cli/commands/{build-theme.mjs → theme.mjs} +27 -14
  462. package/clients/cli/commands/upgrade.config-ordering.test.mjs +2 -1
  463. package/clients/cli/commands/upgrade.doc.mjs +26 -3
  464. package/clients/cli/commands/upgrade.file-protection.test.mjs +3 -2
  465. package/clients/cli/commands/upgrade.hook-output.test.mjs +2 -1
  466. package/clients/cli/commands/upgrade.mjs +9 -2
  467. package/clients/cli/commands/upgrade.older-cli.test.mjs +160 -0
  468. package/clients/cli/commands/upgrade.subfolder-path.test.mjs +97 -0
  469. package/clients/cli/index.mjs +156 -100
  470. package/clients/cli/lib/cli-error.mjs +4 -1
  471. package/clients/cli/lib/component-format.mjs +1 -1
  472. package/clients/cli/lib/component-format.test.mjs +1 -1
  473. package/clients/cli/lib/define-command.mjs +14 -9
  474. package/clients/cli/lib/exit-codes.test.mjs +5 -0
  475. package/clients/cli/lib/json-shim.mjs +3 -1
  476. package/clients/cli/lib/manifest.d.ts +9 -0
  477. package/clients/cli/lib/manifest.mjs +17 -1
  478. package/clients/cli/lib/manifest.test.mjs +37 -0
  479. package/clients/cli/lib/welcome-box.mjs +50 -0
  480. package/clients/cli/run.mjs +108 -0
  481. package/foundation/agent-docs/agent-doc-state.d.mts +67 -13
  482. package/foundation/agent-docs/agent-doc-state.mjs +123 -14
  483. package/foundation/agent-docs/agent-docs.d.mts +104 -15
  484. package/foundation/agent-docs/agent-docs.mjs +1028 -114
  485. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +1239 -17
  486. package/foundation/agent-docs/agent-docs.test.mjs +683 -39
  487. package/foundation/agent-docs/computer-agent-text.d.mts +170 -0
  488. package/foundation/agent-docs/computer-agent-text.mjs +750 -0
  489. package/foundation/agent-docs/computer-agent-text.test.mjs +699 -0
  490. package/foundation/config/project.d.mts +35 -3
  491. package/foundation/config/project.mjs +243 -26
  492. package/foundation/config/project.test.mjs +122 -0
  493. package/foundation/config/theme-state.mjs +5 -4
  494. package/foundation/discovery/authoring-self-docs.d.mts +7 -0
  495. package/foundation/discovery/authoring-self-docs.mjs +17 -4
  496. package/foundation/discovery/authoring-self-docs.test.mjs +15 -3
  497. package/foundation/discovery/authoring-surface.d.mts +1 -1
  498. package/foundation/discovery/authoring-surface.mjs +2 -2
  499. package/foundation/discovery/authoring-surface.test.mjs +1 -1
  500. package/foundation/discovery/cli-self-docs.d.mts +2 -1
  501. package/foundation/discovery/cli-self-docs.mjs +22 -4
  502. package/foundation/discovery/cli-self-docs.test.mjs +3 -2
  503. package/foundation/discovery/component-discovery.d.mts +227 -10
  504. package/foundation/discovery/component-discovery.export-names.test.mjs +760 -0
  505. package/foundation/discovery/component-discovery.mjs +940 -57
  506. package/foundation/discovery/component-discovery.test.mjs +96 -0
  507. package/foundation/discovery/component-loader.d.mts +1 -1
  508. package/foundation/discovery/component-replacement.mjs +20 -1
  509. package/foundation/discovery/component-replacement.test.mjs +40 -0
  510. package/foundation/discovery/copied-passages.d.mts +216 -0
  511. package/foundation/discovery/copied-passages.mjs +720 -0
  512. package/foundation/discovery/copied-passages.test.mjs +124 -0
  513. package/foundation/discovery/doc-consistency.d.mts +34 -0
  514. package/foundation/discovery/doc-consistency.mjs +513 -0
  515. package/foundation/discovery/doc-consistency.test.mjs +347 -0
  516. package/foundation/discovery/doc-fluff.d.mts +112 -0
  517. package/foundation/discovery/doc-fluff.mjs +328 -0
  518. package/foundation/discovery/doc-fluff.test.mjs +142 -0
  519. package/foundation/discovery/doc-types.d.mts +157 -0
  520. package/foundation/discovery/doc-types.mjs +1231 -0
  521. package/foundation/discovery/doc-types.test.mjs +744 -0
  522. package/foundation/discovery/docs-discovery.d.mts +88 -0
  523. package/foundation/discovery/docs-discovery.mjs +97 -3
  524. package/foundation/discovery/integration-doc-files.d.mts +22 -0
  525. package/foundation/discovery/integration-doc-files.mjs +231 -0
  526. package/foundation/discovery/integration-doc-files.test.mjs +246 -0
  527. package/foundation/discovery/module-exports.d.mts +68 -0
  528. package/foundation/discovery/module-exports.mjs +609 -31
  529. package/foundation/discovery/module-exports.test.mjs +172 -0
  530. package/foundation/discovery/package-tsconfig.d.mts +14 -0
  531. package/foundation/discovery/package-tsconfig.mjs +228 -0
  532. package/foundation/discovery/package-tsconfig.test.mjs +210 -0
  533. package/foundation/discovery/project-typescript.d.mts +32 -0
  534. package/foundation/discovery/project-typescript.mjs +89 -0
  535. package/foundation/discovery/prop-drift.d.mts +297 -0
  536. package/foundation/discovery/prop-drift.mjs +2428 -0
  537. package/foundation/discovery/prop-drift.test.mjs +2337 -0
  538. package/foundation/discovery/runner-allowlist.d.mts +38 -0
  539. package/foundation/discovery/runner-allowlist.mjs +51 -0
  540. package/foundation/discovery/runner-commands.d.mts +77 -0
  541. package/foundation/discovery/runner-commands.mjs +294 -0
  542. package/foundation/discovery/runner-commands.test.mjs +128 -0
  543. package/foundation/discovery/stray-pointers.d.mts +52 -0
  544. package/foundation/discovery/stray-pointers.mjs +293 -0
  545. package/foundation/discovery/stray-pointers.test.mjs +86 -0
  546. package/foundation/discovery/template-adapter.mjs +92 -6
  547. package/foundation/discovery/template-needs.mjs +6 -46
  548. package/foundation/discovery/theme-discovery.mjs +147 -3
  549. package/foundation/discovery/theme-imports.mjs +8 -4
  550. package/foundation/discovery/theme-imports.test.mjs +1 -1
  551. package/foundation/discovery/type-match.d.mts +53 -0
  552. package/foundation/discovery/type-match.mjs +660 -0
  553. package/foundation/discovery/type-match.test.mjs +169 -0
  554. package/foundation/discovery/type-text.d.mts +68 -0
  555. package/foundation/discovery/type-text.mjs +658 -0
  556. package/foundation/discovery/type-text.test.mjs +196 -0
  557. package/foundation/discovery/unresolved-references.d.mts +62 -0
  558. package/foundation/discovery/unresolved-references.mjs +790 -0
  559. package/foundation/discovery/unresolved-references.test.mjs +567 -0
  560. package/foundation/doc-compiler/doc-loads.test.mjs +84 -10
  561. package/foundation/doc-compiler/inputs.mjs +27 -1
  562. package/foundation/doc-compiler/inputs.test.mjs +0 -1
  563. package/foundation/doc-compiler/links.d.mts +41 -5
  564. package/foundation/doc-compiler/links.mjs +167 -28
  565. package/foundation/doc-compiler/links.test.mjs +97 -4
  566. package/foundation/doc-compiler/read.d.mts +1 -1
  567. package/foundation/doc-compiler/read.mjs +59 -1
  568. package/foundation/doc-compiler/read.test.mjs +11 -2
  569. package/foundation/doc-compiler/split-topic-keywords.test.mjs +3 -2
  570. package/foundation/doc-compiler/tree.d.mts +32 -6
  571. package/foundation/doc-compiler/tree.mjs +107 -44
  572. package/foundation/doc-compiler/tree.test.mjs +14 -7
  573. package/foundation/env/cli-command.d.mts +83 -0
  574. package/foundation/env/cli-command.mjs +152 -0
  575. package/foundation/env/cli-command.test.mjs +129 -0
  576. package/foundation/env/node-version.test.mjs +15 -3
  577. package/foundation/env/package-manager.d.mts +93 -9
  578. package/foundation/env/package-manager.global.test.mjs +66 -0
  579. package/foundation/env/package-manager.mjs +184 -13
  580. package/foundation/env/package-manager.test.mjs +341 -15
  581. package/foundation/env/project-scope.d.mts +9 -0
  582. package/foundation/env/project-scope.mjs +33 -0
  583. package/foundation/env/search-path.d.mts +42 -0
  584. package/foundation/env/search-path.mjs +205 -0
  585. package/foundation/env/search-path.test.mjs +122 -0
  586. package/foundation/env/user-dirs.d.mts +39 -0
  587. package/foundation/env/user-dirs.mjs +93 -0
  588. package/foundation/env/user-dirs.test.mjs +72 -0
  589. package/foundation/env/user-settings.d.mts +46 -0
  590. package/foundation/env/user-settings.mjs +106 -0
  591. package/foundation/env/user-settings.test.mjs +64 -0
  592. package/foundation/fs/file-protection.mjs +15 -1
  593. package/foundation/fs/module-loader.d.mts +2 -1
  594. package/foundation/fs/module-loader.mjs +60 -4
  595. package/foundation/fs/module-loader.stdout.test.mjs +3 -2
  596. package/foundation/fs/module-loader.test.mjs +194 -0
  597. package/foundation/fs/path-compare.d.mts +33 -0
  598. package/foundation/fs/path-compare.mjs +73 -0
  599. package/foundation/fs/paths.d.mts +122 -4
  600. package/foundation/fs/paths.mjs +675 -29
  601. package/foundation/fs/paths.test.mjs +439 -54
  602. package/foundation/fs/read-record.d.mts +18 -0
  603. package/foundation/fs/read-record.mjs +131 -0
  604. package/foundation/fs/read-record.test.mjs +77 -0
  605. package/foundation/integrations/autolink.d.mts +2 -1
  606. package/foundation/integrations/autolink.mjs +4 -13
  607. package/foundation/integrations/cli-peer-version.d.mts +36 -0
  608. package/foundation/integrations/cli-peer-version.mjs +132 -0
  609. package/foundation/integrations/cli-peer-version.test.mjs +354 -0
  610. package/foundation/integrations/computer-integrations.d.mts +81 -0
  611. package/foundation/integrations/computer-integrations.mjs +345 -0
  612. package/foundation/integrations/computer-integrations.test.mjs +292 -0
  613. package/foundation/integrations/contribution-inventory.d.mts +26 -20
  614. package/foundation/integrations/contribution-inventory.mjs +97 -8
  615. package/foundation/integrations/exports-subpaths.d.mts +57 -0
  616. package/foundation/integrations/exports-subpaths.mjs +113 -0
  617. package/foundation/integrations/integration-warnings.mjs +3 -2
  618. package/foundation/integrations/integration-warnings.test.mjs +8 -9
  619. package/foundation/integrations/integrations.d.mts +51 -1
  620. package/foundation/integrations/integrations.mjs +106 -4
  621. package/foundation/integrations/issue.ts +6 -0
  622. package/foundation/integrations/public-imports.d.mts +118 -0
  623. package/foundation/integrations/public-imports.mjs +1769 -0
  624. package/foundation/integrations/public-imports.test.mjs +1793 -0
  625. package/foundation/integrations/validate-contributions.d.mts +117 -0
  626. package/foundation/integrations/validate-contributions.mjs +1209 -14
  627. package/foundation/release/agent-text-worker.d.mts +4 -0
  628. package/foundation/release/agent-text-worker.mjs +52 -0
  629. package/foundation/release/cache.d.mts +310 -0
  630. package/foundation/release/cache.mjs +1216 -0
  631. package/foundation/release/cache.test.mjs +923 -0
  632. package/foundation/release/choose.d.mts +207 -0
  633. package/foundation/release/choose.mjs +677 -0
  634. package/foundation/release/choose.test.mjs +427 -0
  635. package/foundation/release/core-worker.d.mts +4 -0
  636. package/foundation/release/core-worker.mjs +38 -0
  637. package/foundation/release/global-state.d.mts +263 -0
  638. package/foundation/release/global-state.mjs +474 -0
  639. package/foundation/release/global-state.test.mjs +381 -0
  640. package/foundation/release/handoff.d.mts +79 -0
  641. package/foundation/release/handoff.e2e.test.mjs +278 -0
  642. package/foundation/release/handoff.mjs +524 -0
  643. package/foundation/release/lock-lease.d.mts +23 -0
  644. package/foundation/release/lock-lease.mjs +80 -0
  645. package/foundation/release/notices.d.mts +307 -0
  646. package/foundation/release/notices.mjs +707 -0
  647. package/foundation/release/notices.test.mjs +586 -0
  648. package/foundation/release/npm-guard.d.mts +4 -0
  649. package/foundation/release/npm-guard.mjs +126 -0
  650. package/foundation/release/project.d.mts +141 -0
  651. package/foundation/release/project.mjs +466 -0
  652. package/foundation/release/project.test.mjs +288 -0
  653. package/foundation/release/refresh-worker.d.mts +4 -0
  654. package/foundation/release/refresh-worker.mjs +27 -0
  655. package/foundation/release/run-context.d.mts +47 -0
  656. package/foundation/release/run-context.mjs +163 -0
  657. package/foundation/release/update-notice-env.d.mts +28 -0
  658. package/foundation/release/update-notice-env.mjs +39 -0
  659. package/foundation/response/base.d.ts +26 -3
  660. package/foundation/response/error-codes.d.mts +3 -1
  661. package/foundation/response/error-codes.doc.mjs +12 -0
  662. package/foundation/response/error-codes.mjs +17 -0
  663. package/foundation/response/error-codes.test.mjs +2 -0
  664. package/foundation/response/json-contract.test.mjs +7 -2
  665. package/foundation/response/json.mjs +4 -1
  666. package/foundation/response/response-types.doc.mjs +22 -11
  667. package/foundation/response/response-types.doc.test.mjs +46 -0
  668. package/foundation/response/response.doc.mjs +3 -3
  669. package/foundation/route/route.d.mts +285 -0
  670. package/foundation/route/route.mjs +324 -0
  671. package/foundation/route/route.test.mjs +153 -0
  672. package/foundation/runtime/hosted-runtime.test.mjs +403 -0
  673. package/foundation/runtime/locked-versions.d.mts +32 -0
  674. package/foundation/runtime/locked-versions.mjs +65 -0
  675. package/foundation/runtime/package-root.d.mts +91 -0
  676. package/foundation/runtime/package-root.mjs +174 -0
  677. package/foundation/runtime/package-set.d.mts +62 -0
  678. package/foundation/runtime/package-set.mjs +130 -0
  679. package/foundation/runtime/package-set.test.mjs +432 -0
  680. package/foundation/text/string-utils.d.mts +2 -1
  681. package/foundation/text/string-utils.mjs +16 -5
  682. package/foundation/text/suggest-order.d.mts +72 -0
  683. package/foundation/text/suggest-order.mjs +363 -0
  684. package/foundation/text/suggest-order.test.mjs +259 -0
  685. package/foundation/xle/browser-imports.test.mjs +74 -0
  686. package/foundation/xle/registry.mjs +4 -0
  687. package/foundation/xle/registry.test.mjs +28 -0
  688. package/host/door-conformance.test.mjs +274 -0
  689. package/host/index.d.ts +116 -0
  690. package/host/index.mjs +295 -0
  691. package/host/index.test.mjs +302 -0
  692. package/package.json +16 -11
  693. package/scripts/postinstall.mjs +24 -5
  694. package/assets/docs/tree/integrations.doc.mjs +0 -40
@@ -8,6 +8,7 @@
8
8
  * none of them touch the integration system, the filesystem, or a source. This
9
9
  * adapter does: it resolves the project's installed integrations and what each
10
10
  * one adds, calls every discover source and keeps a saved copy of each answer,
11
+ * reads the official list the CLI carries after them,
11
12
  * locates and loads a component's doc, and names the package manager's add
12
13
  * command. Keeping that I/O here (INV21) is what lets `list`, `detail`,
13
14
  * `detail/doc`, `detail/item`, and `search` stay pure projections.
@@ -18,9 +19,14 @@
18
19
 
19
20
  import {createHash} from 'node:crypto';
20
21
  import * as fs from 'node:fs';
21
- import * as os from 'node:os';
22
22
  import * as path from 'node:path';
23
- import {Project} from '../../foundation/config/project.mjs';
23
+ import {
24
+ Project,
25
+ availableComputerIntegrations,
26
+ } from '../../foundation/config/project.mjs';
27
+ import {isOutsideProject} from '../../foundation/env/project-scope.mjs';
28
+ import {projectAddCommand} from '../../foundation/release/notices.mjs';
29
+ import {hostedRun} from '../../foundation/runtime/package-root.mjs';
24
30
  import {
25
31
  scanAllPackages,
26
32
  findComponentInPackages,
@@ -28,13 +34,30 @@ import {
28
34
  import {loadDocs} from '../../foundation/discovery/component-loader.mjs';
29
35
  import {collectIdentities} from '../../foundation/integrations/contribution-inventory.mjs';
30
36
  import {detectPackageManager} from '../../foundation/env/package-manager.mjs';
37
+ import {isValidSemver, semverCompare} from '../../foundation/env/semver.mjs';
31
38
  import {assertWithin} from '../../foundation/fs/path-safety.mjs';
39
+ import {userCacheDir} from '../../foundation/env/user-dirs.mjs';
40
+ import {CLI_ROOT, findInstalledPackage} from '../../foundation/fs/paths.mjs';
32
41
  import {parseDiscoverCatalog} from '../../authoring/discover/parse.mjs';
33
42
  import {AstryxError} from '../error.mjs';
34
43
  import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
35
44
 
36
45
  const SOURCE_TIMEOUT_MS = 30_000;
37
46
 
47
+ /** The name the official list goes by, as a source and on each of its entries. */
48
+ export const OFFICIAL_SOURCE_NAME = 'Astryx';
49
+
50
+ /** Where the official list comes from: the CLI package that carries it. */
51
+ const OFFICIAL_SOURCE_FROM = '@astryxdesign/cli';
52
+
53
+ /** The official list, generated from the repository when the CLI is built. */
54
+ export const OFFICIAL_LIST_FILE = path.join(
55
+ CLI_ROOT,
56
+ 'assets',
57
+ 'discover',
58
+ 'official-packages.json',
59
+ );
60
+
38
61
  const DEPENDENCY_FIELDS = [
39
62
  'dependencies',
40
63
  'devDependencies',
@@ -48,6 +71,29 @@ const DEPENDENCY_FIELDS = [
48
71
  * @typedef {import('../../authoring/discover/type').DiscoverSource} DiscoverSource
49
72
  */
50
73
 
74
+ /**
75
+ * An official package as this CLI lists it (spec:AST-051 FR11), with what its
76
+ * add command pins (FR2): the project's Core version, the Core range the
77
+ * project declares, or the latest release; with none, it pins nothing.
78
+ * @typedef {DiscoverPackage & {pin?: string}} OfficialPackage
79
+ */
80
+
81
+ /**
82
+ * The official packages the project's package.json declares: the real package
83
+ * name of each, mapped to the name it is installed under (an npm alias such as
84
+ * `"my-theme": "npm:@astryxdesign/theme-gothic@0.7.0"` installs under
85
+ * `my-theme`). `dependency` holds those declared in dependencies,
86
+ * devDependencies or optionalDependencies, which make a package the project's
87
+ * own; `any` adds peerDependencies, which only keep it from being offered.
88
+ * @typedef {{dependency: Map<string, string>, any: Set<string>}} OfficialDeclarations
89
+ */
90
+
91
+ /**
92
+ * The official list as this CLI reads it. `error` says why the file could not
93
+ * be read; the list is then empty and discover reports it like a failed source.
94
+ * @typedef {{packages: OfficialPackage[], error?: string}} OfficialList
95
+ */
96
+
51
97
  /**
52
98
  * An installed integration with what it adds, per kind. `components` is the
53
99
  * scanned component list the discover leaves have always used.
@@ -64,7 +110,8 @@ const DEPENDENCY_FIELDS = [
64
110
  * @typedef {object} SourceState
65
111
  * @property {string} name the source's own name, or where it came from when it
66
112
  * gave none
67
- * @property {string} from `astryx.config`, or the integration that exports it
113
+ * @property {string} from `astryx.config`, the integration that exports it, or
114
+ * `@astryxdesign/cli` for the official list
68
115
  * @property {'fresh' | 'saved' | 'failed'} status
69
116
  * @property {string} [generatedAt]
70
117
  * @property {boolean} [complete]
@@ -73,9 +120,10 @@ const DEPENDENCY_FIELDS = [
73
120
  */
74
121
 
75
122
  /**
76
- * Everything every source returned, merged. When two sources list the same
77
- * package, the earlier source's entry is kept.
78
- * @typedef {{sources: SourceState[], packages: Array<DiscoverPackage & {source: string}>}} CatalogResult
123
+ * Everything every source returned, merged, the official list last. When two
124
+ * sources list the same package, the earlier source's entry is kept. `official`
125
+ * marks an entry the official list supplied.
126
+ * @typedef {{sources: SourceState[], packages: Array<DiscoverPackage & {source: string, official?: true}>}} CatalogResult
79
127
  */
80
128
 
81
129
  /**
@@ -196,6 +244,7 @@ export async function describeInstalled(project, scanned) {
196
244
  * @returns {boolean}
197
245
  */
198
246
  export function hasSources(project) {
247
+ if (doorSources().length > 0) return true;
199
248
  if (project == null) return false;
200
249
  if (typeof project.config?.discover === 'function') return true;
201
250
  return project.loadedIntegrations.some(
@@ -203,6 +252,48 @@ export function hasSources(project) {
203
252
  );
204
253
  }
205
254
 
255
+ /** Where a discover source a host passed comes from (spec AST-081 FR1). */
256
+ const DOOR_SOURCE = 'the host';
257
+
258
+ /**
259
+ * The discover sources the host that started this run passed, if any.
260
+ * @returns {readonly DiscoverSource[]}
261
+ */
262
+ function doorSources() {
263
+ return /** @type {readonly DiscoverSource[]} */ (
264
+ hostedRun()?.discoverSources ?? []
265
+ );
266
+ }
267
+
268
+ /** The source name of a package installed for the computer. */
269
+ const COMPUTER_SOURCE = 'installed for this computer';
270
+
271
+ /**
272
+ * The integrations installed for the computer that a project could add, as
273
+ * available entries with the project's install command (spec AST-081 FR12).
274
+ * Empty outside a project, where they load instead.
275
+ * @param {Project | undefined} project
276
+ * @param {Array<{name: string}>} installed
277
+ * @param {Set<string>} declared
278
+ * @returns {Promise<import('./discover.type.mjs').DiscoverAvailableEntry[]>}
279
+ */
280
+ export async function computerAvailableEntries(project, installed, declared) {
281
+ const cwd = project?.cwd ?? process.cwd();
282
+ if (isOutsideProject(cwd)) return [];
283
+ // The same command doctor names: in the project spec:AST-040 FR9 defines,
284
+ // and none where FR9 finds no project.
285
+ const add = projectAddCommand(cwd);
286
+ const have = new Set([...installed.map(pkg => pkg.name), ...declared]);
287
+ return (await availableComputerIntegrations(cwd, have)).map(c => ({
288
+ name: c.name,
289
+ components: [],
290
+ ...(c.version ? {version: c.version} : {}),
291
+ ...(c.description ? {description: c.description} : {}),
292
+ source: COMPUTER_SOURCE,
293
+ ...(add ? {install: add(c.name)} : {}),
294
+ }));
295
+ }
296
+
206
297
  /**
207
298
  * Package names the project's package.json declares in any dependency field.
208
299
  * @param {Project | undefined} project
@@ -225,13 +316,151 @@ export function declaredDependencies(project) {
225
316
  return names;
226
317
  }
227
318
 
319
+ /**
320
+ * The nearest package.json at or above the project's folder, read. Discover
321
+ * runs from any folder of a project; this is the project's own manifest.
322
+ * @param {Project | undefined} project
323
+ * @returns {{dir: string, pkg: Record<string, any>} | null}
324
+ */
325
+ function nearestManifest(project) {
326
+ let dir = project?.cwd ?? process.cwd();
327
+ for (;;) {
328
+ const file = path.join(dir, 'package.json');
329
+ if (fs.existsSync(file)) {
330
+ try {
331
+ return {dir, pkg: JSON.parse(fs.readFileSync(file, 'utf8'))};
332
+ } catch {
333
+ return null;
334
+ }
335
+ }
336
+ const parent = path.dirname(dir);
337
+ if (parent === dir) return null;
338
+ dir = parent;
339
+ }
340
+ }
341
+
342
+ /** The fields that make a declared package the project's own. */
343
+ const OWN_DEPENDENCY_FIELDS = [
344
+ 'dependencies',
345
+ 'devDependencies',
346
+ 'optionalDependencies',
347
+ ];
348
+
349
+ /**
350
+ * The package a dependency entry installs: its own name, or the target of an
351
+ * npm alias (`npm:<name>@<range>`).
352
+ * @param {string} name
353
+ * @param {unknown} spec
354
+ * @returns {string}
355
+ */
356
+ function declaredPackage(name, spec) {
357
+ if (typeof spec !== 'string' || !spec.startsWith('npm:')) return name;
358
+ const target = spec.slice('npm:'.length);
359
+ const at = target.indexOf('@', 1);
360
+ return at > 0 ? target.slice(0, at) : target;
361
+ }
362
+
363
+ /**
364
+ * What the project's own package.json, the nearest one above the folder
365
+ * discover runs in, declares among the official packages.
366
+ * @param {Project | undefined} project
367
+ * @param {OfficialPackage[]} official
368
+ * @returns {OfficialDeclarations}
369
+ */
370
+ export function officialDeclarations(project, official) {
371
+ const names = new Set(official.map(pkg => pkg.package));
372
+ /** @type {OfficialDeclarations} */
373
+ const declared = {dependency: new Map(), any: new Set()};
374
+ const manifest = nearestManifest(project);
375
+ if (manifest == null) return declared;
376
+ for (const field of DEPENDENCY_FIELDS) {
377
+ for (const [local, spec] of Object.entries(manifest.pkg?.[field] ?? {})) {
378
+ const real = declaredPackage(local, spec);
379
+ if (!names.has(real)) continue;
380
+ declared.any.add(real);
381
+ if (
382
+ OWN_DEPENDENCY_FIELDS.includes(field) &&
383
+ !declared.dependency.has(real)
384
+ )
385
+ declared.dependency.set(real, local);
386
+ }
387
+ }
388
+ return declared;
389
+ }
390
+
391
+ /**
392
+ * One part of a semver range: an optional comparator and a version that may
393
+ * use `x` or `*` wildcards.
394
+ */
395
+ const RANGE_PART =
396
+ /^(?:[<>]=?|=|\^|~)?v?(?:\d+|[xX*])(?:\.(?:\d+|[xX*])){0,2}(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/u;
397
+
398
+ /**
399
+ * Whether a dependency spec is a semver range every supported package manager
400
+ * resolves: comparators, wildcards, `||` and hyphen ranges. A dist-tag, path,
401
+ * URL, alias or workspace protocol is not.
402
+ * @param {string} spec
403
+ * @returns {boolean}
404
+ */
405
+ function isSemverRange(spec) {
406
+ const parts = spec
407
+ .trim()
408
+ .split(/\s*\|\|\s*|\s+/u)
409
+ .filter(part => part !== '-');
410
+ return parts.length > 0 && parts.every(part => RANGE_PART.test(part));
411
+ }
412
+
413
+ /**
414
+ * The project's Core: the installed copy's version, else what its own
415
+ * package.json declares (a fresh clone before install): an exact `version`, or
416
+ * a semver `range`. Neither, for a declaration no package manager can pin
417
+ * against, such as a path or a dist-tag. Null when the project has no Core.
418
+ * @param {Project | undefined} project
419
+ * @returns {{version?: string, range?: string} | null}
420
+ */
421
+ function projectCore(project) {
422
+ const installed = installedVersion(project, '@astryxdesign/core');
423
+ if (installed) return {version: installed};
424
+ const manifest = nearestManifest(project);
425
+ for (const field of OWN_DEPENDENCY_FIELDS) {
426
+ const spec = manifest?.pkg?.[field]?.['@astryxdesign/core'];
427
+ if (typeof spec !== 'string') continue;
428
+ // A space after an operator (`~ 0.6.8`, `>= 0.6.8 < 0.7.0`) is allowed by
429
+ // node-semver; join each operator to its version before reading the spec.
430
+ const range = spec.trim().replace(/([<>]=?|=|\^|~)\s+/gu, '$1');
431
+ const exact = range.replace(/^=/u, '');
432
+ if (isValidSemver(exact)) return {version: exact};
433
+ return isSemverRange(range) ? {range} : {};
434
+ }
435
+ return null;
436
+ }
437
+
438
+ /**
439
+ * Newest first: by release number, then a release before its prereleases.
440
+ * @param {string} a
441
+ * @param {string} b
442
+ * @returns {number}
443
+ */
444
+ function newerFirst(a, b) {
445
+ const byNumber = semverCompare(b, a);
446
+ if (byNumber !== 0) return byNumber;
447
+ const aRelease = !a.includes('-');
448
+ if (aRelease !== !b.includes('-')) return aRelease ? -1 : 1;
449
+ return b.localeCompare(a, 'en', {numeric: true});
450
+ }
451
+
228
452
  /**
229
453
  * The command that adds a package with the project's package manager. Discover
230
- * only prints it; it never runs it.
454
+ * only prints it; it never runs it. Asked for one version, it adds that
455
+ * version. Given the official list, it otherwise pins an official package to
456
+ * what its entry names (spec:AST-051 FR2): the project's Core version or
457
+ * declared Core range, else the latest release. A range is quoted, because
458
+ * `^`, `<`, `>`, `|` and spaces mean something to a shell.
231
459
  * @param {Project | undefined} project
460
+ * @param {{official?: OfficialPackage[]}} [options]
232
461
  * @returns {(name: string, version?: string) => string}
233
462
  */
234
- export function addCommand(project) {
463
+ export function addCommand(project, {official = []} = {}) {
235
464
  const pm = detectPackageManager(project?.cwd ?? process.cwd());
236
465
  const verb =
237
466
  pm === 'pnpm'
@@ -241,7 +470,15 @@ export function addCommand(project) {
241
470
  : pm === 'bun'
242
471
  ? 'bun add'
243
472
  : 'npm install';
244
- return (name, version) => `${verb} ${version ? `${name}@${version}` : name}`;
473
+ const byName = new Map(official.map(pkg => [pkg.package, pkg]));
474
+ return (name, version) => {
475
+ if (version) return `${verb} ${name}@${version}`;
476
+ const pin = byName.get(name)?.pin;
477
+ if (!pin) return `${verb} ${name}`;
478
+ return isValidSemver(pin)
479
+ ? `${verb} ${name}@${pin}`
480
+ : `${verb} "${name}@${pin}"`;
481
+ };
245
482
  }
246
483
 
247
484
  /**
@@ -250,26 +487,13 @@ export function addCommand(project) {
250
487
  * @returns {string}
251
488
  */
252
489
  export function defaultCacheDir() {
253
- const home = os.homedir();
254
- if (process.platform === 'win32') {
255
- return path.join(
256
- process.env.LOCALAPPDATA || path.join(home, 'AppData', 'Local'),
257
- 'astryx',
258
- 'Cache',
259
- );
260
- }
261
- if (process.platform === 'darwin') {
262
- return path.join(home, 'Library', 'Caches', 'astryx');
263
- }
264
- return path.join(
265
- process.env.XDG_CACHE_HOME || path.join(home, '.cache'),
266
- 'astryx',
267
- );
490
+ return userCacheDir();
268
491
  }
269
492
 
270
493
  /**
271
494
  * @param {string} cacheDir
272
- * @param {string} from
495
+ * @param {string} from the source's key: its `from` label, with the host for
496
+ * a host's source
273
497
  * @param {{package?: string, version?: string}} request
274
498
  */
275
499
  function savedCopyPath(cacheDir, from, request) {
@@ -347,8 +571,9 @@ async function callSource(source, request, label, timeoutMs) {
347
571
  }
348
572
 
349
573
  /**
350
- * Call every discover source — the project's `discover` first, then each
351
- * integration's in load order — once per distinct function. A source that
574
+ * Call the discover sources — the project's `discover` first, then each
575
+ * integration's in load order, then each a host passed, named as the host's
576
+ * (spec AST-081 FR1, AST-051 FR6) — once per distinct function. A source that
352
577
  * throws, times out, or returns an invalid catalog falls back to its saved copy;
353
578
  * with none, it is reported and adds nothing. The others always count.
354
579
  *
@@ -358,24 +583,34 @@ async function callSource(source, request, label, timeoutMs) {
358
583
  * @param {{cacheDir?: string, timeoutMs?: number}} [options]
359
584
  * @returns {Promise<CatalogResult>}
360
585
  */
361
- export async function callSources(project, request = {}, options = {}) {
586
+ async function callOwnSources(project, request = {}, options = {}) {
362
587
  const {cacheDir = defaultCacheDir(), timeoutMs = SOURCE_TIMEOUT_MS} = options;
363
588
  /** @type {CatalogResult} */
364
589
  const result = {sources: [], packages: []};
365
- if (project == null) return result;
590
+ const fromDoor = doorSources();
591
+ if (project == null && fromDoor.length === 0) return result;
366
592
 
367
- /** @type {Array<{from: string, source?: DiscoverSource, error?: string}>} */
593
+ /** @type {Array<{from: string, key?: string, source?: DiscoverSource, error?: string}>} */
368
594
  const origins = [];
369
- if (typeof project.config?.discover === 'function') {
595
+ if (typeof project?.config?.discover === 'function') {
370
596
  origins.push({from: 'astryx.config', source: project.config.discover});
371
597
  }
372
- for (const integration of project.loadedIntegrations) {
598
+ for (const integration of project?.loadedIntegrations ?? []) {
373
599
  if (integration.__discoverError) {
374
600
  origins.push({from: integration.name, error: integration.__discoverError});
375
601
  } else if (integration.__discover) {
376
602
  origins.push({from: integration.name, source: integration.__discover});
377
603
  }
378
604
  }
605
+ // Every tool that carries the CLI reports its sources as the host's, so
606
+ // their saved copies are kept per host, by the root that holds its CLI
607
+ // (spec:AST-051 FR8).
608
+ const host = hostedRun()?.startingRoot ?? '';
609
+ fromDoor.forEach((source, index) => {
610
+ const from =
611
+ fromDoor.length === 1 ? DOOR_SOURCE : `${DOOR_SOURCE} (${index + 1})`;
612
+ origins.push({from, key: `${from}\n${host}`, source});
613
+ });
379
614
 
380
615
  /** @type {Set<unknown>} */
381
616
  const called = new Set();
@@ -384,7 +619,7 @@ export async function callSources(project, request = {}, options = {}) {
384
619
  const ask = request.package
385
620
  ? {package: request.package, ...(request.version ? {version: request.version} : {})}
386
621
  : {};
387
- for (const {from, source, error} of origins) {
622
+ for (const {from, key = from, source, error} of origins) {
388
623
  if (source == null) {
389
624
  result.sources.push({name: from, from, status: 'failed', error});
390
625
  continue;
@@ -393,7 +628,7 @@ export async function callSources(project, request = {}, options = {}) {
393
628
  called.add(source);
394
629
 
395
630
  const label = `the discover source from ${from}`;
396
- const file = savedCopyPath(cacheDir, from, ask);
631
+ const file = savedCopyPath(cacheDir, key, ask);
397
632
  /** @type {import('../../authoring/discover/type').DiscoverCatalog} */
398
633
  let catalog;
399
634
  try {
@@ -433,6 +668,257 @@ export async function callSources(project, request = {}, options = {}) {
433
668
  return result;
434
669
  }
435
670
 
671
+ /**
672
+ * Call every discover source (see {@link callOwnSources}), then read the
673
+ * official list (spec:AST-051 FR11). The list comes last, so a source keeps
674
+ * its entry for an official package, or for any package of the same
675
+ * integration (FR7); the list adds the official packages no source covers.
676
+ * The result stays in source order; discover puts official packages first
677
+ * only where it shows them ({@link officialFirst}).
678
+ *
679
+ * @param {Project | undefined} project
680
+ * @param {{package?: string, version?: string}} [request]
681
+ * @param {{cacheDir?: string, timeoutMs?: number, official?: OfficialList}} [options]
682
+ * `official`: the list {@link officialList} read; read here when absent
683
+ * @returns {Promise<CatalogResult>}
684
+ */
685
+ export async function callSources(project, request = {}, options = {}) {
686
+ const {official = officialList({project}), ...rest} = options;
687
+ const own = await callOwnSources(project, request, rest);
688
+ // A source's entry wins for its package and for the integration it
689
+ // publishes under any name (FR7), so a fork or mirror keeps its place.
690
+ const seen = new Set(
691
+ own.packages.flatMap(pkg => [pkg.package, pkg.integration, ...pkg.aliases]),
692
+ );
693
+ /** @type {CatalogResult['packages']} */
694
+ const added = [];
695
+ for (const {pin: _pin, ...pkg} of official.packages) {
696
+ if (seen.has(pkg.package)) continue;
697
+ if (request.package && pkg.package !== request.package) continue;
698
+ added.push({...pkg, source: OFFICIAL_SOURCE_NAME, official: true});
699
+ }
700
+ return {
701
+ sources: [
702
+ ...own.sources,
703
+ official.error
704
+ ? {
705
+ name: OFFICIAL_SOURCE_NAME,
706
+ from: OFFICIAL_SOURCE_FROM,
707
+ status: 'failed',
708
+ error: official.error,
709
+ }
710
+ : {
711
+ name: OFFICIAL_SOURCE_NAME,
712
+ from: OFFICIAL_SOURCE_FROM,
713
+ status: 'fresh',
714
+ complete: true,
715
+ },
716
+ ],
717
+ // Source order: the first entry per integration is the one discover
718
+ // keeps. Official packages are put first only where discover shows them.
719
+ packages: [...own.packages, ...added],
720
+ };
721
+ }
722
+
723
+ /**
724
+ * Official packages first, in the official list's order; the rest keep theirs.
725
+ * @template T
726
+ * @param {T[]} items
727
+ * @param {OfficialPackage[]} official
728
+ * @param {(item: T) => string} nameOf
729
+ * @returns {T[]}
730
+ */
731
+ export function officialFirst(items, official, nameOf) {
732
+ const order = new Map(official.map((pkg, index) => [pkg.package, index]));
733
+ const rank = (/** @type {T} */ item) => order.get(nameOf(item)) ?? order.size;
734
+ return [...items].sort((a, b) => rank(a) - rank(b));
735
+ }
736
+
737
+ /**
738
+ * The official list this CLI carries (spec:AST-051 FR11). The file holds no
739
+ * versions; each entry takes them from this CLI and the project:
740
+ *
741
+ * - Its latest release is the newest release this CLI knows: its own version
742
+ * on a release CLI, or the project's Core version when that is a newer
743
+ * release.
744
+ * - A package released with Core lists a release CLI's own version and the
745
+ * project's Core version (installed, else declared exactly), so each,
746
+ * the latest release included, can be looked up. Its add command pins the project's Core version, else the Core range
747
+ * the project declares, else the latest release; nothing on a canary CLI in
748
+ * a project with no Core, which may have been published without it.
749
+ * - A canary-only package is listed only by a canary CLI, as a prerelease at
750
+ * the project's Core version when that is a prerelease, else at the CLI's
751
+ * own version when the project has no Core. It is not listed beside a
752
+ * released or declared Core, which it cannot be installed with.
753
+ *
754
+ * @param {{file?: string, version?: string, project?: Project}} [options] the
755
+ * list file and the CLI version to read it for, both defaulting to this
756
+ * CLI's own, and the project whose Core decides the versions
757
+ * @returns {OfficialList}
758
+ */
759
+ export function officialList({
760
+ file = OFFICIAL_LIST_FILE,
761
+ version,
762
+ project,
763
+ } = {}) {
764
+ try {
765
+ const cli = version ?? packageVersion(CLI_ROOT);
766
+ if (cli == null) throw new Error('the CLI package names no version');
767
+ const core = project == null ? null : projectCore(project);
768
+ const list = JSON.parse(fs.readFileSync(file, 'utf8'));
769
+ const canaryCli = /-canary\./u.test(cli);
770
+ /** @type {(v: string | undefined) => v is string} */
771
+ const isRelease = v => v != null && !v.includes('-');
772
+ const latest =
773
+ [cli, core?.version].filter(isRelease).sort(newerFirst)[0] ?? null;
774
+ /** @type {OfficialPackage[]} */
775
+ const packages = [];
776
+ for (const pkg of list.packages) {
777
+ /** @type {string[]} */
778
+ let listed = [];
779
+ /** @type {string | null} */
780
+ let entryLatest = null;
781
+ /** @type {string | undefined} */
782
+ let pin;
783
+ if (pkg.canaryOnly === true) {
784
+ if (!canaryCli) continue;
785
+ if (core == null) pin = cli;
786
+ else if (core.version && !isRelease(core.version)) pin = core.version;
787
+ else continue;
788
+ listed = [pin];
789
+ } else if (pkg.releasedWithCore === true) {
790
+ entryLatest = latest;
791
+ listed = [
792
+ ...new Set(
793
+ [isRelease(cli) ? cli : undefined, core?.version].filter(
794
+ /** @returns {v is string} */ v => v != null,
795
+ ),
796
+ ),
797
+ ].sort(newerFirst);
798
+ // The project's Core version, else the plain range it declares, else
799
+ // the latest release (spec:AST-051 FR11): a Core declared as
800
+ // `workspace:*`, a `file:` path or a dist-tag, and not installed,
801
+ // still gets a pin.
802
+ pin =
803
+ core == null
804
+ ? canaryCli
805
+ ? undefined
806
+ : cli
807
+ : (core.version ?? core.range ?? entryLatest ?? undefined);
808
+ }
809
+ packages.push({
810
+ package: pkg.package,
811
+ integration: pkg.package,
812
+ aliases: [],
813
+ ...(pkg.description ? {description: pkg.description} : {}),
814
+ latest: entryLatest,
815
+ versions: listed.map(v => ({
816
+ version: v,
817
+ publishedAt: null,
818
+ prerelease: v.includes('-'),
819
+ status: 'ok',
820
+ })),
821
+ contributions: pkg.contributions,
822
+ ...(pin ? {pin} : {}),
823
+ });
824
+ }
825
+ return {packages};
826
+ } catch (err) {
827
+ return {
828
+ packages: [],
829
+ error: `the official list could not be read (${err instanceof Error ? err.message : String(err)})`,
830
+ };
831
+ }
832
+ }
833
+
834
+ /**
835
+ * What the project has: its installed integrations plus each official package
836
+ * its own package.json declares as a dependency whose entry the official list
837
+ * supplied, official packages first. A declared official package that a source
838
+ * lists stays as that source shows it (FR7). One that failed to load as an
839
+ * integration stays out. A declared one takes what it adds from the list and
840
+ * its version from the copy the project installed, under an npm alias too.
841
+ *
842
+ * @param {Project | undefined} project
843
+ * @param {InstalledPackage[]} installed from {@link describeInstalled}
844
+ * @param {CatalogResult} catalog
845
+ * @param {OfficialDeclarations} declared from {@link officialDeclarations}
846
+ * @param {OfficialPackage[]} official the official list, for the order
847
+ * @returns {Array<InstalledPackage & {declaredOfficial?: true}>}
848
+ */
849
+ export function withDeclaredOfficial(
850
+ project,
851
+ installed,
852
+ catalog,
853
+ declared,
854
+ official,
855
+ ) {
856
+ const loaded = new Set(project?.loadedIntegrations.map(i => i.name) ?? []);
857
+ /** @type {Array<InstalledPackage & {declaredOfficial?: true}>} */
858
+ const added = [];
859
+ for (const pkg of catalog.packages) {
860
+ const local = declared.dependency.get(pkg.package);
861
+ if (!pkg.official || local == null || loaded.has(pkg.package)) continue;
862
+ const version = installedVersion(project, local);
863
+ added.push(
864
+ /** @type {InstalledPackage & {declaredOfficial: true}} */ (
865
+ /** @type {unknown} */ ({
866
+ name: pkg.package,
867
+ category: pkg.package,
868
+ ...(version ? {version} : {}),
869
+ ...(pkg.description ? {description: pkg.description} : {}),
870
+ ...itemLists(pkg.contributions),
871
+ declaredOfficial: true,
872
+ })
873
+ ),
874
+ );
875
+ }
876
+ return officialFirst([...installed, ...added], official, pkg => pkg.name);
877
+ }
878
+
879
+ /**
880
+ * Group contributions into the entry fields, one list per kind that has any.
881
+ * `components` is always present, like on a scanned package.
882
+ * @param {DiscoverPackage['contributions']} contributions
883
+ * @returns {Record<string, string[]>}
884
+ */
885
+ function itemLists(contributions) {
886
+ /** @type {Record<string, string[]>} */
887
+ const lists = {components: []};
888
+ for (const [kind, field] of KIND_FIELDS) {
889
+ const names = contributions.filter(c => c.kind === kind).map(c => c.name);
890
+ if (names.length > 0) lists[field] = names;
891
+ }
892
+ return lists;
893
+ }
894
+
895
+ /**
896
+ * The version in a package directory's package.json, if it names one.
897
+ * @param {string} dir
898
+ * @returns {string | undefined}
899
+ */
900
+ function packageVersion(dir) {
901
+ try {
902
+ const {version} = JSON.parse(
903
+ fs.readFileSync(path.join(dir, 'package.json'), 'utf8'),
904
+ );
905
+ return typeof version === 'string' && version ? version : undefined;
906
+ } catch {
907
+ return undefined;
908
+ }
909
+ }
910
+
911
+ /**
912
+ * The version of `name` the project installed, if it installed it.
913
+ * @param {Project | undefined} project
914
+ * @param {string} name
915
+ * @returns {string | undefined}
916
+ */
917
+ function installedVersion(project, name) {
918
+ const dir = findInstalledPackage(project?.cwd ?? process.cwd(), name);
919
+ return dir == null ? undefined : packageVersion(dir);
920
+ }
921
+
436
922
  /** The list and detail entry fields for each item kind, in display order. */
437
923
  export const KIND_FIELDS = /** @type {const} */ ([
438
924
  ['component', 'components'],