@astryxdesign/cli 0.6.4 → 0.6.5-canary.00f1ed9

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 (405) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +103 -95
  3. package/api/build/_adapter.d.mts +36 -2
  4. package/api/build/_adapter.mjs +41 -10
  5. package/api/build/build.doc.mjs +8 -3
  6. package/api/build/build.test.mjs +60 -2
  7. package/api/build/kit/kit.mjs +109 -26
  8. package/api/build/kit/rank.d.mts +24 -8
  9. package/api/build/kit/rank.mjs +277 -97
  10. package/api/build/kit/rank.test.mjs +231 -48
  11. package/api/component/_adapter.d.mts +25 -0
  12. package/api/component/_adapter.mjs +59 -5
  13. package/api/component/component.d.mts +6 -3
  14. package/api/component/component.doc.mjs +37 -17
  15. package/api/component/component.mjs +249 -9
  16. package/api/component/component.type.d.mts +25 -0
  17. package/api/component/component.type.mjs +44 -0
  18. package/api/discover/_adapter.d.mts +114 -6
  19. package/api/discover/_adapter.mjs +372 -17
  20. package/api/discover/_adapter.test.mjs +215 -0
  21. package/api/discover/_catalog-view.d.mts +115 -0
  22. package/api/discover/_catalog-view.mjs +203 -0
  23. package/api/discover/_catalog-view.test.mjs +128 -0
  24. package/api/discover/detail/detail.d.mts +18 -6
  25. package/api/discover/detail/detail.mjs +67 -13
  26. package/api/discover/detail/detail.test.mjs +85 -0
  27. package/api/discover/detail/item/item.d.mts +26 -0
  28. package/api/discover/detail/item/item.mjs +78 -0
  29. package/api/discover/detail/item/item.test.mjs +73 -0
  30. package/api/discover/discover.d.mts +3 -9
  31. package/api/discover/discover.doc.mjs +61 -18
  32. package/api/discover/discover.mjs +220 -36
  33. package/api/discover/discover.test.mjs +11 -2
  34. package/api/discover/discover.type.d.mts +147 -8
  35. package/api/discover/discover.type.mjs +102 -12
  36. package/api/discover/list/list.d.mts +20 -6
  37. package/api/discover/list/list.mjs +45 -12
  38. package/api/discover/list/list.test.mjs +46 -0
  39. package/api/discover/search/search.d.mts +18 -16
  40. package/api/discover/search/search.mjs +102 -56
  41. package/api/discover/search/search.test.mjs +144 -10
  42. package/api/docs/_adapter.d.mts +8 -3
  43. package/api/docs/_adapter.mjs +14 -6
  44. package/api/docs/docOverlays.test.mjs +27 -1
  45. package/api/docs/docs.doc.mjs +2 -2
  46. package/api/docs/docs.test.mjs +54 -18
  47. package/api/docs/integration-tree.test.mjs +17 -0
  48. package/api/docs/integrationDocs.test.mjs +27 -5
  49. package/api/doctor/doctor.d.mts +8 -3
  50. package/api/doctor/doctor.doc.mjs +17 -8
  51. package/api/doctor/doctor.mjs +90 -9
  52. package/api/doctor/doctor.test.mjs +122 -10
  53. package/api/doctor/doctor.type.d.mts +1 -1
  54. package/api/doctor/doctor.type.mjs +1 -1
  55. package/api/error.d.mts +22 -0
  56. package/api/error.mjs +42 -0
  57. package/api/gap-report/gap-report.doc.mjs +19 -10
  58. package/api/hook/hook.doc.mjs +6 -3
  59. package/api/index.d.mts +1 -0
  60. package/api/index.mjs +5 -3
  61. package/api/init/init.doc.mjs +17 -12
  62. package/api/integration/add-contribution.d.mts +2 -1
  63. package/api/integration/add-contribution.mjs +7 -3
  64. package/api/integration/add-contribution.test.mjs +3 -3
  65. package/api/integration/add-helpers.d.mts +5 -2
  66. package/api/integration/add-helpers.mjs +36 -9
  67. package/api/integration/add-theme.mjs +266 -23
  68. package/api/integration/add-theme.test.mjs +247 -0
  69. package/api/integration/authoring-checks.mjs +12 -9
  70. package/api/integration/authoring-checks.type.d.mts +8 -0
  71. package/api/integration/authoring-checks.type.mjs +7 -3
  72. package/api/integration/integration-authoring.type.d.mts +4 -1
  73. package/api/integration/integration-authoring.type.mjs +6 -1
  74. package/api/integration/integrationAdd.doc.mjs +6 -0
  75. package/api/integration/integrationAddTheme.doc.mjs +10 -0
  76. package/api/integration/integrationComponentConflicts.doc.mjs +1 -1
  77. package/api/integration/integrationDocConflicts.doc.mjs +1 -1
  78. package/api/integration/integrationPackCheck.doc.mjs +3 -3
  79. package/api/integration/integrationTemplateConflicts.doc.mjs +1 -1
  80. package/api/integration/pack-check.lifecycle-output.test.mjs +107 -0
  81. package/api/integration/pack-check.mjs +92 -10
  82. package/api/integration/pack-check.test.mjs +140 -1
  83. package/api/integration/pack-check.type.mjs +1 -1
  84. package/api/integration/validate-integration.d.mts +4 -2
  85. package/api/integration/validate-integration.mjs +7 -2
  86. package/api/integration/validate-integration.test.mjs +55 -0
  87. package/api/integration/validate-integration.type.d.mts +5 -0
  88. package/api/integration/validate-integration.type.mjs +5 -1
  89. package/api/integration/validateIntegration.doc.mjs +1 -1
  90. package/api/json/assertResponse.doc.mjs +1 -1
  91. package/api/json/isError.doc.mjs +1 -1
  92. package/api/layout/expand/expand.mjs +12 -7
  93. package/api/layout/expand/expand.receipt.test.mjs +74 -0
  94. package/api/layout/layout.type.d.mts +1 -0
  95. package/api/layout/layout.type.mjs +1 -0
  96. package/api/layout/layoutExpand.doc.mjs +1 -1
  97. package/api/search/search.d.mts +51 -1
  98. package/api/search/search.doc.mjs +2 -2
  99. package/api/search/search.mjs +299 -17
  100. package/api/search/search.test.mjs +216 -18
  101. package/api/swizzle/copy/copy.mjs +66 -3
  102. package/api/swizzle/swizzle.doc.mjs +11 -5
  103. package/api/template/copy/copy.mjs +15 -9
  104. package/api/template/copy/copy.receipt.test.mjs +77 -0
  105. package/api/template/copy/copy.test.mjs +9 -0
  106. package/api/template/show/show.mjs +15 -4
  107. package/api/template/show/show.test.mjs +76 -0
  108. package/api/template/template-integration.test.mjs +14 -0
  109. package/api/template/template.d.mts +1 -1
  110. package/api/template/template.doc.mjs +8 -3
  111. package/api/template/template.mjs +1 -0
  112. package/api/template/template.type.d.mts +2 -0
  113. package/api/template/template.type.mjs +2 -0
  114. package/api/theme/add/add.mjs +17 -25
  115. package/api/theme/add/add.rollback.test.mjs +158 -0
  116. package/api/theme/add/add.staging.test.mjs +40 -23
  117. package/api/theme/build/build.d.mts +24 -0
  118. package/api/theme/build/build.family.test.mjs +7 -12
  119. package/api/theme/build/build.mjs +243 -26
  120. package/api/theme/build/build.project-core.test.mjs +165 -0
  121. package/api/theme/build/build.rollback.test.mjs +148 -0
  122. package/api/theme/generateTonalPalette.doc.mjs +1 -2
  123. package/api/theme/listThemes.doc.mjs +1 -1
  124. package/api/theme/themeAdd.doc.mjs +9 -10
  125. package/api/theme/themeBuild.doc.mjs +13 -13
  126. package/api/theme/themeList.doc.mjs +1 -1
  127. package/api/theme/themeListAvailable.doc.mjs +2 -1
  128. package/api/theme/themePaletteGenerate.doc.mjs +15 -8
  129. package/api/theme/themeTargets.doc.mjs +3 -2
  130. package/api/theme/themeTemplate.doc.mjs +2 -1
  131. package/api/upgrade/run/files-changed.test.mjs +111 -0
  132. package/api/upgrade/run/run.mjs +25 -6
  133. package/api/upgrade/run/run.test.mjs +45 -1
  134. package/api/upgrade/upgrade.doc.mjs +24 -22
  135. package/api/upgrade/upgrade.type.d.mts +1 -0
  136. package/api/upgrade/upgrade.type.mjs +3 -2
  137. package/assets/codemods/__tests__/runner.test.mjs +3 -1
  138. package/assets/codemods/file-count.test.mjs +163 -0
  139. package/assets/codemods/integration-runner.mjs +3 -3
  140. package/assets/codemods/runner.mjs +5 -4
  141. package/assets/docs/README.md +4 -2
  142. package/assets/docs/browser-support.doc.mjs +11 -11
  143. package/assets/docs/color.doc.mjs +8 -2
  144. package/assets/docs/elevation.doc.mjs +6 -4
  145. package/assets/docs/getting-started.doc.mjs +5 -16
  146. package/assets/docs/icons.doc.mjs +3 -21
  147. package/assets/docs/illustrations.doc.mjs +7 -15
  148. package/assets/docs/internationalization.doc.mjs +7 -5
  149. package/assets/docs/layout.doc.dense.mjs +130 -82
  150. package/assets/docs/layout.doc.mjs +133 -77
  151. package/assets/docs/migration.doc.mjs +19 -21
  152. package/assets/docs/motion.doc.mjs +16 -3
  153. package/assets/docs/principles.doc.dense.mjs +5 -5
  154. package/assets/docs/principles.doc.mjs +8 -0
  155. package/assets/docs/principles.doc.zh.mjs +6 -6
  156. package/assets/docs/shape.doc.mjs +8 -3
  157. package/assets/docs/spacing.doc.mjs +7 -2
  158. package/assets/docs/styling-libraries.doc.mjs +6 -2
  159. package/assets/docs/styling.doc.mjs +19 -23
  160. package/assets/docs/theme.doc.dense.mjs +58 -18
  161. package/assets/docs/theme.doc.mjs +57 -47
  162. package/assets/docs/theme.doc.zh.mjs +9 -8
  163. package/assets/docs/tokens.doc.dense.mjs +2 -2
  164. package/assets/docs/tokens.doc.mjs +389 -8
  165. package/assets/docs/tokens.doc.zh.mjs +2 -2
  166. package/assets/docs/tree/add-a-component.doc.mjs +75 -0
  167. package/assets/docs/tree/add-a-theme.doc.mjs +85 -0
  168. package/assets/docs/tree/add-a-topic.doc.mjs +144 -0
  169. package/assets/docs/tree/agent-guidance.doc.mjs +138 -0
  170. package/assets/docs/tree/block-template.doc.mjs +130 -0
  171. package/assets/docs/tree/build-the-template.doc.mjs +28 -0
  172. package/assets/docs/tree/building-blocks.doc.mjs +46 -0
  173. package/assets/docs/tree/check-your-docs.doc.mjs +137 -0
  174. package/assets/docs/tree/checks.doc.mjs +119 -0
  175. package/assets/docs/tree/codemods.doc.mjs +147 -0
  176. package/assets/docs/tree/component-family.doc.mjs +113 -0
  177. package/assets/docs/tree/component-imports.doc.mjs +69 -0
  178. package/assets/docs/tree/component-lookups.doc.mjs +149 -0
  179. package/assets/docs/tree/components.doc.mjs +23 -0
  180. package/assets/docs/tree/configuration.doc.mjs +23 -0
  181. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +182 -0
  182. package/assets/docs/tree/define-the-theme.doc.mjs +118 -0
  183. package/assets/docs/tree/describe-the-component.doc.mjs +57 -0
  184. package/assets/docs/tree/docs.doc.mjs +21 -0
  185. package/assets/docs/tree/document-the-template.doc.mjs +28 -0
  186. package/assets/docs/tree/document-the-theme.doc.mjs +68 -0
  187. package/assets/docs/tree/export-template-assets.doc.mjs +147 -0
  188. package/assets/docs/tree/extend-or-replace.doc.mjs +103 -0
  189. package/assets/docs/tree/fonts-and-assets.doc.mjs +106 -0
  190. package/assets/docs/tree/generate-a-palette.doc.mjs +66 -0
  191. package/assets/docs/tree/grade-template-with-agent.doc.mjs +105 -0
  192. package/assets/docs/tree/help.doc.mjs +16 -0
  193. package/assets/docs/tree/integrations.doc.mjs +25 -451
  194. package/assets/docs/tree/links.doc.mjs +98 -0
  195. package/assets/docs/tree/package-and-test.doc.mjs +32 -0
  196. package/assets/docs/tree/page-template.doc.mjs +71 -0
  197. package/assets/docs/tree/publishing.doc.mjs +111 -0
  198. package/assets/docs/tree/quick-start.doc.mjs +272 -0
  199. package/assets/docs/tree/replace-a-core-component.doc.mjs +104 -0
  200. package/assets/docs/tree/replace-a-core-template.doc.mjs +172 -0
  201. package/assets/docs/tree/sections-and-placement.doc.mjs +108 -0
  202. package/assets/docs/tree/see-it-in-an-app.doc.mjs +59 -0
  203. package/assets/docs/tree/ship.doc.mjs +16 -0
  204. package/assets/docs/tree/short-and-findable.doc.mjs +108 -0
  205. package/assets/docs/tree/single-component.doc.mjs +165 -0
  206. package/assets/docs/tree/start-a-template.doc.mjs +143 -0
  207. package/assets/docs/tree/subcomponent.doc.mjs +115 -0
  208. package/assets/docs/tree/template-assets.doc.mjs +64 -0
  209. package/assets/docs/tree/template-doc-overview.doc.mjs +121 -0
  210. package/assets/docs/tree/template-fonts.doc.mjs +102 -0
  211. package/assets/docs/tree/template-grading-rubric.doc.mjs +452 -0
  212. package/assets/docs/tree/template-icons.doc.mjs +97 -0
  213. package/assets/docs/tree/template-images-media.doc.mjs +127 -0
  214. package/assets/docs/tree/template-styles.doc.mjs +93 -0
  215. package/assets/docs/tree/templates.doc.mjs +34 -0
  216. package/assets/docs/tree/test-in-an-app.doc.mjs +115 -0
  217. package/assets/docs/tree/test-template-in-app.doc.mjs +128 -0
  218. package/assets/docs/tree/themes.doc.mjs +39 -0
  219. package/assets/docs/tree/troubleshooting.doc.mjs +153 -0
  220. package/assets/docs/tree/upgrading.doc.mjs +103 -0
  221. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +51 -0
  222. package/assets/docs/tree/verify-packed-template.doc.mjs +77 -0
  223. package/assets/docs/tree/versioning.doc.mjs +162 -0
  224. package/assets/docs/tree/write-good-templates.doc.mjs +64 -0
  225. package/assets/docs/tree/write-the-template-file.doc.mjs +154 -0
  226. package/assets/docs/typography.doc.mjs +24 -4
  227. package/assets/docs/working-with-ai.doc.mjs +30 -22
  228. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  229. package/assets/templates/pages/ai-chat/template.doc.mjs +16 -1
  230. package/assets/templates/pages/ai-chat-landing/template.doc.mjs +9 -1
  231. package/assets/templates/pages/blank/template.doc.mjs +3 -1
  232. package/assets/templates/pages/canvas-editor/template.doc.mjs +9 -1
  233. package/assets/templates/pages/centered-hero/template.doc.mjs +3 -1
  234. package/assets/templates/pages/checkout-wizard/template.doc.mjs +1 -0
  235. package/assets/templates/pages/classic-gallery/template.doc.mjs +3 -1
  236. package/assets/templates/pages/contact-form/template.doc.mjs +16 -1
  237. package/assets/templates/pages/dashboard/template.doc.mjs +15 -1
  238. package/assets/templates/pages/dashboard-alert-rail/template.doc.mjs +23 -1
  239. package/assets/templates/pages/dashboard-cohort-funnel/template.doc.mjs +10 -1
  240. package/assets/templates/pages/dashboard-comparison/template.doc.mjs +9 -1
  241. package/assets/templates/pages/dashboard-composition/template.doc.mjs +10 -1
  242. package/assets/templates/pages/dashboard-progress/template.doc.mjs +17 -1
  243. package/assets/templates/pages/dashboard-scorecard/template.doc.mjs +2 -1
  244. package/assets/templates/pages/detail-page/template.doc.mjs +8 -0
  245. package/assets/templates/pages/documentation/template.doc.mjs +10 -1
  246. package/assets/templates/pages/documentation-design/template.doc.mjs +10 -1
  247. package/assets/templates/pages/documentation-technical/template.doc.mjs +10 -1
  248. package/assets/templates/pages/editor/template.doc.mjs +9 -1
  249. package/assets/templates/pages/file-explorer/template.doc.mjs +3 -1
  250. package/assets/templates/pages/form-two-column/template.doc.mjs +17 -1
  251. package/assets/templates/pages/form-wizard/template.doc.mjs +14 -1
  252. package/assets/templates/pages/form-wizard-dialog/template.doc.mjs +1 -0
  253. package/assets/templates/pages/gallery-hero/template.doc.mjs +10 -1
  254. package/assets/templates/pages/ide/template.doc.mjs +9 -1
  255. package/assets/templates/pages/incident-console/template.doc.mjs +10 -1
  256. package/assets/templates/pages/kanban-board/template.doc.mjs +11 -1
  257. package/assets/templates/pages/library/template.doc.mjs +15 -1
  258. package/assets/templates/pages/login/template.doc.mjs +10 -1
  259. package/assets/templates/pages/login-card/template.doc.mjs +11 -1
  260. package/assets/templates/pages/login-split/template.doc.mjs +10 -1
  261. package/assets/templates/pages/login-sso/template.doc.mjs +10 -1
  262. package/assets/templates/pages/messaging-shell/template.doc.mjs +11 -1
  263. package/assets/templates/pages/mixed-gallery/template.doc.mjs +10 -1
  264. package/assets/templates/pages/payment-form/template.doc.mjs +3 -1
  265. package/assets/templates/pages/product-detail/template.doc.mjs +9 -1
  266. package/assets/templates/pages/product-gallery/template.doc.mjs +10 -1
  267. package/assets/templates/pages/settings/template.doc.mjs +3 -1
  268. package/assets/templates/pages/settings-dialog/template.doc.mjs +9 -1
  269. package/assets/templates/pages/settings-sidebar/template.doc.mjs +9 -1
  270. package/assets/templates/pages/shell-nav/template.doc.mjs +10 -1
  271. package/assets/templates/pages/shell-side-nav/template.doc.mjs +14 -1
  272. package/assets/templates/pages/shell-top-nav/template.doc.mjs +11 -1
  273. package/assets/templates/pages/side-gallery/template.doc.mjs +3 -1
  274. package/assets/templates/pages/table/template.doc.mjs +11 -1
  275. package/assets/templates/pages/table-filter/template.doc.mjs +21 -1
  276. package/assets/templates/pages/table-grouped/template.doc.mjs +15 -1
  277. package/assets/templates/pages/table-inbox/template.doc.mjs +18 -6
  278. package/assets/templates/pages/table-page/template.doc.mjs +20 -1
  279. package/assets/templates/pages/table-tree/template.doc.mjs +14 -1
  280. package/assets/templates/pages/theme-showcase/template.doc.mjs +10 -1
  281. package/assets/templates/pages/work-item-detail/template.doc.mjs +10 -0
  282. package/assets/templates/themes/butter/icons.tsx +2 -0
  283. package/assets/templates/themes/chocolate/icons.tsx +2 -0
  284. package/assets/templates/themes/gothic/icons.tsx +2 -0
  285. package/assets/templates/themes/matcha/icons.tsx +2 -0
  286. package/assets/templates/themes/neutral/icons.tsx +2 -0
  287. package/assets/templates/themes/stone/icons.tsx +2 -0
  288. package/assets/templates/themes/y2k/icons.tsx +2 -0
  289. package/authoring/config/config.doc.mjs +9 -1
  290. package/authoring/config/parse.d.mts +2 -0
  291. package/authoring/config/parse.mjs +19 -0
  292. package/authoring/config/parse.test.mjs +8 -0
  293. package/authoring/config/type.ts +11 -0
  294. package/authoring/discover/discover.doc.d.mts +13 -0
  295. package/authoring/discover/discover.doc.mjs +138 -0
  296. package/authoring/discover/parse.d.mts +24 -0
  297. package/authoring/discover/parse.mjs +128 -0
  298. package/authoring/discover/parse.test.mjs +124 -0
  299. package/authoring/discover/type.ts +87 -0
  300. package/authoring/doctypes/_schema.d.mts +3 -2
  301. package/authoring/doctypes/_schema.mjs +6 -0
  302. package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
  303. package/authoring/doctypes/base/type.ts +4 -2
  304. package/authoring/doctypes/component/component.doc.mjs +6 -0
  305. package/authoring/doctypes/component/type.ts +8 -0
  306. package/authoring/doctypes/reference/reference.doc.mjs +7 -0
  307. package/authoring/doctypes/reference/type.ts +5 -0
  308. package/authoring/doctypes/schema/schema.doc.mjs +2 -2
  309. package/authoring/doctypes/template/parse.d.mts +2 -0
  310. package/authoring/doctypes/template/parse.mjs +1 -0
  311. package/authoring/doctypes/template/parse.test.mjs +21 -0
  312. package/authoring/doctypes/template/template.doc.mjs +7 -1
  313. package/authoring/doctypes/template/type.ts +12 -2
  314. package/authoring/index.d.mts +1 -0
  315. package/authoring/index.d.ts +10 -0
  316. package/authoring/index.mjs +1 -0
  317. package/authoring/integration/integration.doc.mjs +12 -10
  318. package/clients/cli/commands/component/index.mjs +152 -55
  319. package/clients/cli/commands/component-batch.test.mjs +341 -0
  320. package/clients/cli/commands/component-ownership.test.mjs +89 -0
  321. package/clients/cli/commands/component.doc.mjs +27 -9
  322. package/clients/cli/commands/discover.doc.mjs +53 -9
  323. package/clients/cli/commands/discover.mjs +393 -118
  324. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  325. package/clients/cli/commands/docs.doc.mjs +1 -1
  326. package/clients/cli/commands/docs.mjs +60 -17
  327. package/clients/cli/commands/docs.test.mjs +113 -24
  328. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -2
  329. package/clients/cli/commands/doctor-integration.test.mjs +53 -0
  330. package/clients/cli/commands/doctor.doc.mjs +3 -1
  331. package/clients/cli/commands/doctor.mjs +53 -9
  332. package/clients/cli/commands/gap-report.doc.mjs +10 -9
  333. package/clients/cli/commands/init.doc.mjs +9 -6
  334. package/clients/cli/commands/integration-add.doc.mjs +17 -7
  335. package/clients/cli/commands/integration-authoring.test.mjs +70 -9
  336. package/clients/cli/commands/integration-pack.doc.mjs +5 -9
  337. package/clients/cli/commands/integration-real-world.test.mjs +1 -1
  338. package/clients/cli/commands/integration-verify.doc.mjs +22 -0
  339. package/clients/cli/commands/integration.doc.mjs +4 -4
  340. package/clients/cli/commands/integration.mjs +76 -43
  341. package/clients/cli/commands/layout-expand.doc.mjs +3 -1
  342. package/clients/cli/commands/layout.expand-receipt.test.mjs +94 -0
  343. package/clients/cli/commands/layout.mjs +16 -0
  344. package/clients/cli/commands/manifest.doc.mjs +1 -1
  345. package/clients/cli/commands/search.doc.mjs +10 -3
  346. package/clients/cli/commands/search.mjs +21 -2
  347. package/clients/cli/commands/search.test.mjs +21 -4
  348. package/clients/cli/commands/swizzle.doc.mjs +1 -1
  349. package/clients/cli/commands/template.copy-receipt.test.mjs +60 -0
  350. package/clients/cli/commands/template.doc.mjs +1 -1
  351. package/clients/cli/commands/template.mjs +19 -5
  352. package/clients/cli/commands/template.show-media.test.mjs +62 -0
  353. package/clients/cli/commands/text-json-parity.test.mjs +7 -1
  354. package/clients/cli/commands/theme-add.doc.mjs +1 -1
  355. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -2
  356. package/clients/cli/commands/theme-palette.doc.mjs +1 -2
  357. package/clients/cli/commands/theme-targets.doc.mjs +2 -2
  358. package/clients/cli/commands/theme.doc.mjs +2 -1
  359. package/clients/cli/commands/upgrade.ascii-output.test.mjs +14 -0
  360. package/clients/cli/commands/upgrade.doc.mjs +62 -3
  361. package/clients/cli/commands/write-failure.test.mjs +175 -0
  362. package/clients/cli/index.mjs +28 -6
  363. package/clients/cli/lib/define-command.mjs +28 -4
  364. package/clients/cli/lib/define-command.test.mjs +54 -0
  365. package/clients/cli/lib/exit-codes.test.mjs +17 -1
  366. package/clients/cli/lib/json-shim.mjs +24 -14
  367. package/clients/cli/lib/manifest.mjs +48 -156
  368. package/clients/cli/lib/manifest.test.mjs +103 -9
  369. package/clients/cli/lib/parse-error-format.test.mjs +81 -0
  370. package/foundation/agent-docs/agent-docs.mjs +1 -1
  371. package/foundation/agent-docs/agent-docs.test.mjs +3 -2
  372. package/foundation/discovery/authoring-self-docs.mjs +1 -0
  373. package/foundation/discovery/authoring-self-docs.test.mjs +6 -2
  374. package/foundation/discovery/cli-self-docs.mjs +16 -2
  375. package/foundation/discovery/cli-self-docs.test.mjs +20 -0
  376. package/foundation/discovery/docs-discovery.mjs +5 -1
  377. package/foundation/discovery/docs-discovery.test.mjs +21 -0
  378. package/foundation/discovery/docs-section-key.d.mts +1 -1
  379. package/foundation/discovery/docs-section-key.mjs +1 -1
  380. package/foundation/discovery/template-adapter.d.mts +14 -0
  381. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +37 -1
  382. package/foundation/discovery/template-adapter.mjs +21 -1
  383. package/foundation/doc-compiler/doc-loads.test.mjs +5 -4
  384. package/foundation/doc-compiler/inputs.test.mjs +0 -1
  385. package/foundation/doc-compiler/tree.d.mts +4 -0
  386. package/foundation/doc-compiler/tree.mjs +6 -1
  387. package/foundation/doc-compiler/tree.test.mjs +65 -14
  388. package/foundation/integrations/cli-requirement.d.mts +75 -11
  389. package/foundation/integrations/cli-requirement.mjs +120 -23
  390. package/foundation/integrations/cli-requirement.test.mjs +141 -9
  391. package/foundation/integrations/contribution-inventory.mjs +1 -1
  392. package/foundation/integrations/integrations.d.mts +14 -1
  393. package/foundation/integrations/integrations.mjs +41 -1
  394. package/foundation/integrations/integrations.test.mjs +31 -0
  395. package/foundation/response/batch.type.d.mts +33 -0
  396. package/foundation/response/batch.type.mjs +34 -0
  397. package/foundation/response/error-codes.doc.mjs +6 -8
  398. package/foundation/response/error-codes.test.mjs +30 -5
  399. package/foundation/response/response-types.doc.d.mts +5 -4
  400. package/foundation/response/response-types.doc.mjs +49 -19
  401. package/foundation/response/response-types.doc.test.mjs +23 -0
  402. package/foundation/response/response.doc.mjs +11 -10
  403. package/package.json +9 -9
  404. package/assets/docs/tree/integrations.test.mjs +0 -62
  405. package/assets/docs/tree/writing-docs.doc.mjs +0 -286
