@astryxdesign/cli 0.6.3 → 0.6.4-canary.10dd683

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 (643) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/README.md +117 -78
  3. package/api/blog/blog.doc.mjs +1 -0
  4. package/api/build/_adapter.d.mts +50 -0
  5. package/api/build/_adapter.mjs +60 -0
  6. package/api/build/build.doc.mjs +16 -9
  7. package/api/build/build.test.mjs +197 -8
  8. package/api/build/build.type.d.mts +91 -2
  9. package/api/build/build.type.mjs +52 -8
  10. package/api/build/help/help.d.mts +12 -5
  11. package/api/build/help/help.mjs +69 -6
  12. package/api/build/kit/kit.d.mts +4 -1
  13. package/api/build/kit/kit.mjs +165 -49
  14. package/api/build/kit/rank.d.mts +44 -0
  15. package/api/build/kit/rank.mjs +432 -0
  16. package/api/build/kit/rank.test.mjs +196 -0
  17. package/api/component/_adapter.d.mts +6 -12
  18. package/api/component/_adapter.mjs +20 -10
  19. package/api/component/component.doc.mjs +13 -3
  20. package/api/component/component.mjs +91 -14
  21. package/api/component/component.test.mjs +38 -0
  22. package/api/component/component.type.d.mts +22 -11
  23. package/api/component/component.type.mjs +32 -24
  24. package/api/component/detail/blocks/blocks.d.mts +2 -1
  25. package/api/component/detail/blocks/blocks.mjs +4 -3
  26. package/api/component/list/list.d.mts +0 -5
  27. package/api/component/list/list.mjs +40 -11
  28. package/api/discover/_adapter.d.mts +114 -6
  29. package/api/discover/_adapter.mjs +372 -17
  30. package/api/discover/_adapter.test.mjs +215 -0
  31. package/api/discover/_catalog-view.d.mts +115 -0
  32. package/api/discover/_catalog-view.mjs +203 -0
  33. package/api/discover/_catalog-view.test.mjs +128 -0
  34. package/api/discover/detail/detail.d.mts +18 -6
  35. package/api/discover/detail/detail.mjs +67 -13
  36. package/api/discover/detail/detail.test.mjs +85 -0
  37. package/api/discover/detail/item/item.d.mts +26 -0
  38. package/api/discover/detail/item/item.mjs +78 -0
  39. package/api/discover/detail/item/item.test.mjs +73 -0
  40. package/api/discover/discover.d.mts +3 -9
  41. package/api/discover/discover.doc.mjs +62 -18
  42. package/api/discover/discover.mjs +220 -36
  43. package/api/discover/discover.test.mjs +11 -2
  44. package/api/discover/discover.type.d.mts +150 -11
  45. package/api/discover/discover.type.mjs +107 -17
  46. package/api/discover/list/list.d.mts +20 -6
  47. package/api/discover/list/list.mjs +45 -12
  48. package/api/discover/list/list.test.mjs +46 -0
  49. package/api/discover/search/search.d.mts +18 -16
  50. package/api/discover/search/search.mjs +102 -56
  51. package/api/discover/search/search.test.mjs +144 -10
  52. package/api/docs/_adapter.d.mts +272 -41
  53. package/api/docs/_adapter.mjs +985 -108
  54. package/api/docs/compiled-topics.test.mjs +78 -0
  55. package/api/docs/detail/detail.mjs +22 -63
  56. package/api/docs/detail/section/section.d.mts +1 -1
  57. package/api/docs/detail/section/section.mjs +54 -19
  58. package/api/docs/detail/section/section.test.mjs +50 -0
  59. package/api/docs/docs.d.mts +10 -3
  60. package/api/docs/docs.doc.mjs +55 -16
  61. package/api/docs/docs.mjs +53 -10
  62. package/api/docs/docs.test.mjs +164 -4
  63. package/api/docs/docs.type.d.mts +221 -5
  64. package/api/docs/docs.type.mjs +153 -11
  65. package/api/docs/index/index.d.mts +18 -0
  66. package/api/docs/index/index.mjs +40 -0
  67. package/api/docs/index/index.test.mjs +62 -0
  68. package/api/docs/integration-tree.test.mjs +555 -0
  69. package/api/docs/integrationDocs.test.mjs +114 -8
  70. package/api/docs/list/list.mjs +28 -12
  71. package/api/docs/node/node.d.mts +43 -0
  72. package/api/docs/node/node.mjs +192 -0
  73. package/api/docs/reference-blocks.test.mjs +406 -0
  74. package/api/doctor/doctor.d.mts +99 -1
  75. package/api/doctor/doctor.doc.mjs +1 -0
  76. package/api/doctor/doctor.mjs +548 -1
  77. package/api/doctor/doctor.test.mjs +610 -1
  78. package/api/gap-report/gap-report.doc.mjs +8 -4
  79. package/api/hook/_adapter.mjs +19 -5
  80. package/api/hook/hook.doc.mjs +1 -0
  81. package/api/hook/hook.type.d.mts +3 -3
  82. package/api/hook/hook.type.mjs +11 -11
  83. package/api/hook/list/list.d.mts +2 -2
  84. package/api/hook/list/list.mjs +69 -17
  85. package/api/index.d.mts +1 -1
  86. package/api/index.mjs +1 -0
  87. package/api/init/init.doc.mjs +6 -1
  88. package/api/init/init.test.mjs +41 -1
  89. package/api/init/remove/remove.mjs +1 -1
  90. package/api/init/run/run.mjs +20 -10
  91. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  92. package/api/integration/add-contribution.d.mts +2 -1
  93. package/api/integration/add-contribution.mjs +130 -15
  94. package/api/integration/add-contribution.test.mjs +258 -7
  95. package/api/integration/add-helpers.d.mts +5 -2
  96. package/api/integration/add-helpers.mjs +36 -9
  97. package/api/integration/add-theme.mjs +34 -64
  98. package/api/integration/add-theme.test.mjs +105 -21
  99. package/api/integration/authoring-checks.mjs +138 -28
  100. package/api/integration/authoring-checks.test.mjs +179 -7
  101. package/api/integration/authoring-checks.type.mjs +6 -1
  102. package/api/integration/integration-authoring.type.d.mts +3 -1
  103. package/api/integration/integration-authoring.type.mjs +2 -0
  104. package/api/integration/integration-block-exports.test.mjs +10 -6
  105. package/api/integration/integrationAdd.doc.mjs +14 -4
  106. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  107. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  108. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  109. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  110. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  111. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  112. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  113. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  114. package/api/integration/integrationPackCheck.doc.mjs +2 -1
  115. package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
  116. package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
  117. package/api/integration/pack-check.mjs +83 -7
  118. package/api/integration/pack-check.test.mjs +387 -47
  119. package/api/integration/pack-check.type.d.mts +26 -2
  120. package/api/integration/pack-check.type.mjs +14 -1
  121. package/api/integration/summarizeIssues.doc.mjs +1 -0
  122. package/api/integration/template-conflict-compatibility.test.mjs +73 -0
  123. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  124. package/api/integration/validate-integration.mjs +52 -102
  125. package/api/integration/validate-integration.test.mjs +179 -26
  126. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  127. package/api/integration/validateIntegration.doc.mjs +3 -2
  128. package/api/json/assertResponse.doc.mjs +1 -0
  129. package/api/json/envelope-types.test.mjs +76 -0
  130. package/api/json/index.ts +2 -0
  131. package/api/json/isError.doc.mjs +1 -0
  132. package/api/json/parseResponse.doc.mjs +3 -2
  133. package/api/layout/_adapter.mjs +20 -5
  134. package/api/layout/expand/expand.mjs +7 -5
  135. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  136. package/api/layout/grammar/grammar.mjs +2 -1
  137. package/api/layout/layoutCheck.doc.mjs +1 -0
  138. package/api/layout/layoutExpand.doc.mjs +2 -1
  139. package/api/layout/layoutGrammar.doc.mjs +1 -0
  140. package/api/search/search-return-type.test.mjs +54 -0
  141. package/api/search/search.d.mts +62 -11
  142. package/api/search/search.doc.mjs +8 -2
  143. package/api/search/search.mjs +471 -83
  144. package/api/search/search.test.mjs +124 -1
  145. package/api/search/search.type.d.mts +15 -3
  146. package/api/search/search.type.mjs +5 -2
  147. package/api/swizzle/copy/copy.mjs +28 -11
  148. package/api/swizzle/swizzle.doc.mjs +2 -1
  149. package/api/swizzle/swizzle.type.d.mts +2 -2
  150. package/api/swizzle/swizzle.type.mjs +2 -2
  151. package/api/template/copy/copy.mjs +17 -23
  152. package/api/template/copy/copy.test.mjs +17 -0
  153. package/api/template/list/list.mjs +1 -0
  154. package/api/template/table-floating-bulk-actions.test.mjs +66 -0
  155. package/api/template/template-integration.test.mjs +1072 -3
  156. package/api/template/template-suffix.test.mjs +41 -21
  157. package/api/template/template.d.mts +1 -1
  158. package/api/template/template.doc.mjs +30 -8
  159. package/api/template/template.mjs +45 -8
  160. package/api/template/template.type.d.mts +12 -14
  161. package/api/template/template.type.mjs +15 -14
  162. package/api/theme/_adapter.d.mts +2 -3
  163. package/api/theme/_adapter.mjs +4 -5
  164. package/api/theme/add/add.binary.test.mjs +84 -0
  165. package/api/theme/add/add.mjs +31 -22
  166. package/api/theme/add/add.rollback.test.mjs +158 -0
  167. package/api/theme/add/add.staging.test.mjs +83 -0
  168. package/api/theme/add/add.test.mjs +14 -1
  169. package/api/theme/build/build.family.test.mjs +7 -12
  170. package/api/theme/build/build.mjs +140 -59
  171. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  172. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  173. package/api/theme/build/build.rollback.test.mjs +148 -0
  174. package/api/theme/build/build.test.mjs +127 -0
  175. package/api/theme/build/font-warning.mjs +3 -3
  176. package/api/theme/build/font-warning.test.mjs +5 -2
  177. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  178. package/api/theme/integration-themes.test.mjs +39 -28
  179. package/api/theme/list/list.test.mjs +19 -20
  180. package/api/theme/listThemes.doc.mjs +6 -5
  181. package/api/theme/palette/generate/generate.mjs +8 -3
  182. package/api/theme/palette/generate/generate.test.mjs +96 -0
  183. package/api/theme/palette/generate/generator.d.mts +10 -13
  184. package/api/theme/palette/generate/generator.mjs +15 -4
  185. package/api/theme/palette/generate/generator.test.mjs +10 -0
  186. package/api/theme/template/template.mjs +11 -2
  187. package/api/theme/template/template.test.mjs +20 -0
  188. package/api/theme/theme.type.d.mts +170 -11
  189. package/api/theme/theme.type.mjs +94 -27
  190. package/api/theme/themeAdd.doc.mjs +4 -3
  191. package/api/theme/themeBuild.doc.mjs +8 -4
  192. package/api/theme/themeList.doc.mjs +6 -3
  193. package/api/theme/themeListAvailable.doc.mjs +5 -3
  194. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  195. package/api/theme/themeTargets.doc.mjs +1 -0
  196. package/api/theme/themeTemplate.doc.mjs +6 -2
  197. package/api/upgrade/_adapter.d.mts +32 -5
  198. package/api/upgrade/_adapter.mjs +139 -22
  199. package/api/upgrade/list/list.mjs +2 -1
  200. package/api/upgrade/list/list.test.mjs +73 -0
  201. package/api/upgrade/project-context.test.mjs +272 -0
  202. package/api/upgrade/provider-agreement.test.mjs +152 -0
  203. package/api/upgrade/run/run.mjs +356 -59
  204. package/api/upgrade/status/status.mjs +2 -2
  205. package/api/upgrade/upgrade.doc.mjs +12 -5
  206. package/api/upgrade/upgrade.type.d.mts +43 -5
  207. package/api/upgrade/upgrade.type.mjs +27 -11
  208. package/assets/codemods/__tests__/registry.test.mjs +1 -0
  209. package/assets/codemods/__tests__/runner.test.mjs +330 -8
  210. package/assets/codemods/integration-discovery.mjs +48 -4
  211. package/assets/codemods/integration-discovery.test.mjs +73 -0
  212. package/assets/codemods/integration-runner.mjs +56 -4
  213. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  214. package/assets/codemods/registry.mjs +1 -0
  215. package/assets/codemods/run-codemod.mjs +177 -34
  216. package/assets/codemods/runner.mjs +350 -102
  217. package/assets/codemods/term-log.mjs +32 -8
  218. package/assets/codemods/term-log.test.mjs +19 -1
  219. package/assets/codemods/transform-prop.mjs +109 -0
  220. package/assets/codemods/transform-prop.test.mjs +95 -0
  221. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  222. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  223. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  224. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  225. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  226. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  227. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  228. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  229. package/assets/codemods/transforms/v0.6.4/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  230. package/assets/codemods/transforms/v0.6.4/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  231. package/assets/codemods/transforms/v0.6.4/index.mjs +31 -0
  232. package/assets/codemods/transforms/v0.6.4/migrate-native-picker-to-presentation.mjs +148 -0
  233. package/assets/codemods/transforms/v0.6.4/migrate-theme-catalog-to-descriptors.mjs +141 -0
  234. package/assets/docs/README.md +9 -0
  235. package/assets/docs/authoring.doc.mjs +14 -0
  236. package/assets/docs/getting-started.doc.mjs +2 -2
  237. package/assets/docs/internationalization.doc.mjs +7 -5
  238. package/assets/docs/layout.doc.dense.mjs +2 -2
  239. package/assets/docs/layout.doc.mjs +1 -1
  240. package/assets/docs/principles.doc.mjs +6 -6
  241. package/assets/docs/styling-libraries.doc.mjs +4 -4
  242. package/assets/docs/styling.doc.mjs +4 -4
  243. package/assets/docs/theme.doc.mjs +5 -5
  244. package/assets/docs/tokens.doc.mjs +1 -1
  245. package/assets/docs/tree/api.doc.mjs +30 -0
  246. package/assets/docs/tree/cli.doc.mjs +23 -0
  247. package/assets/docs/tree/commands.doc.mjs +25 -0
  248. package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +144 -26
  249. package/assets/docs/tree/integrations.test.mjs +62 -0
  250. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  251. package/assets/docs/working-with-ai.doc.mjs +4 -4
  252. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
  253. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
  254. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  255. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  256. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  257. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  258. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  259. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  260. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  261. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  262. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  263. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  264. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  265. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  266. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  267. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  268. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  269. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  270. package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
  271. package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
  272. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
  273. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
  274. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  275. package/assets/templates/blocks/components/Timer/TimerFormats.doc.mjs +14 -0
  276. package/assets/templates/blocks/components/Timer/TimerFormats.tsx +34 -0
  277. package/assets/templates/blocks/components/Timer/TimerInline.doc.mjs +14 -0
  278. package/assets/templates/blocks/components/Timer/TimerInline.tsx +14 -0
  279. package/assets/templates/blocks/components/Timer/TimerShowcase.doc.mjs +13 -0
  280. package/assets/templates/blocks/components/Timer/TimerShowcase.tsx +47 -0
  281. package/assets/templates/blocks/components/Timer/TimerTypography.doc.mjs +14 -0
  282. package/assets/templates/blocks/components/Timer/TimerTypography.tsx +31 -0
  283. package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.doc.mjs +19 -3
  284. package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +383 -65
  285. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  286. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  287. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  288. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  289. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  290. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  291. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  292. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  293. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  294. package/authoring/_shared/contract.ts +22 -0
  295. package/authoring/codemod/codemod.doc.mjs +7 -2
  296. package/authoring/codemod/parse.d.mts +8 -8
  297. package/authoring/codemod/parse.mjs +8 -6
  298. package/authoring/codemod/type.ts +12 -0
  299. package/authoring/config/config.doc.mjs +10 -2
  300. package/authoring/config/debug-composition.test.mjs +92 -0
  301. package/authoring/config/parse.d.mts +15 -13
  302. package/authoring/config/parse.mjs +27 -8
  303. package/authoring/config/parse.test.mjs +8 -0
  304. package/authoring/config/type.ts +29 -6
  305. package/authoring/debug/debug.doc.d.mts +11 -0
  306. package/authoring/debug/debug.doc.mjs +182 -0
  307. package/authoring/debug/parse.d.mts +8 -8
  308. package/authoring/debug/parse.mjs +3 -3
  309. package/authoring/discover/discover.doc.d.mts +13 -0
  310. package/authoring/discover/discover.doc.mjs +138 -0
  311. package/authoring/discover/parse.d.mts +24 -0
  312. package/authoring/discover/parse.mjs +128 -0
  313. package/authoring/discover/parse.test.mjs +124 -0
  314. package/authoring/discover/type.ts +87 -0
  315. package/authoring/doctypes/_schema.d.mts +790 -23
  316. package/authoring/doctypes/_schema.mjs +543 -39
  317. package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
  318. package/authoring/doctypes/base/graph-fields.doc.mjs +64 -0
  319. package/authoring/doctypes/base/type.ts +41 -0
  320. package/authoring/doctypes/command/command.doc.mjs +4 -3
  321. package/authoring/doctypes/command/parse.d.mts +2 -2
  322. package/authoring/doctypes/command/parse.mjs +1 -1
  323. package/authoring/doctypes/command/type.ts +5 -4
  324. package/authoring/doctypes/component/component.doc.mjs +6 -3
  325. package/authoring/doctypes/component/parse.d.mts +2 -2
  326. package/authoring/doctypes/component/parse.mjs +1 -1
  327. package/authoring/doctypes/component/type.ts +6 -5
  328. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  329. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  330. package/authoring/doctypes/enum/parse.d.mts +2 -2
  331. package/authoring/doctypes/enum/parse.mjs +1 -1
  332. package/authoring/doctypes/enum/type.ts +4 -2
  333. package/authoring/doctypes/function/function.doc.mjs +7 -2
  334. package/authoring/doctypes/function/parse.d.mts +2 -2
  335. package/authoring/doctypes/function/parse.mjs +1 -1
  336. package/authoring/doctypes/function/type.ts +9 -4
  337. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  338. package/authoring/doctypes/hook/parse.d.mts +2 -2
  339. package/authoring/doctypes/hook/parse.mjs +1 -1
  340. package/authoring/doctypes/hook/type.ts +5 -4
  341. package/authoring/doctypes/legacy.d.mts +8 -6
  342. package/authoring/doctypes/legacy.mjs +5 -4
  343. package/authoring/doctypes/load-contract.test.mjs +233 -0
  344. package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
  345. package/authoring/doctypes/namespace/namespace.doc.mjs +128 -0
  346. package/authoring/doctypes/namespace/parse.d.mts +12 -0
  347. package/authoring/doctypes/namespace/parse.mjs +25 -0
  348. package/authoring/doctypes/namespace/parse.test.mjs +163 -0
  349. package/authoring/doctypes/namespace/type.ts +74 -0
  350. package/authoring/doctypes/parse.d.mts +22 -18
  351. package/authoring/doctypes/parse.mjs +22 -11
  352. package/authoring/doctypes/parse.test.mjs +77 -3
  353. package/authoring/doctypes/reference/parse.d.mts +2 -2
  354. package/authoring/doctypes/reference/parse.mjs +8 -5
  355. package/authoring/doctypes/reference/reference.doc.mjs +48 -6
  356. package/authoring/doctypes/reference/type.ts +70 -7
  357. package/authoring/doctypes/schema/parse.d.mts +2 -2
  358. package/authoring/doctypes/schema/parse.mjs +1 -1
  359. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  360. package/authoring/doctypes/schema/type.ts +4 -4
  361. package/authoring/doctypes/template/parse.d.mts +94 -1
  362. package/authoring/doctypes/template/parse.mjs +40 -2
  363. package/authoring/doctypes/template/parse.test.mjs +26 -2
  364. package/authoring/doctypes/template/template.doc.mjs +13 -3
  365. package/authoring/doctypes/template/type.ts +13 -2
  366. package/authoring/doctypes/theme/parse.d.mts +35 -0
  367. package/authoring/doctypes/theme/parse.mjs +76 -0
  368. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  369. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  370. package/authoring/doctypes/theme/type.ts +42 -0
  371. package/authoring/doctypes/types.ts +12 -10
  372. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  373. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  374. package/authoring/gap-report/parse.d.mts +10 -10
  375. package/authoring/gap-report/parse.mjs +6 -6
  376. package/authoring/gap-report/type.ts +1 -1
  377. package/authoring/identity/identity.doc.d.mts +9 -0
  378. package/authoring/identity/identity.doc.mjs +61 -0
  379. package/authoring/identity/type.ts +132 -0
  380. package/authoring/index.d.mts +3 -0
  381. package/authoring/index.d.ts +62 -17
  382. package/authoring/index.mjs +4 -1
  383. package/authoring/integration/integration.doc.mjs +15 -8
  384. package/authoring/integration/parse.d.mts +2 -2
  385. package/authoring/integration/parse.mjs +1 -1
  386. package/authoring/integration/parse.test.mjs +10 -1
  387. package/authoring/integration/schema.d.mts +6 -4
  388. package/authoring/integration/schema.mjs +9 -3
  389. package/authoring/integration/type.ts +19 -8
  390. package/authoring/shadcn/receipt.d.mts +6 -6
  391. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  392. package/clients/cli/command-load-failure.test.mjs +83 -0
  393. package/clients/cli/commands/blog.doc.mjs +1 -1
  394. package/clients/cli/commands/blog.mjs +23 -8
  395. package/clients/cli/commands/blog.test.mjs +42 -1
  396. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  397. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  398. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  399. package/clients/cli/commands/build-theme.mjs +16 -50
  400. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  401. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  402. package/clients/cli/commands/build.doc.mjs +16 -8
  403. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  404. package/clients/cli/commands/build.mjs +137 -114
  405. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  406. package/clients/cli/commands/build.text-fields.test.mjs +81 -0
  407. package/clients/cli/commands/component/index.mjs +3 -8
  408. package/clients/cli/commands/component-ownership.test.mjs +3 -3
  409. package/clients/cli/commands/component-package.test.mjs +46 -0
  410. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  411. package/clients/cli/commands/component.doc.mjs +1 -1
  412. package/clients/cli/commands/component.test.mjs +19 -0
  413. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  414. package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
  415. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  416. package/clients/cli/commands/discover.doc.mjs +55 -9
  417. package/clients/cli/commands/discover.mjs +393 -118
  418. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  419. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  420. package/clients/cli/commands/docs.doc.mjs +28 -6
  421. package/clients/cli/commands/docs.mjs +240 -26
  422. package/clients/cli/commands/docs.test.mjs +193 -1
  423. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  424. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
  425. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  426. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  427. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  428. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  429. package/clients/cli/commands/doctor-integration.test.mjs +90 -8
  430. package/clients/cli/commands/doctor.doc.mjs +1 -1
  431. package/clients/cli/commands/doctor.mjs +59 -32
  432. package/clients/cli/commands/doctor.test.mjs +42 -0
  433. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  434. package/clients/cli/commands/gap-report.test.mjs +72 -0
  435. package/clients/cli/commands/hook/index.mjs +7 -17
  436. package/clients/cli/commands/hook.doc.mjs +1 -1
  437. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  438. package/clients/cli/commands/init.doc.mjs +20 -9
  439. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  440. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  441. package/clients/cli/commands/integration-add.doc.mjs +32 -6
  442. package/clients/cli/commands/integration-authoring.test.mjs +13 -9
  443. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  444. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  445. package/clients/cli/commands/integration.doc.mjs +1 -1
  446. package/clients/cli/commands/integration.mjs +1 -0
  447. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  448. package/clients/cli/commands/json-contract.test.mjs +33 -0
  449. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  450. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  451. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  452. package/clients/cli/commands/layout.doc.mjs +3 -3
  453. package/clients/cli/commands/layout.mjs +21 -9
  454. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  455. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  456. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  457. package/clients/cli/commands/manifest.doc.mjs +1 -1
  458. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  459. package/clients/cli/commands/search.doc.mjs +7 -4
  460. package/clients/cli/commands/search.mjs +28 -9
  461. package/clients/cli/commands/search.test.mjs +75 -0
  462. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  463. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  464. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  465. package/clients/cli/commands/template.doc.mjs +52 -13
  466. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  467. package/clients/cli/commands/template.mjs +4 -91
  468. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  469. package/clients/cli/commands/text-json-parity.test.mjs +719 -0
  470. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  471. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  472. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  473. package/clients/cli/commands/theme-palette-generate.doc.mjs +9 -5
  474. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  475. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  476. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  477. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  478. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  479. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  480. package/clients/cli/commands/theme.doc.mjs +1 -1
  481. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  482. package/clients/cli/commands/upgrade.doc.mjs +22 -10
  483. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  484. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  485. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  486. package/clients/cli/commands/upgrade.mjs +29 -7
  487. package/clients/cli/formatters/index.mjs +164 -1
  488. package/clients/cli/formatters/index.test.mjs +97 -0
  489. package/clients/cli/index.mjs +21 -30
  490. package/clients/cli/latest-version-env.test.mjs +50 -0
  491. package/clients/cli/lib/cli-error.test.mjs +7 -0
  492. package/clients/cli/lib/component-format.mjs +9 -9
  493. package/clients/cli/lib/component-format.test.mjs +1 -1
  494. package/clients/cli/lib/define-command.mjs +32 -6
  495. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  496. package/clients/cli/lib/exit-codes.test.mjs +97 -0
  497. package/clients/cli/lib/hook-format.mjs +19 -10
  498. package/clients/cli/lib/json-shim.mjs +38 -2
  499. package/clients/cli/lib/json-shim.test.mjs +83 -0
  500. package/clients/cli/lib/manifest.d.ts +2 -0
  501. package/clients/cli/lib/manifest.mjs +37 -2
  502. package/clients/cli/lib/manifest.test.mjs +17 -0
  503. package/foundation/agent-docs/agent-docs.d.mts +7 -2
  504. package/foundation/agent-docs/agent-docs.mjs +82 -12
  505. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  506. package/foundation/agent-docs/agent-docs.test.mjs +19 -1
  507. package/foundation/config/integration-debug.test.mjs +28 -3
  508. package/foundation/config/project-themes.test.mjs +11 -19
  509. package/foundation/config/project.d.mts +20 -11
  510. package/foundation/config/project.mjs +263 -91
  511. package/foundation/config/project.test.mjs +270 -21
  512. package/foundation/discovery/authoring-self-docs.d.mts +87 -0
  513. package/foundation/discovery/authoring-self-docs.mjs +237 -0
  514. package/foundation/discovery/authoring-self-docs.test.mjs +170 -0
  515. package/foundation/discovery/authoring-surface.d.mts +74 -0
  516. package/foundation/discovery/authoring-surface.mjs +525 -0
  517. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  518. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  519. package/foundation/discovery/cli-self-docs.mjs +490 -0
  520. package/foundation/discovery/cli-self-docs.test.mjs +375 -0
  521. package/foundation/discovery/component-discovery.d.mts +39 -1
  522. package/foundation/discovery/component-discovery.mjs +50 -1
  523. package/foundation/discovery/component-loader.d.mts +35 -38
  524. package/foundation/discovery/component-loader.mjs +53 -222
  525. package/foundation/discovery/docs-discovery.d.mts +119 -11
  526. package/foundation/discovery/docs-discovery.mjs +423 -108
  527. package/foundation/discovery/docs-discovery.test.mjs +365 -20
  528. package/foundation/discovery/docs-output-budget.d.mts +28 -0
  529. package/foundation/discovery/docs-output-budget.mjs +50 -0
  530. package/foundation/discovery/docs-section-key.d.mts +116 -0
  531. package/foundation/discovery/docs-section-key.mjs +322 -0
  532. package/foundation/discovery/docs-section-key.test.mjs +246 -0
  533. package/foundation/discovery/template-adapter.d.mts +113 -11
  534. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  535. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  536. package/foundation/discovery/template-adapter.mjs +774 -83
  537. package/foundation/discovery/template-adapter.test.mjs +57 -0
  538. package/foundation/discovery/template-conflict-release.d.mts +13 -0
  539. package/foundation/discovery/template-conflict-release.mjs +40 -0
  540. package/foundation/discovery/template-conflict-release.test.mjs +40 -0
  541. package/foundation/discovery/theme-discovery.d.mts +67 -7
  542. package/foundation/discovery/theme-discovery.mjs +916 -186
  543. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  544. package/foundation/discovery/theming-targets.test.mjs +4 -0
  545. package/foundation/doc-compiler/bundle.d.mts +47 -0
  546. package/foundation/doc-compiler/bundle.mjs +278 -0
  547. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  548. package/foundation/doc-compiler/compile.d.mts +343 -0
  549. package/foundation/doc-compiler/compile.mjs +558 -0
  550. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  551. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  552. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  553. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  554. package/foundation/doc-compiler/import.d.mts +24 -0
  555. package/foundation/doc-compiler/import.mjs +59 -0
  556. package/foundation/doc-compiler/inputs.d.mts +102 -0
  557. package/foundation/doc-compiler/inputs.mjs +291 -0
  558. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  559. package/foundation/doc-compiler/ir.d.mts +22 -0
  560. package/foundation/doc-compiler/ir.mjs +471 -0
  561. package/foundation/doc-compiler/lenses.d.mts +36 -0
  562. package/foundation/doc-compiler/lenses.mjs +173 -0
  563. package/foundation/doc-compiler/links.d.mts +162 -0
  564. package/foundation/doc-compiler/links.mjs +294 -0
  565. package/foundation/doc-compiler/links.test.mjs +192 -0
  566. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  567. package/foundation/doc-compiler/overlays.d.mts +37 -0
  568. package/foundation/doc-compiler/overlays.mjs +206 -0
  569. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  570. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  571. package/foundation/doc-compiler/read.d.mts +127 -0
  572. package/foundation/doc-compiler/read.mjs +325 -0
  573. package/foundation/doc-compiler/read.test.mjs +313 -0
  574. package/foundation/doc-compiler/source.d.mts +33 -0
  575. package/foundation/doc-compiler/source.mjs +128 -0
  576. package/foundation/doc-compiler/tree.d.mts +288 -0
  577. package/foundation/doc-compiler/tree.mjs +876 -0
  578. package/foundation/doc-compiler/tree.test.mjs +598 -0
  579. package/foundation/fs/file-protection.d.mts +33 -0
  580. package/foundation/fs/file-protection.mjs +825 -0
  581. package/foundation/fs/file-protection.test.mjs +250 -0
  582. package/foundation/fs/module-loader.d.mts +1 -0
  583. package/foundation/fs/module-loader.mjs +50 -1
  584. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  585. package/foundation/fs/path-safety.d.mts +3 -2
  586. package/foundation/fs/path-safety.mjs +49 -19
  587. package/foundation/fs/path-safety.test.mjs +50 -0
  588. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  589. package/foundation/identity/provider-identity.d.mts +90 -0
  590. package/foundation/identity/provider-identity.mjs +320 -0
  591. package/foundation/identity/provider-identity.test.mjs +254 -0
  592. package/foundation/identity/providers.d.mts +7 -0
  593. package/foundation/identity/providers.mjs +16 -0
  594. package/foundation/integrations/autolink.d.mts +58 -1
  595. package/foundation/integrations/autolink.mjs +143 -45
  596. package/foundation/integrations/autolink.test.mjs +1 -1
  597. package/foundation/integrations/cli-requirement.d.mts +45 -0
  598. package/foundation/integrations/cli-requirement.mjs +154 -0
  599. package/foundation/integrations/cli-requirement.test.mjs +84 -0
  600. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  601. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  602. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  603. package/foundation/integrations/contribution-inventory.mjs +27 -24
  604. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  605. package/foundation/integrations/integration-warnings.d.mts +9 -2
  606. package/foundation/integrations/integration-warnings.mjs +52 -21
  607. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  608. package/foundation/integrations/integrations.d.mts +63 -3
  609. package/foundation/integrations/integrations.mjs +122 -9
  610. package/foundation/integrations/integrations.test.mjs +415 -1
  611. package/foundation/integrations/provider-conflicts.test.mjs +125 -0
  612. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  613. package/foundation/integrations/provider-resolution.d.mts +152 -0
  614. package/foundation/integrations/provider-resolution.mjs +576 -0
  615. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  616. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  617. package/foundation/integrations/theme-descriptor.mjs +44 -0
  618. package/foundation/integrations/validate-contributions.d.mts +2 -0
  619. package/foundation/integrations/validate-contributions.mjs +131 -29
  620. package/foundation/response/base.d.ts +8 -4
  621. package/foundation/response/error-codes.d.mts +3 -1
  622. package/foundation/response/error-codes.d.ts +2 -0
  623. package/foundation/response/error-codes.doc.mjs +13 -4
  624. package/foundation/response/error-codes.mjs +8 -2
  625. package/foundation/response/error-codes.test.mjs +137 -10
  626. package/foundation/response/json-contract.test.mjs +57 -17
  627. package/foundation/response/json.d.mts +4 -2
  628. package/foundation/response/json.mjs +8 -10
  629. package/foundation/response/response-types.doc.d.mts +5 -1
  630. package/foundation/response/response-types.doc.mjs +41 -21
  631. package/foundation/response/response-types.doc.test.mjs +158 -0
  632. package/foundation/response/response.doc.mjs +1 -1
  633. package/foundation/text/string-utils.d.mts +8 -0
  634. package/foundation/text/string-utils.mjs +40 -10
  635. package/foundation/xle/expand.d.mts +2 -0
  636. package/foundation/xle/expand.mjs +4 -3
  637. package/foundation/xle/expand.test.mjs +54 -0
  638. package/foundation/xle/xle.test.mjs +13 -0
  639. package/package.json +10 -11
  640. package/assets/templates/themes/manifest.json +0 -95
  641. package/clients/cli/lib/update-check.mjs +0 -83
  642. package/clients/cli/lib/update-check.test.mjs +0 -137
  643. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -15,15 +15,16 @@ import {
15
15
  CORE_PACKAGE,
16
16
  discoverComponents,
17
17
  discoverExternalComponentsGrouped,
18
- discoverIntegrationComponents,
18
+ discoverValidIntegrationComponents,
19
19
  findComponentReadme,
20
+ findExternalComponentDoc,
20
21
  resolveImportPath,
21
22
  resolveIntegrationImportPath,
22
23
  } from '../../../foundation/discovery/component-discovery.mjs';
23
24
  import {discoverExternalPackages} from '../../../foundation/fs/paths.mjs';
24
25
  import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
25
26
  import {AstryxError} from '../../error.mjs';
26
- import {loadComponentDoc, loadIntegrationsSafely} from '../_adapter.mjs';
27
+ import {loadComponentDoc, loadIntegrationsSafely, withOwnership} from '../_adapter.mjs';
27
28
 
28
29
  /**
29
30
  * @typedef {import('../component.type.mjs').ComponentListResponse} ComponentListResponse
@@ -31,6 +32,29 @@ import {loadComponentDoc, loadIntegrationsSafely} from '../_adapter.mjs';
31
32
  * @typedef {import('../component.type.mjs').ComponentBriefEntry} ComponentBriefEntry
32
33
  */
33
34
 
35
+ /**
36
+ * The import a legacy `pkg.astryx.docs` component's detail reports, derived the
37
+ * same way (`withOwnership`) so list and detail agree.
38
+ * @param {{name: string, docsDir: string}} ext
39
+ * @param {string} name
40
+ * @param {string} coreDir
41
+ * @param {{zh: boolean, lang: string|null}} docOpts
42
+ * @returns {Promise<string>}
43
+ */
44
+ async function legacyImport(ext, name, coreDir, docOpts) {
45
+ const docPath = findExternalComponentDoc(ext.docsDir, name);
46
+ /** @type {import('../_adapter.mjs').LoadedComponentDoc} */
47
+ let docs = {};
48
+ if (docPath && docPath.endsWith('.doc.mjs')) {
49
+ try {
50
+ docs = await loadComponentDoc(docPath, docOpts);
51
+ } catch {
52
+ // Keep list resilient; validation owns malformed docs.
53
+ }
54
+ }
55
+ return withOwnership(docs, {package: ext.name, sourcePath: null}, name, coreDir).import;
56
+ }
57
+
34
58
  /**
35
59
  * Build the `component.list` envelope. The list taxonomy is collapsed: all
36
60
  * three detail levels emit ONE `component.list` type; the depth rides in
@@ -204,7 +228,8 @@ export async function componentList(
204
228
  const seenIntegration = new Set();
205
229
  for (const integration of loadedIntegrations) {
206
230
  seenIntegration.add(integration.name);
207
- const owned = discoverIntegrationComponents(integration);
231
+ const {components: owned} =
232
+ await discoverValidIntegrationComponents(integration);
208
233
  // Group integration components by their doc `group`, falling back to the
209
234
  // package name. Keys are package-qualified so they never collide with
210
235
  // core groups or each other.
@@ -267,20 +292,24 @@ export async function componentList(
267
292
  k => grouped[k].length > 1 || grouped[k][0] !== k,
268
293
  );
269
294
 
270
- if (hasGroups) {
271
- for (const [group, members] of Object.entries(grouped)) {
272
- listData[`${group} (${ext.name})`] = members.map(n => ({
295
+ /** @param {string[]} names */
296
+ const entriesFor = names =>
297
+ Promise.all(
298
+ names.map(async n => ({
273
299
  name: n,
274
300
  package: ext.name,
275
- }));
301
+ import: await legacyImport(ext, n, coreDir, {zh, lang}),
302
+ })),
303
+ );
304
+
305
+ if (hasGroups) {
306
+ for (const [group, members] of Object.entries(grouped)) {
307
+ listData[`${group} (${ext.name})`] = await entriesFor(members);
276
308
  }
277
309
  } else {
278
310
  const allComps = Object.values(grouped).flat().sort();
279
311
  if (allComps.length > 0) {
280
- listData[`${ext.category} (${ext.name})`] = allComps.map(n => ({
281
- name: n,
282
- package: ext.name,
283
- }));
312
+ listData[`${ext.category} (${ext.name})`] = await entriesFor(allComps);
284
313
  }
285
314
  }