@@ -1,13 +1,16 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
3
  /**
4
- * @file The CLI an integration's namespace docs need (spec:AST-046 FR11).
4
+ * @file The CLI release an integration's newer contributions need
5
+ * (spec:AST-046 FR11).
5
6
  *
6
7
  * @input A package.json object.
7
8
  * @output Whether its `peerDependencies` range for `@astryxdesign/cli` admits
8
- * only CLIs that read namespace docs, and the package.json that declares it.
9
- * @position foundation/integrations; read by `integration add doc --parent`,
10
- * which declares the peer, and `integration pack --check`, which requires it.
9
+ * only CLIs that read what the package ships, and the package.json that
10
+ * declares that range.
11
+ * @position foundation/integrations; read by `integration add doc --parent`
12
+ * and `integration add theme`, which declare the peer, and
13
+ * `integration verify`, which requires it.
11
14
  */
12
15
 
13
16
  import {semverCompare} from '../env/semver.mjs';
@@ -15,13 +18,34 @@ import {semverCompare} from '../env/semver.mjs';
15
18
  export const CLI_PACKAGE = '@astryxdesign/cli';
16
19
 
17
20
  /**
18
- * The first CLI release that reads an integration's docs tree (namespace docs
19
- * and placed guides) and its templates' `replaces`. A release before it can
20
- * hide every doc topic a package with a namespace doc or a placed guide
21
- * ships, with no warning, and it rejects `replaces` and withholds the
22
- * package's templates and doc topics.
21
+ * The first stable CLI release that reads an integration's docs tree:
22
+ * namespace docs and placed guides. Published 0.6.3 rejects a namespace doc
23
+ * and hides every doc topic the package ships, with no warning; published
24
+ * 0.6.4 lists the namespace and reads its guides.
23
25
  */