286
315
  }
@@ -12,20 +12,78 @@
12
12
  * configured" (`false`) from "configured but nothing discovered" (`true`),
13
13
  * which the list leaf surfaces as `meta`.
14
14
  *
15
- * @returns {Promise<{packages: ScannedPackage[], configured: boolean}>}
15
+ * @returns {Promise<{packages: ScannedPackage[], configured: boolean, project: Project}>}
16
16
  */
17
17
  export function discoverPackages(): Promise<{
18
18
  packages: ScannedPackage[];
19
19
  configured: boolean;
20
+ project: Project;
20
21
  }>;
21
22
  /**
22
- * Project a scanned package into the discover list/detail entry shape. Shared
23
- * by the list and detail leaves so the entry keys (and their order) stay in one
24
- * place.
25
- * @param {ScannedPackage} pkg
23
+ * Every integration the project loads, with what it adds. An integration with
24
+ * no components root is included with `components: []`; one that failed to
25
+ * load is left out (the integration-issues nudge and Doctor report it).
26
+ *
27
+ * @param {Project | undefined} project
28
+ * @param {ScannedPackage[]} scanned the packages {@link discoverPackages} found
29
+ * @returns {Promise<InstalledPackage[]>}
30
+ */
31
+ export function describeInstalled(project: Project | undefined, scanned: ScannedPackage[]): Promise<InstalledPackage[]>;
32
+ /**
33
+ * Whether the project has any discover source: its own `discover` config field,
34
+ * or an integration's `discover` named export (valid or not).
35
+ * @param {Project | undefined} project
36
+ * @returns {boolean}
37
+ */
38
+ export function hasSources(project: Project | undefined): boolean;
39
+ /**
40
+ * Package names the project's package.json declares in any dependency field.
41
+ * @param {Project | undefined} project
42
+ * @returns {Set<string>}
43
+ */
44
+ export function declaredDependencies(project: Project | undefined): Set<string>;
45
+ /**
46
+ * The command that adds a package with the project's package manager. Discover
47
+ * only prints it; it never runs it.
48
+ * @param {Project | undefined} project
49
+ * @returns {(name: string, version?: string) => string}
50
+ */
51
+ export function addCommand(project: Project | undefined): (name: string, version?: string) => string;
52
+ /**
53
+ * The per-user cache directory the saved copies live in, never inside a
54
+ * project. Standard platform locations only.
55
+ * @returns {string}
56
+ */
57
+ export function defaultCacheDir(): string;
58
+ /**
59
+ * Call every discover source — the project's `discover` first, then each
60
+ * integration's in load order — once per distinct function. A source that
61
+ * throws, times out, or returns an invalid catalog falls back to its saved copy;
62
+ * with none, it is reported and adds nothing. The others always count.
63
+ *
64
+ * @param {Project | undefined} project
65
+ * @param {{package?: string, version?: string}} [request] ask for one package,
66
+ * and optionally one version's contributions
67
+ * @param {{cacheDir?: string, timeoutMs?: number}} [options]
68
+ * @returns {Promise<CatalogResult>}
69
+ */
70
+ export function callSources(project: Project | undefined, request?: {
71
+ package?: string;
72
+ version?: string;
73
+ }, options?: {
74
+ cacheDir?: string;
75
+ timeoutMs?: number;
76
+ }): Promise<CatalogResult>;
77
+ /**
78
+ * Project a scanned or installed package into the discover list/detail entry
79
+ * shape. Shared by the list and detail leaves so the entry keys (and their
80
+ * order) stay in one place. A kind list appears only when it is not empty.
81
+ * @param {InstalledPackage & {latest?: string}} pkg
26
82
  * @returns {import('./discover.type.mjs').DiscoverListEntry}
27
83
  */
28
- export function toEntry(pkg: ScannedPackage): import("./discover.type.mjs").DiscoverListEntry;
84
+ export function toEntry(pkg: InstalledPackage & {
85
+ latest?: string;
86
+ }): import("./discover.type.mjs").DiscoverListEntry;
29
87
  /**
30
88
  * Locate a component's doc file within the given packages (case-insensitive).
31
89
  * @param {ScannedPackage[]} packages
@@ -46,7 +104,56 @@ export function loadValidatedDoc(result: ComponentResolution, { lang, zh }: {
46
104
  lang?: string | null;
47
105
  zh?: boolean;
48
106
  }): Promise<import("./discover.type.mjs").DiscoverDetailDocResponse["data"]>;
107
+ /** The list and detail entry fields for each item kind, in display order. */
108
+ export const KIND_FIELDS: readonly [readonly ["component", "components"], readonly ["template", "templates"], readonly ["doc", "docs"], readonly ["theme", "themes"], readonly ["codemod", "codemods"], readonly ["agent-doc", "agentDocs"]];
49
109
  export type ScannedPackage = import("./_package-scanner.mjs").ScannedPackage;
110
+ export type DiscoverPackage = import("../../authoring/discover/type").DiscoverPackage;
111
+ export type DiscoverSource = import("../../authoring/discover/type").DiscoverSource;
112
+ /**
113
+ * An installed integration with what it adds, per kind. `components` is the
114
+ * scanned component list the discover leaves have always used.
115
+ */
116
+ export type InstalledPackage = ScannedPackage & {
117
+ templates?: string[];
118
+ docs?: string[];
119
+ themes?: string[];
120
+ codemods?: string[];
121
+ };
122
+ /**
123
+ * What one source did on this run.
124
+ */
125
+ export type SourceState = {
126
+ /**
127
+ * the source's own name, or where it came from when it
128
+ * gave none
129
+ */
130
+ name: string;
131
+ /**
132
+ * `astryx.config`, or the integration that exports it
133
+ */
134
+ from: string;
135
+ status: "fresh" | "saved" | "failed";
136
+ generatedAt?: string | undefined;
137
+ complete?: boolean | undefined;
138
+ /**
139
+ * when the saved copy in use was written
140
+ */
141
+ savedAt?: string | undefined;
142
+ /**
143
+ * why the live call failed
144
+ */
145
+ error?: string | undefined;
146
+ };
147
+ /**
148
+ * Everything every source returned, merged. When two sources list the same
149
+ * package, the earlier source's entry is kept.
150
+ */
151
+ export type CatalogResult = {
152
+ sources: SourceState[];
153
+ packages: Array<DiscoverPackage & {
154
+ source: string;
155
+ }>;
156
+ };
50
157
  /**
51
158
  * A located component doc within a scanned package — the shape returned by
52
159
  * {@link findComponent}, consumed by {@link loadValidatedDoc}.
@@ -56,3 +163,4 @@ export type ComponentResolution = {
56
163
  docPath: string;
57
164
  componentName: string;
58
165
  };
166
+ import { Project } from '../../foundation/config/project.mjs';
@@ -1,31 +1,81 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
3
  /**
4
- * @file Shared external-package adapter for the discover leaves.
4
+ * @file Shared adapter for the discover leaves: the one place discover reaches
5
+ * the environment.
5
6
  *
6
7
  * Every `discover.*` leaf projects already-resolved data into a typed response;
7
- * none of them touch the integration system or the filesystem directly. This
8
- * adapter is the single place that does: it discovers the configured external
9
- * packages, locates a component's doc file within them, and loads + validates a
10
- * component's docs. Keeping that I/O here (rather than duplicated across leaves)
11
- * is what lets `list`, `detail`, `detail/doc`, and `search` stay pure
12
- * projections.
8
+ * none of them touch the integration system, the filesystem, or a source. This
9
+ * adapter does: it resolves the project's installed integrations and what each
10
+ * one adds, calls every discover source and keeps a saved copy of each answer,
11
+ * locates and loads a component's doc, and names the package manager's add
12
+ * command. Keeping that I/O here (INV21) is what lets `list`, `detail`,
13
+ * `detail/doc`, `detail/item`, and `search` stay pure projections.
13
14
  *
14
- * @position api/discover — orchestration over lib/project, lib/package-scanner,
15
- * and lib/component-loader; the discover dispatcher + leaves consume it.
15
+ * @position api/discover — orchestration over foundation/config/project,
16
+ * foundation/integrations, the discovery loaders, and discover sources.
16
17
  */