24
- export const DOCS_TREE_CLI = '0.7.0';
26
+ export const NAMESPACE_DOCS_CLI = '0.6.4';
27
+
28
+ /**
29
+ * The first CLI release that reads a template's `replaces` and `keywords`. A
30
+ * release before it rejects either field, drops that template, and hides the
31
+ * package's doc topics.
32
+ */
33
+ export const REPLACES_CLI = '0.7.0';
34
+
35
+ /**
36
+ * The first stable CLI release that reads typed theme descriptors, the theme
37
+ * folder `integration add theme` writes. Published 0.6.3 rejects a themes root
38
+ * with no `manifest.json` catalog and withholds the package's themes and doc
39
+ * topics; published 0.6.4 lists the themes.
40
+ */
41
+ export const THEMES_CLI = '0.6.4';
42
+
43
+ /**
44
+ * The first stable CLI release that reads a doc section's `id`. Published
45
+ * 0.6.3 rejects the field and hides every doc topic the package ships;
46
+ * published 0.6.4 reads the section by its id.
47
+ */
48
+ export const SECTION_IDS_CLI = '0.6.4';
25
49
 
26
50
  const VERSION_RE = /^v?(\d+|[xX*])(?:\.(\d+|[xX*]))?(?:\.(\d+|[xX*]))?(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
27
51
 
@@ -86,17 +110,25 @@ export function lowestAdmitted(range) {
86
110
  * @param {any} pkg package.json
87
111
  * @param {string} feature what the package does, e.g. "ships a namespace doc"
88
112
  * @param {string} loss what an older CLI does with it
113
+ * @param {string} floor the first stable CLI release that reads it
89
114
  * @returns {string | null}
90
115
  */
91
- function cliRangeProblem(pkg, feature, loss) {
116
+ export function cliRangeProblem(pkg, feature, loss, floor) {
117
+ // A floor that is missing or not a version means a caller passed the
118
+ // arguments in another order, as after a merge with a caller written for
119
+ // another signature. Fail loudly rather than compare a range against
120
+ // feature text, or against nothing.
121
+ if (typeof floor !== 'string' || lowerVersion(floor) == null) {
122
+ throw new TypeError(`cliRangeProblem: floor "${floor}" is not a version`);
123
+ }
92
124
  const range = pkg?.peerDependencies?.[CLI_PACKAGE];
93
- const fix = `"${CLI_PACKAGE}": ">=${DOCS_TREE_CLI}" in peerDependencies (optional in peerDependenciesMeta, if the CLI is not required)`;
125
+ const fix = `"${CLI_PACKAGE}": ">=${floor}" in peerDependencies (optional in peerDependenciesMeta, if the CLI is not required)`;
94
126
  if (typeof range !== 'string') {
95
- return `The package ${feature} but declares no ${CLI_PACKAGE} peer. A CLI older than ${DOCS_TREE_CLI} ${loss}. Declare ${fix}.`;
127
+ return `The package ${feature} but declares no ${CLI_PACKAGE} peer. A stable CLI before ${floor} ${loss}. Declare ${fix}.`;
96
128
  }
97
129
  const lowest = lowestAdmitted(range);
98
- if (lowest == null || semverCompare(lowest, DOCS_TREE_CLI) < 0) {
99
- return `The package ${feature}, but its ${CLI_PACKAGE} peer range "${range}" admits a CLI older than ${DOCS_TREE_CLI}, which ${loss}. Declare ${fix}.`;
130
+ if (lowest == null || semverCompare(lowest, floor) < 0) {
131
+ return `The package ${feature}, but its ${CLI_PACKAGE} peer range "${range}" admits a stable CLI before ${floor}, which ${loss}. Declare ${fix}.`;
100
132
  }
101
133
  return null;
102
134
  }
@@ -106,7 +138,7 @@ function cliRangeProblem(pkg, feature, loss) {
106
138
  * docs on an older CLI, or null when its declared CLI range admits only CLIs
107
139
  * that read the docs tree. Published 0.6.3 hides every topic of a package
108
140
  * with a namespace doc; builds of main before the docs tree also do so for a
109
- * placed guide.
141
+ * placed guide. Published 0.6.4 reads both.
110
142
  * @param {any} pkg package.json
111
143
  * @returns {string | null}
112
144
  */
@@ -115,12 +147,13 @@ export function docsTreeCliProblem(pkg) {
115
147
  pkg,
116
148
  'ships a namespace doc or a placed guide',
117
149
  'does not read the docs tree, and can hide every doc topic the package ships',
150
+ NAMESPACE_DOCS_CLI,
118
151
  );
119
152
  }
120
153
 
121
154
  /**
122
- * Why a package with a template that sets `replaces` would lose its templates
123
- * and doc topics on an older CLI (spec:AST-035), or null when its declared CLI
155
+ * Why a package with a template that sets `replaces` would lose templates and
156
+ * doc topics on an older CLI (spec:AST-035), or null when its declared CLI
124
157
  * range admits only CLIs that read the field.
125
158
  * @param {any} pkg package.json
126
159
  * @returns {string | null}
@@ -129,26 +162,90 @@ export function replacesCliProblem(pkg) {
129
162
  return cliRangeProblem(
130
163
  pkg,
131
164
  'has a template that sets `replaces`',
132
- "rejects the field, and withholds the package's templates and doc topics",
165
+ "rejects the field, drops that template, and hides the package's doc topics",
166
+ REPLACES_CLI,
133
167
  );
134
168
  }
135
169
 
136
170
  /**
137
- * The package.json with a CLI peer that reads namespace docs: optional, unless
138
- * the package already says otherwise.
171
+ * Why a package with a doc section that sets `id` would lose its doc topics on
172
+ * an older CLI, or null when its declared CLI range admits only CLIs that read
173
+ * the field. Published 0.6.3 rejects a section `id` and hides every doc topic
174
+ * the package ships; published 0.6.4 reads it.
139
175
  * @param {any} pkg package.json
176
+ * @returns {string | null}
177
+ */
178
+ export function sectionIdsCliProblem(pkg) {
179
+ return cliRangeProblem(
180
+ pkg,
181
+ 'has a doc section that sets `id`',
182
+ 'rejects the field, and can hide every doc topic the package ships',
183
+ SECTION_IDS_CLI,
184
+ );
185
+ }
186
+
187
+ /**
188
+ * Why a package that ships a theme would lose its themes and doc topics on an
189
+ * older CLI, or null when its declared CLI range admits only CLIs that read
190
+ * typed theme descriptors. Published 0.6.3 rejects a themes root with no
191
+ * `manifest.json` catalog, which `integration add theme` no longer writes;
192
+ * published 0.6.4 reads the descriptors.
193
+ * @param {any} pkg package.json
194
+ * @returns {string | null}
195
+ */
196
+ export function themesCliProblem(pkg) {
197
+ return cliRangeProblem(
198
+ pkg,
199
+ 'ships a theme',
200
+ "cannot read typed theme descriptors, and can drop the package's themes and hide its doc topics",
201
+ THEMES_CLI,
202
+ );
203
+ }
204
+
205
+ /**
206
+ * Why a package with a template that sets `keywords` would lose that template
207
+ * and its doc topics on an older CLI, or null when its declared CLI range
208
+ * admits only CLIs that read the field. Published 0.6.3 rejects the field,
209
+ * drops that template, and hides the package's doc topics.
210
+ * @param {any} pkg package.json
211
+ * @returns {string | null}
212
+ */
213
+ export function keywordsCliProblem(pkg) {
214
+ return cliRangeProblem(
215
+ pkg,
216
+ 'has a template that sets `keywords`',
217
+ "rejects the field, drops that template, and hides the package's doc topics",
218
+ REPLACES_CLI,
219
+ );
220
+ }
221
+
222
+ /**
223
+ * The package.json with a CLI peer of `>=floor`: optional, unless the package
224
+ * already says otherwise. Call it only when the package's range admits a CLI
225
+ * before `floor`, so a stricter range is never lowered.
226
+ * @param {any} pkg package.json
227
+ * @param {string} floor the first stable CLI release the package needs
140
228
  * @returns {any}
141
229
  */
142
- export function withDocsTreeCli(pkg) {
230
+ export function withCliPeer(pkg, floor) {
143
231
  const meta = pkg.peerDependenciesMeta ?? {};
144
232
  return {
145
233
  ...pkg,
146
234
  peerDependencies: {
147
235
  ...(pkg.peerDependencies ?? {}),
148
- [CLI_PACKAGE]: `>=${DOCS_TREE_CLI}`,
236
+ [CLI_PACKAGE]: `>=${floor}`,
149
237
  },
150
238
  peerDependenciesMeta: meta[CLI_PACKAGE]
151
239
  ? meta
152
240
  : {...meta, [CLI_PACKAGE]: {optional: true}},
153
241
  };
154
242
  }
243
+
244
+ /**
245
+ * The package.json with a CLI peer that reads namespace docs.
246
+ * @param {any} pkg package.json
247
+ * @returns {any}
248
+ */
249
+ export function withDocsTreeCli(pkg) {
250
+ return withCliPeer(pkg, NAMESPACE_DOCS_CLI);
251
+ }
@@ -1,11 +1,22 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
+ import fs from 'node:fs';
3
4
  import {describe, expect, it} from 'vitest';
5
+ import {semverCompare} from '../env/semver.mjs';
6
+ import * as requirement from './cli-requirement.mjs';
4
7
  import {
5
- DOCS_TREE_CLI,
8
+ NAMESPACE_DOCS_CLI,
9
+ REPLACES_CLI,
10
+ SECTION_IDS_CLI,
11
+ cliRangeProblem,
12
+ THEMES_CLI,
6
13
  lowestAdmitted,
7
14
  docsTreeCliProblem,
15
+ keywordsCliProblem,
8
16
  replacesCliProblem,
17
+ sectionIdsCliProblem,
18
+ themesCliProblem,
19
+ withCliPeer,
9
20
  withDocsTreeCli,
10
21
  } from './cli-requirement.mjs';
11
22
 
@@ -32,6 +43,11 @@ describe('docsTreeCliProblem', () => {
32
43
  expect(docsTreeCliProblem({name: '@acme/kit'})).toContain(
33
44
  'declares no @astryxdesign/cli peer',
34
45
  );
46
+ // Stable releases: a canary built from main before its release reports
47
+ // the older version and reads every feature.
48
+ expect(docsTreeCliProblem({name: '@acme/kit'})).toContain(
49
+ 'A stable CLI before 0.6.4 does not read the docs tree',
50
+ );
35
51
  });
36
52
 
37
53
  it.each(['^0.6.0', '^0.6.0 || >=0.7.0', '*', '>=0.6.3'])(
@@ -39,20 +55,23 @@ describe('docsTreeCliProblem', () => {
39
55
  range => {
40
56
  expect(
41
57
  docsTreeCliProblem({peerDependencies: {'@astryxdesign/cli': range}}),
42
- ).toContain('admits a CLI older than');
58
+ ).toContain('admits a stable CLI before');
43
59
  },
44
60
  );
45
61
 
46
- it.each(['>=0.7.0', '^0.7.2', '>=0.7.0 <2'])('accepts %s', range => {
47
- expect(
48
- docsTreeCliProblem({peerDependencies: {'@astryxdesign/cli': range}}),
49
- ).toBeNull();
50
- });
62
+ it.each(['>=0.6.4', '^0.6.4', '>=0.7.0', '^0.7.2', '>=0.7.0 <2'])(
63
+ 'accepts %s',
64
+ range => {
65
+ expect(
66
+ docsTreeCliProblem({peerDependencies: {'@astryxdesign/cli': range}}),
67
+ ).toBeNull();
68
+ },
69
+ );
51
70
 
52
71
  it('declares the peer as optional, and keeps what the package says of it', () => {
53
72
  const declared = withDocsTreeCli({name: '@acme/kit'});
54
73
  expect(declared.peerDependencies).toEqual({
55
- '@astryxdesign/cli': `>=${DOCS_TREE_CLI}`,
74
+ '@astryxdesign/cli': '>=0.6.4',
56
75
  });
57
76
  expect(declared.peerDependenciesMeta).toEqual({
58
77
  '@astryxdesign/cli': {optional: true},
@@ -76,9 +95,122 @@ describe('replacesCliProblem', () => {
76
95
  );
77
96
  expect(
78
97
  replacesCliProblem({peerDependencies: {'@astryxdesign/cli': '^0.6.0'}}),
79
- ).toContain('admits a CLI older than');
98
+ ).toContain('admits a stable CLI before');
80
99
  expect(
81
100
  replacesCliProblem({peerDependencies: {'@astryxdesign/cli': '>=0.7.0'}}),
82
101
  ).toBeNull();
102
+ // Unlike the docs tree, `replaces` still needs 0.7.0.
103
+ expect(
104
+ replacesCliProblem({peerDependencies: {'@astryxdesign/cli': '>=0.6.4'}}),
105
+ ).toContain('admits a stable CLI before 0.7.0');
106
+ });
107
+ });
108
+
109
+ describe('themesCliProblem and sectionIdsCliProblem', () => {
110
+ // Published 0.6.4 reads typed theme descriptors and section ids. Published
111
+ // 0.6.3 rejects both and hides the package's doc topics.
112
+ it.each([
113
+ ['a theme', themesCliProblem, 'ships a theme'],
114
+ ['a section id', sectionIdsCliProblem, 'sets `id`'],
115
+ ])('asks for a CLI from 0.6.4 for %s', (_name, problem, feature) => {
116
+ expect(problem({name: '@acme/kit'})).toContain(feature);
117
+ expect(problem({name: '@acme/kit'})).toContain('A stable CLI before 0.6.4');
118
+ for (const range of ['>=0.6.4', '^0.6.4', '>=0.6.5', '>=0.7.0']) {
119
+ expect(
120
+ problem({peerDependencies: {'@astryxdesign/cli': range}}),
121
+ ).toBeNull();
122
+ }
123
+ for (const range of ['^0.6.0', '>=0.6.3', '*']) {
124
+ expect(
125
+ problem({peerDependencies: {'@astryxdesign/cli': range}}),
126
+ ).toContain('admits a stable CLI before 0.6.4');
127
+ }
128
+ });
129
+
130
+ it('keeps 0.7.0 for replaces and keywords', () => {
131
+ const pkg = {peerDependencies: {'@astryxdesign/cli': '>=0.6.4'}};
132
+ expect(docsTreeCliProblem(pkg)).toBeNull();
133
+ expect(replacesCliProblem(pkg)).toContain(
134
+ 'admits a stable CLI before 0.7.0',
135
+ );
136
+ expect(keywordsCliProblem(pkg)).toContain(
137
+ 'admits a stable CLI before 0.7.0',
138
+ );
139
+ expect(
140
+ keywordsCliProblem({peerDependencies: {'@astryxdesign/cli': '>=0.7.0'}}),
141
+ ).toBeNull();
142
+ });
143
+
144
+ it('names a released CLI for a feature that already shipped', () => {
145
+ const {version} = JSON.parse(
146
+ fs.readFileSync(new URL('../../package.json', import.meta.url), 'utf-8'),
147
+ );
148
+ for (const floor of [NAMESPACE_DOCS_CLI, THEMES_CLI, SECTION_IDS_CLI]) {
149
+ expect(semverCompare(floor, version.split('-')[0])).toBeLessThanOrEqual(
150
+ 0,
151
+ );
152
+ }
153
+ });
154
+
155
+ it('declares the floor a theme needs as an optional peer', () => {
156
+ const declared = withCliPeer({name: '@acme/kit'}, THEMES_CLI);
157
+ expect(declared.peerDependencies).toEqual({
158
+ '@astryxdesign/cli': '>=0.6.4',
159
+ });
160
+ expect(declared.peerDependenciesMeta).toEqual({
161
+ '@astryxdesign/cli': {optional: true},
162
+ });
163
+ expect(themesCliProblem(declared)).toBeNull();
164
+ });
165
+ });
166
+
167
+ describe('cliRangeProblem', () => {
168
+ it('fails loudly when a caller names no floor', () => {
169
+ expect(() =>
170
+ // @ts-expect-error: the floor is required
171
+ cliRangeProblem({name: '@acme/kit'}, 'ships x', 'drops x'),
172
+ ).toThrow(TypeError);
173
+ });
174
+
175
+ it('fails loudly when the floor is not a version', () => {
176
+ expect(() =>
177
+ cliRangeProblem({name: '@acme/kit'}, '0.6.4', 'ships x', 'drops x'),
178
+ ).toThrow(TypeError);
179
+ });
180
+ });
181
+
182
+ describe('every feature check names its CLI floor', () => {
183
+ // The first stable CLI release that reads each feature. A new check, or a
184
+ // check whose floor changes, fails here until this table says so on
185
+ // purpose, so a floor never moves as a side effect of another change.
186
+ const FLOORS = {
187
+ docsTreeCliProblem: '0.6.4',
188
+ replacesCliProblem: REPLACES_CLI,
189
+ keywordsCliProblem: REPLACES_CLI,
190
+ sectionIdsCliProblem: '0.6.4',
191
+ themesCliProblem: '0.6.4',
192
+ };
193
+
194
+ it('asks each feature for the CLI release this table names', () => {
195
+ const named = Object.fromEntries(
196
+ Object.entries(requirement)
197
+ .filter(
198
+ ([name, value]) =>
199
+ typeof value === 'function' &&
200
+ /CliProblem$/.test(name) &&
201
+ name !== 'cliRangeProblem',
202
+ )
203
+ .map(([name, check]) => [
204
+ name,
205
+ /A stable CLI before (\d+\.\d+\.\d+)/.exec(
206
+ check({name: '@acme/kit'}) ?? '',
207
+ )?.[1] ?? null,
208
+ ]),
209
+ );
210
+ expect(named).toEqual({
211
+ ...FLOORS,
212
+ replacesCliProblem: '0.7.0',
213
+ keywordsCliProblem: '0.7.0',
214
+ });
83
215
  });
84
216
  });
@@ -1,7 +1,7 @@
1
1
  // Copyright (c) Meta Platforms, Inc. and affiliates.
2
2
 
3
3
  /**
4
- * @file Contribution inventory for integration pack-check.
4
+ * @file Contribution inventory for `astryx integration verify`.
5
5
  *
6
6
  * Enumerates the files and contribution identities an integration package
7
7
  * declares, for cross-referencing against the npm tarball. The file inventory
@@ -45,7 +45,7 @@ export function findManifestPaths(dir: string): string[];
45
45
  * @param {string} file absolute manifest path
46
46
  * @param {string} [label] used in error messages
47
47
  * @param {{fresh?: boolean}} [options]
48
- * @returns {Promise<{manifest: import('../../authoring/integration/type').AstryxIntegration, unknownKeys: string[], debug?: import('../../authoring/debug/type').DebugEventHandler, gapReport?: import('../../authoring/gap-report/type').GapReportHandler, gapReportError?: string, agentDocsError?: string}>}
48
+ * @returns {Promise<{manifest: import('../../authoring/integration/type').AstryxIntegration, unknownKeys: string[], debug?: import('../../authoring/debug/type').DebugEventHandler, gapReport?: import('../../authoring/gap-report/type').GapReportHandler, gapReportError?: string, discover?: import('../../authoring/discover/type').DiscoverSource, discoverError?: string, agentDocsError?: string}>}
49
49
  */
50
50
  export function loadManifest(file: string, label?: string, { fresh }?: {
51
51
  fresh?: boolean;
@@ -55,6 +55,8 @@ export function loadManifest(file: string, label?: string, { fresh }?: {
55
55
  debug?: import("../../authoring/debug/type").DebugEventHandler;
56
56
  gapReport?: import("../../authoring/gap-report/type").GapReportHandler;
57
57
  gapReportError?: string;
58
+ discover?: import("../../authoring/discover/type").DiscoverSource;
59
+ discoverError?: string;
58
60
  agentDocsError?: string;
59
61
  }>;
60
62
  /**
@@ -154,6 +156,9 @@ export function loadIntegrations(specs?: string[], { cwd, fresh, resolveProvider
154
156
  * validated package-owned handler from the `gapReport` NAMED export.
155
157
  * @property {string} [__gapReportError] isolated named-handler validation error.
156
158
  * Named exports are not manifest keys — see {@link loadManifest}.
159
+ * @property {import('../../authoring/discover/type').DiscoverSource} [__discover]
160
+ * validated catalog source from the `discover` NAMED export.
161
+ * @property {string} [__discoverError] isolated discover-source validation error.
157
162
  */
158
163
  /** Conventional manifest basenames, in load-precedence order. */
159
164
  export const MANIFEST_BASENAMES: string[];
@@ -245,4 +250,12 @@ export type LoadedIntegration = {
245
250
  * Named exports are not manifest keys — see {@link loadManifest}.
246
251
  */
247
252
  __gapReportError?: string | undefined;
253
+ /**
254
+ * validated catalog source from the `discover` NAMED export.
255
+ */
256
+ __discover?: import("../../authoring/discover/type").DiscoverSource | undefined;
257
+ /**
258
+ * isolated discover-source validation error.
259
+ */
260
+ __discoverError?: string | undefined;
248
261
  };
@@ -29,6 +29,7 @@ import {
29
29
  } from '../../authoring/integration/schema.mjs';
30
30
  import {importUserModule, findPresentFiles} from '../fs/module-loader.mjs';
31
31
  import {parseGapReportHandler} from '../../authoring/gap-report/parse.mjs';
32
+ import {parseDiscoverSource} from '../../authoring/discover/parse.mjs';
32
33
  import {resolveProviders} from './provider-resolution.mjs';
33
34
 
34
35
  /**
@@ -80,6 +81,9 @@ import {resolveProviders} from './provider-resolution.mjs';
80
81
  * validated package-owned handler from the `gapReport` NAMED export.
81
82
  * @property {string} [__gapReportError] isolated named-handler validation error.
82
83
  * Named exports are not manifest keys — see {@link loadManifest}.
84
+ * @property {import('../../authoring/discover/type').DiscoverSource} [__discover]
85
+ * validated catalog source from the `discover` NAMED export.
86
+ * @property {string} [__discoverError] isolated discover-source validation error.
83
87
  */
84
88
 
85
89
  /** Conventional manifest basenames, in load-precedence order. */
@@ -167,6 +171,23 @@ function parseGapReportHandlerExport(value, label) {
167
171
  }
168
172
  }
169
173
 
174
+ /**
175
+ * Parse the optional named discover source the same way: a malformed one is
176
+ * isolated from every other contribution and reported by `astryx discover`.
177
+ *
178
+ * @param {unknown} value
179
+ * @param {string} label
180
+ * @returns {{source?: import('../../authoring/discover/type').DiscoverSource, error?: string}}
181
+ */
182
+ function parseDiscoverSourceExport(value, label) {
183
+ if (value === undefined) return {};
184
+ try {
185
+ return {source: parseDiscoverSource(value, `${label} named export "discover"`)};
186
+ } catch (error) {
187
+ return {error: error instanceof Error ? error.message : String(error)};
188
+ }
189
+ }
190
+
170
191
  /**
171
192
  * Load and validate a manifest module's default export, while isolating the
172
193
  * optional `agentDocs` contribution from the manifest's other fields.
@@ -183,7 +204,7 @@ function parseGapReportHandlerExport(value, label) {
183
204
  * @param {string} file absolute manifest path
184
205
  * @param {string} [label] used in error messages
185
206
  * @param {{fresh?: boolean}} [options]
186
- * @returns {Promise<{manifest: import('../../authoring/integration/type').AstryxIntegration, unknownKeys: string[], debug?: import('../../authoring/debug/type').DebugEventHandler, gapReport?: import('../../authoring/gap-report/type').GapReportHandler, gapReportError?: string, agentDocsError?: string}>}
207
+ * @returns {Promise<{manifest: import('../../authoring/integration/type').AstryxIntegration, unknownKeys: string[], debug?: import('../../authoring/debug/type').DebugEventHandler, gapReport?: import('../../authoring/gap-report/type').GapReportHandler, gapReportError?: string, discover?: import('../../authoring/discover/type').DiscoverSource, discoverError?: string, agentDocsError?: string}>}
187
208
  */
188
209
  export async function loadManifest(
189
210
  file,
@@ -194,6 +215,7 @@ export async function loadManifest(
194
215
  const raw = mod?.default;
195
216
  const baseManifest = parseIntegrationBase(raw, label);
196
217
  const gapReport = parseGapReportHandlerExport(mod?.gapReport, label);
218
+ const discover = parseDiscoverSourceExport(mod?.discover, label);
197
219
  const hasAgentDocs =
198
220
  raw != null &&
199
221
  typeof raw === 'object' &&
@@ -228,6 +250,8 @@ export async function loadManifest(
228
250
  : undefined,
229
251
  gapReport: gapReport.handler,
230
252
  gapReportError: gapReport.error,
253
+ discover: discover.source,
254
+ discoverError: discover.error,
231
255
  agentDocsError,
232
256
  };
233
257
  }
@@ -345,6 +369,10 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
345
369
  let gapReportHandler;
346
370
  /** @type {string | undefined} */
347
371
  let gapReportError;
372
+ /** @type {import('../../authoring/discover/type').DiscoverSource | undefined} */
373
+ let discoverSource;
374
+ /** @type {string | undefined} */
375
+ let discoverError;
348
376
  /** @type {string | undefined} */
349
377
  let agentDocsError;
350
378
  try {
@@ -354,6 +382,8 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
354
382
  debug: debugHandler,
355
383
  gapReport: gapReportHandler,
356
384
  gapReportError,
385
+ discover: discoverSource,
386
+ discoverError,
357
387
  agentDocsError,
358
388
  } = await loadManifest(manifestFile, `Integration ${spec}`, {fresh}));
359
389
  } catch (err) {
@@ -397,6 +427,8 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
397
427
  __debug: debugHandler,
398
428
  __gapReport: gapReportHandler,
399
429
  __gapReportError: gapReportError,
430
+ __discover: discoverSource,
431
+ __discoverError: discoverError,
400
432
  __spec: spec,
401
433
  __packageDir: packageDir,
402
434
  __packageExports: pkg.exports ?? null,
@@ -448,6 +480,10 @@ export async function loadIntegrations(
448
480
  let gapReportHandler;
449
481
  /** @type {string | undefined} */
450
482
  let gapReportError;
483
+ /** @type {import('../../authoring/discover/type').DiscoverSource | undefined} */
484
+ let discoverSource;
485
+ /** @type {string | undefined} */
486
+ let discoverError;
451
487
  /** @type {string | undefined} */
452
488
  let agentDocsError;
453
489
  try {
@@ -457,6 +493,8 @@ export async function loadIntegrations(
457
493
  debug: debugHandler,
458
494
  gapReport: gapReportHandler,
459
495
  gapReportError,
496
+ discover: discoverSource,
497
+ discoverError,
460
498
  agentDocsError,
461
499
  } = await loadManifest(manifestFile, `Integration ${spec}`, {fresh}));
462
500
  } catch (err) {
@@ -507,6 +545,8 @@ export async function loadIntegrations(
507
545
  __debug: debugHandler,
508
546
  __gapReport: gapReportHandler,
509
547
  __gapReportError: gapReportError,
548
+ __discover: discoverSource,
549
+ __discoverError: discoverError,
510
550
  __spec: spec,
511
551
  __packageDir: packageDir,
512
552
  __packageExports: pkg.exports ?? null,
@@ -785,3 +785,34 @@ describe('the `gapReport` named export', () => {
785
785
  expect(loaded.__unknownKeys).toEqual(['gapReport']);
786
786
  });
787
787
  });
788
+
789
+ describe('the `discover` named export', () => {
790
+ it('is carried out of the manifest module as __discover', async () => {
791
+ writeManifestPackage(tmpDir, {
792
+ body:
793
+ `export async function discover() { return {schemaVersion: 1}; }\n` +
794
+ `export default {issuesUrl: 'https://example.com/i'};\n`,
795
+ });
796
+
797
+ const [loaded] = await loadIntegrations(['@acme/widgets'], {cwd: tmpDir});
798
+
799
+ expect(typeof loaded.__discover).toBe('function');
800
+ expect(loaded.__discoverError).toBeUndefined();
801
+ expect(loaded.__unknownKeys).toEqual([]);
802
+ expect(loaded.issuesUrl).toBe('https://example.com/i');
803
+ });
804
+
805
+ it('keeps the manifest and records why when the export is not a function', async () => {
806
+ writeManifestPackage(tmpDir, {
807
+ body:
808
+ `export const discover = {url: 'https://example.com/catalog.json'};\n` +
809
+ `export default {issuesUrl: 'https://example.com/i'};\n`,
810
+ });
811
+
812
+ const [loaded] = await loadIntegrations(['@acme/widgets'], {cwd: tmpDir});
813
+
814
+ expect(loaded.__discover).toBeUndefined();
815
+ expect(loaded.__discoverError).toContain('must be a function');
816
+ expect(loaded.issuesUrl).toBe('https://example.com/i');
817
+ });
818
+ });
@@ -0,0 +1,33 @@
1
+ // @generated by scripts/sync-api-types.mjs from the JSDoc in foundation/**/*.mjs.
2
+ // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
+
4
+ /**
5
+ * One complete row for an accepted selector.
6
+ */
7
+ export type BatchRow<TResult, TCandidate> = ({
8
+ selector: string;
9
+ status: "found";
10
+ result: TResult;
11
+ } | {
12
+ selector: string;
13
+ status: "ambiguous";
14
+ code: string;
15
+ error: string;
16
+ candidates: TCandidate[];
17
+ } | {
18
+ selector: string;
19
+ status: "not_found" | "error";
20
+ code: string;
21
+ error: string;
22
+ suggestions?: import("./base").Suggestion[];
23
+ });
24
+ /**
25
+ * One ordered batch receipt inside the shared `{type, data}` success envelope.
26
+ */
27
+ export type BatchResponse<TType extends string, TResult, TCandidate> = {
28
+ type: TType;
29
+ data: {
30
+ count: number;
31
+ results: BatchRow<TResult, TCandidate>[];
32
+ };
33
+ };