17
18
 
19
+ import {createHash} from 'node:crypto';
20
+ import * as fs from 'node:fs';
21
+ import * as os from 'node:os';
22
+ import * as path from 'node:path';
18
23
  import {Project} from '../../foundation/config/project.mjs';
19
24
  import {
20
25
  scanAllPackages,
21
26
  findComponentInPackages,
22
27
  } from './_package-scanner.mjs';
23
28
  import {loadDocs} from '../../foundation/discovery/component-loader.mjs';
29
+ import {collectIdentities} from '../../foundation/integrations/contribution-inventory.mjs';
30
+ import {detectPackageManager} from '../../foundation/env/package-manager.mjs';
31
+ import {assertWithin} from '../../foundation/fs/path-safety.mjs';
32
+ import {parseDiscoverCatalog} from '../../authoring/discover/parse.mjs';
24
33
  import {AstryxError} from '../error.mjs';
25
34
  import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
26
35
 
36
+ const SOURCE_TIMEOUT_MS = 30_000;
37
+
38
+ const DEPENDENCY_FIELDS = [
39
+ 'dependencies',
40
+ 'devDependencies',
41
+ 'optionalDependencies',
42
+ 'peerDependencies',
43
+ ];
44
+
27
45
  /**
28
46
  * @typedef {import('./_package-scanner.mjs').ScannedPackage} ScannedPackage
47
+ * @typedef {import('../../authoring/discover/type').DiscoverPackage} DiscoverPackage
48
+ * @typedef {import('../../authoring/discover/type').DiscoverSource} DiscoverSource
49
+ */
50
+
51
+ /**
52
+ * An installed integration with what it adds, per kind. `components` is the
53
+ * scanned component list the discover leaves have always used.
54
+ * @typedef {ScannedPackage & {
55
+ * templates?: string[],
56
+ * docs?: string[],
57
+ * themes?: string[],
58
+ * codemods?: string[],
59
+ * }} InstalledPackage
60
+ */
61
+
62
+ /**
63
+ * What one source did on this run.
64
+ * @typedef {object} SourceState
65
+ * @property {string} name the source's own name, or where it came from when it
66
+ * gave none
67
+ * @property {string} from `astryx.config`, or the integration that exports it
68
+ * @property {'fresh' | 'saved' | 'failed'} status
69
+ * @property {string} [generatedAt]
70
+ * @property {boolean} [complete]
71
+ * @property {string} [savedAt] when the saved copy in use was written
72
+ * @property {string} [error] why the live call failed
73
+ */
74
+
75
+ /**
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
29
79
  */
30
80
 
31
81
  /**
@@ -68,7 +118,7 @@ function validateDocs(docs) {
68
118
  * configured" (`false`) from "configured but nothing discovered" (`true`),
69
119
  * which the list leaf surfaces as `meta`.
70
120
  *
71
- * @returns {Promise<{packages: ScannedPackage[], configured: boolean}>}
121
+ * @returns {Promise<{packages: ScannedPackage[], configured: boolean, project: Project}>}
72
122
  */
73
123
  export async function discoverPackages() {
74
124
  const project = await Project.load();
@@ -86,25 +136,323 @@ export async function discoverPackages() {
86
136
  docsDir: integration.components,
87
137
  }));
88
138
  if (explicitPackages.length === 0) {
89
- return {packages: [], configured: loadedIntegrations.length > 0};
139
+ return {packages: [], configured: loadedIntegrations.length > 0, project};
90
140
  }
91
141
 
92
142
  const packages = scanAllPackages(
93
143
  [],
94
144
  /** @type {ScannedPackage[]} */ (/** @type {unknown} */ (explicitPackages)),
95
145
  );
96
- return {packages, configured: true};
146
+ return {packages, configured: true, project};
147
+ }
148
+
149
+ /**
150
+ * Every integration the project loads, with what it adds. An integration with
151
+ * no components root is included with `components: []`; one that failed to
152
+ * load is left out (the integration-issues nudge and Doctor report it).
153
+ *
154
+ * @param {Project | undefined} project
155
+ * @param {ScannedPackage[]} scanned the packages {@link discoverPackages} found
156
+ * @returns {Promise<InstalledPackage[]>}
157
+ */
158
+ export async function describeInstalled(project, scanned) {
159
+ if (project == null) return scanned;
160
+ const byName = new Map(scanned.map(pkg => [pkg.name, pkg]));
161
+ /** @type {InstalledPackage[]} */
162
+ const installed = [];
163
+ for (const integration of project.loadedIntegrations) {
164
+ if (integration.__loadError) continue;
165
+ const base =
166
+ byName.get(integration.name) ??
167
+ /** @type {ScannedPackage} */ (
168
+ /** @type {unknown} */ ({
169
+ name: integration.name,
170
+ category: integration.name,
171
+ version: integration.version,
172
+ components: [],
173
+ })
174
+ );
175
+ // Components come from the scan above; loading every component doc again
176
+ // here would only slow the list down.
177
+ const {identities} = await collectIdentities({
178
+ ...integration,
179
+ components: undefined,
180
+ });
181
+ installed.push({
182
+ ...base,
183
+ templates: identities.templates.map(t => t.id),
184
+ docs: identities.docs,
185
+ themes: identities.themes.map(t => t.slug),
186
+ codemods: identities.codemods.map(c => `${c.version}/${c.id}`),
187
+ });
188
+ }
189
+ return installed;
97
190
  }
98
191
 
99
192
  /**
100
- * Project a scanned package into the discover list/detail entry shape. Shared
101
- * by the list and detail leaves so the entry keys (and their order) stay in one
102
- * place.
103
- * @param {ScannedPackage} pkg
193
+ * Whether the project has any discover source: its own `discover` config field,
194
+ * or an integration's `discover` named export (valid or not).
195
+ * @param {Project | undefined} project
196
+ * @returns {boolean}
197
+ */
198
+ export function hasSources(project) {
199
+ if (project == null) return false;
200
+ if (typeof project.config?.discover === 'function') return true;
201
+ return project.loadedIntegrations.some(
202
+ i => i.__discover != null || i.__discoverError != null,
203
+ );
204
+ }
205
+
206
+ /**
207
+ * Package names the project's package.json declares in any dependency field.
208
+ * @param {Project | undefined} project
209
+ * @returns {Set<string>}
210
+ */
211
+ export function declaredDependencies(project) {
212
+ /** @type {Set<string>} */
213
+ const names = new Set();
214
+ if (project == null) return names;
215
+ try {
216
+ const pkg = JSON.parse(
217
+ fs.readFileSync(path.join(project.cwd, 'package.json'), 'utf8'),
218
+ );
219
+ for (const field of DEPENDENCY_FIELDS) {
220
+ for (const name of Object.keys(pkg?.[field] ?? {})) names.add(name);
221
+ }
222
+ } catch {
223
+ // No readable package.json: nothing is declared.
224
+ }
225
+ return names;
226
+ }
227
+
228
+ /**
229
+ * The command that adds a package with the project's package manager. Discover
230
+ * only prints it; it never runs it.
231
+ * @param {Project | undefined} project
232
+ * @returns {(name: string, version?: string) => string}
233
+ */
234
+ export function addCommand(project) {
235
+ const pm = detectPackageManager(project?.cwd ?? process.cwd());
236
+ const verb =
237
+ pm === 'pnpm'
238
+ ? 'pnpm add'
239
+ : pm === 'yarn'
240
+ ? 'yarn add'
241
+ : pm === 'bun'
242
+ ? 'bun add'
243
+ : 'npm install';
244
+ return (name, version) => `${verb} ${version ? `${name}@${version}` : name}`;
245
+ }
246
+
247
+ /**
248
+ * The per-user cache directory the saved copies live in, never inside a
249
+ * project. Standard platform locations only.
250
+ * @returns {string}
251
+ */
252
+ 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
+ );
268
+ }
269
+
270
+ /**
271
+ * @param {string} cacheDir
272
+ * @param {string} from
273
+ * @param {{package?: string, version?: string}} request
274
+ */
275
+ function savedCopyPath(cacheDir, from, request) {
276
+ const key = createHash('sha256')
277
+ .update(`${from}\n${request.package ?? ''}\n${request.version ?? ''}`)
278
+ .digest('hex')
279
+ .slice(0, 32);
280
+ const dir = path.join(cacheDir, 'discover');
281
+ return assertWithin(`${key}.json`, dir, {label: 'discover saved copy'});
282
+ }
283
+
284
+ /**
285
+ * @param {string} file
286
+ * @param {string} label
287
+ */
288
+ function readSavedCopy(file, label) {
289
+ try {
290
+ const saved = JSON.parse(fs.readFileSync(file, 'utf8'));
291
+ return {
292
+ savedAt: String(saved.savedAt),
293
+ catalog: parseDiscoverCatalog(saved.catalog, label),
294
+ };
295
+ } catch {
296
+ return null;
297
+ }
298
+ }
299
+
300
+ /**
301
+ * @param {string} file
302
+ * @param {import('../../authoring/discover/type').DiscoverCatalog} catalog
303
+ */
304
+ function writeSavedCopy(file, catalog) {
305
+ try {
306
+ fs.mkdirSync(path.dirname(file), {recursive: true});
307
+ const tmp = `${file}.${process.pid}.tmp`;
308
+ fs.writeFileSync(
309
+ tmp,
310
+ JSON.stringify({savedAt: new Date().toISOString(), catalog}),
311
+ );
312
+ fs.renameSync(tmp, file);
313
+ } catch {
314
+ // An unwritable cache only costs the offline copy.
315
+ }
316
+ }
317
+
318
+ /**
319
+ * @param {DiscoverSource} source
320
+ * @param {{package?: string, version?: string}} request
321
+ * @param {string} label
322
+ * @param {number} timeoutMs
323
+ */
324
+ async function callSource(source, request, label, timeoutMs) {
325
+ const controller = new AbortController();
326
+ /** @type {ReturnType<typeof setTimeout> | undefined} */
327
+ let timer;
328
+ const timedOut = new Promise((_, reject) => {
329
+ timer = setTimeout(() => {
330
+ controller.abort();
331
+ reject(
332
+ new Error(`${label} did not answer within ${timeoutMs / 1000} seconds`),
333
+ );
334
+ }, timeoutMs);
335
+ });
336
+ try {
337
+ const answer = await Promise.race([
338
+ Promise.resolve().then(() =>
339
+ source({signal: controller.signal, ...request}),
340
+ ),
341
+ timedOut,
342
+ ]);
343
+ return parseDiscoverCatalog(answer, label);
344
+ } finally {
345
+ clearTimeout(timer);
346
+ }
347
+ }
348
+
349
+ /**
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
352
+ * throws, times out, or returns an invalid catalog falls back to its saved copy;
353
+ * with none, it is reported and adds nothing. The others always count.
354
+ *
355
+ * @param {Project | undefined} project
356
+ * @param {{package?: string, version?: string}} [request] ask for one package,
357
+ * and optionally one version's contributions
358
+ * @param {{cacheDir?: string, timeoutMs?: number}} [options]
359
+ * @returns {Promise<CatalogResult>}
360
+ */
361
+ export async function callSources(project, request = {}, options = {}) {
362
+ const {cacheDir = defaultCacheDir(), timeoutMs = SOURCE_TIMEOUT_MS} = options;
363
+ /** @type {CatalogResult} */
364
+ const result = {sources: [], packages: []};
365
+ if (project == null) return result;
366
+
367
+ /** @type {Array<{from: string, source?: DiscoverSource, error?: string}>} */
368
+ const origins = [];
369
+ if (typeof project.config?.discover === 'function') {
370
+ origins.push({from: 'astryx.config', source: project.config.discover});
371
+ }
372
+ for (const integration of project.loadedIntegrations) {
373
+ if (integration.__discoverError) {
374
+ origins.push({from: integration.name, error: integration.__discoverError});
375
+ } else if (integration.__discover) {
376
+ origins.push({from: integration.name, source: integration.__discover});
377
+ }
378
+ }
379
+
380
+ /** @type {Set<unknown>} */
381
+ const called = new Set();
382
+ /** @type {Set<string>} */
383
+ const seen = new Set();
384
+ const ask = request.package
385
+ ? {package: request.package, ...(request.version ? {version: request.version} : {})}
386
+ : {};
387
+ for (const {from, source, error} of origins) {
388
+ if (source == null) {
389
+ result.sources.push({name: from, from, status: 'failed', error});
390
+ continue;
391
+ }
392
+ if (called.has(source)) continue;
393
+ called.add(source);
394
+
395
+ const label = `the discover source from ${from}`;
396
+ const file = savedCopyPath(cacheDir, from, ask);
397
+ /** @type {import('../../authoring/discover/type').DiscoverCatalog} */
398
+ let catalog;
399
+ try {
400
+ catalog = await callSource(source, ask, label, timeoutMs);
401
+ writeSavedCopy(file, catalog);
402
+ result.sources.push({
403
+ name: catalog.source.name,
404
+ from,
405
+ status: 'fresh',
406
+ generatedAt: catalog.source.generatedAt,
407
+ complete: catalog.source.complete,
408
+ });
409
+ } catch (err) {
410
+ const message = err instanceof Error ? err.message : String(err);
411
+ const saved = readSavedCopy(file, label);
412
+ if (saved == null) {
413
+ result.sources.push({name: from, from, status: 'failed', error: message});
414
+ continue;
415
+ }
416
+ catalog = saved.catalog;
417
+ result.sources.push({
418
+ name: catalog.source.name,
419
+ from,
420
+ status: 'saved',
421
+ generatedAt: catalog.source.generatedAt,
422
+ complete: catalog.source.complete,
423
+ savedAt: saved.savedAt,
424
+ error: message,
425
+ });
426
+ }
427
+ for (const pkg of catalog.packages) {
428
+ if (seen.has(pkg.package)) continue;
429
+ seen.add(pkg.package);
430
+ result.packages.push({...pkg, source: catalog.source.name});
431
+ }
432
+ }
433
+ return result;
434
+ }
435
+
436
+ /** The list and detail entry fields for each item kind, in display order. */
437
+ export const KIND_FIELDS = /** @type {const} */ ([
438
+ ['component', 'components'],
439
+ ['template', 'templates'],
440
+ ['doc', 'docs'],
441
+ ['theme', 'themes'],
442
+ ['codemod', 'codemods'],
443
+ ['agent-doc', 'agentDocs'],
444
+ ]);
445
+
446
+ /**
447
+ * Project a scanned or installed package into the discover list/detail entry
448
+ * shape. Shared by the list and detail leaves so the entry keys (and their
449
+ * order) stay in one place. A kind list appears only when it is not empty.
450
+ * @param {InstalledPackage & {latest?: string}} pkg
104
451
  * @returns {import('./discover.type.mjs').DiscoverListEntry}
105
452
  */
106
453
  export function toEntry(pkg) {
107
- return {
454
+ /** @type {Record<string, unknown>} */
455
+ const entry = {
108
456
  name: pkg.name,
109
457
  category: pkg.category,
110
458
  components: pkg.components,
@@ -112,6 +460,13 @@ export function toEntry(pkg) {
112
460
  description: pkg.description,
113
461
  displayName: pkg.displayName,
114
462
  };
463
+ for (const [, field] of KIND_FIELDS) {
464
+ if (field === 'components') continue;
465
+ const values = /** @type {Record<string, unknown>} */ (pkg)[field];
466
+ if (Array.isArray(values) && values.length > 0) entry[field] = values;
467
+ }
468
+ if (pkg.latest) entry.latest = pkg.latest;
469
+ return /** @type {import('./discover.type.mjs').DiscoverListEntry} */ (entry);
115
470
  }
116
471
 
117
472
  /**