@astryxdesign/cli 0.6.3-canary.98a2e4e → 0.6.3-canary.9c4d44d

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 (612) hide show
  1. package/README.md +117 -79
  2. package/api/blog/blog.doc.mjs +1 -0
  3. package/api/build/_adapter.d.mts +50 -0
  4. package/api/build/_adapter.mjs +60 -0
  5. package/api/build/build.doc.mjs +16 -9
  6. package/api/build/build.test.mjs +197 -8
  7. package/api/build/build.type.d.mts +91 -2
  8. package/api/build/build.type.mjs +52 -8
  9. package/api/build/help/help.d.mts +12 -5
  10. package/api/build/help/help.mjs +69 -6
  11. package/api/build/kit/kit.d.mts +4 -1
  12. package/api/build/kit/kit.mjs +165 -49
  13. package/api/build/kit/rank.d.mts +44 -0
  14. package/api/build/kit/rank.mjs +432 -0
  15. package/api/build/kit/rank.test.mjs +196 -0
  16. package/api/component/_adapter.d.mts +6 -12
  17. package/api/component/_adapter.mjs +20 -10
  18. package/api/component/component.doc.mjs +13 -3
  19. package/api/component/component.mjs +91 -14
  20. package/api/component/component.test.mjs +38 -0
  21. package/api/component/component.type.d.mts +22 -11
  22. package/api/component/component.type.mjs +32 -24
  23. package/api/component/detail/blocks/blocks.d.mts +2 -1
  24. package/api/component/detail/blocks/blocks.mjs +4 -3
  25. package/api/component/list/list.d.mts +0 -5
  26. package/api/component/list/list.mjs +40 -11
  27. package/api/discover/_adapter.d.mts +114 -6
  28. package/api/discover/_adapter.mjs +372 -17
  29. package/api/discover/_adapter.test.mjs +215 -0
  30. package/api/discover/_catalog-view.d.mts +115 -0
  31. package/api/discover/_catalog-view.mjs +203 -0
  32. package/api/discover/_catalog-view.test.mjs +128 -0
  33. package/api/discover/detail/detail.d.mts +18 -6
  34. package/api/discover/detail/detail.mjs +67 -13
  35. package/api/discover/detail/detail.test.mjs +85 -0
  36. package/api/discover/detail/item/item.d.mts +26 -0
  37. package/api/discover/detail/item/item.mjs +78 -0
  38. package/api/discover/detail/item/item.test.mjs +73 -0
  39. package/api/discover/discover.d.mts +3 -9
  40. package/api/discover/discover.doc.mjs +62 -18
  41. package/api/discover/discover.mjs +220 -36
  42. package/api/discover/discover.test.mjs +11 -2
  43. package/api/discover/discover.type.d.mts +150 -11
  44. package/api/discover/discover.type.mjs +107 -17
  45. package/api/discover/list/list.d.mts +20 -6
  46. package/api/discover/list/list.mjs +45 -12
  47. package/api/discover/list/list.test.mjs +46 -0
  48. package/api/discover/search/search.d.mts +18 -16
  49. package/api/discover/search/search.mjs +102 -56
  50. package/api/discover/search/search.test.mjs +144 -10
  51. package/api/docs/_adapter.d.mts +268 -47
  52. package/api/docs/_adapter.mjs +970 -149
  53. package/api/docs/compiled-topics.test.mjs +78 -0
  54. package/api/docs/detail/detail.d.mts +0 -15
  55. package/api/docs/detail/detail.mjs +22 -78
  56. package/api/docs/detail/section/section.mjs +39 -24
  57. package/api/docs/detail/section/section.test.mjs +19 -9
  58. package/api/docs/docs.d.mts +5 -3
  59. package/api/docs/docs.doc.mjs +39 -17
  60. package/api/docs/docs.mjs +44 -8
  61. package/api/docs/docs.test.mjs +158 -4
  62. package/api/docs/docs.type.d.mts +185 -6
  63. package/api/docs/docs.type.mjs +127 -13
  64. package/api/docs/index/index.mjs +15 -6
  65. package/api/docs/index/index.test.mjs +1 -1
  66. package/api/docs/integration-tree.test.mjs +555 -0
  67. package/api/docs/integrationDocs.test.mjs +14 -14
  68. package/api/docs/list/list.mjs +28 -12
  69. package/api/docs/node/node.d.mts +43 -0
  70. package/api/docs/node/node.mjs +192 -0
  71. package/api/docs/reference-blocks.test.mjs +406 -0
  72. package/api/doctor/doctor.d.mts +54 -4
  73. package/api/doctor/doctor.doc.mjs +1 -0
  74. package/api/doctor/doctor.mjs +332 -21
  75. package/api/doctor/doctor.test.mjs +420 -7
  76. package/api/gap-report/gap-report.doc.mjs +8 -4
  77. package/api/hook/_adapter.mjs +19 -5
  78. package/api/hook/hook.doc.mjs +1 -0
  79. package/api/hook/hook.type.d.mts +3 -3
  80. package/api/hook/hook.type.mjs +11 -11
  81. package/api/hook/list/list.d.mts +1 -1
  82. package/api/hook/list/list.mjs +69 -17
  83. package/api/index.d.mts +1 -1
  84. package/api/index.mjs +1 -0
  85. package/api/init/init.doc.mjs +6 -1
  86. package/api/init/init.test.mjs +41 -1
  87. package/api/init/remove/remove.mjs +1 -1
  88. package/api/init/run/run.mjs +20 -10
  89. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  90. package/api/integration/add-contribution.d.mts +2 -1
  91. package/api/integration/add-contribution.mjs +130 -15
  92. package/api/integration/add-contribution.test.mjs +258 -7
  93. package/api/integration/add-helpers.d.mts +5 -2
  94. package/api/integration/add-helpers.mjs +36 -9
  95. package/api/integration/add-theme.mjs +34 -64
  96. package/api/integration/add-theme.test.mjs +105 -21
  97. package/api/integration/authoring-checks.mjs +138 -28
  98. package/api/integration/authoring-checks.test.mjs +179 -7
  99. package/api/integration/authoring-checks.type.mjs +6 -1
  100. package/api/integration/integration-authoring.type.d.mts +2 -0
  101. package/api/integration/integration-authoring.type.mjs +2 -0
  102. package/api/integration/integration-block-exports.test.mjs +10 -6
  103. package/api/integration/integrationAdd.doc.mjs +14 -4
  104. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  105. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  106. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  107. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  108. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  109. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  110. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  111. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  112. package/api/integration/integrationPackCheck.doc.mjs +2 -1
  113. package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
  114. package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
  115. package/api/integration/pack-check.mjs +83 -7
  116. package/api/integration/pack-check.test.mjs +387 -47
  117. package/api/integration/pack-check.type.d.mts +26 -2
  118. package/api/integration/pack-check.type.mjs +14 -1
  119. package/api/integration/summarizeIssues.doc.mjs +1 -0
  120. package/api/integration/template-conflict-compatibility.test.mjs +73 -0
  121. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  122. package/api/integration/validate-integration.mjs +52 -102
  123. package/api/integration/validate-integration.test.mjs +179 -26
  124. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  125. package/api/integration/validateIntegration.doc.mjs +3 -2
  126. package/api/json/assertResponse.doc.mjs +1 -0
  127. package/api/json/envelope-types.test.mjs +76 -0
  128. package/api/json/index.ts +2 -0
  129. package/api/json/isError.doc.mjs +1 -0
  130. package/api/json/parseResponse.doc.mjs +3 -2
  131. package/api/layout/_adapter.mjs +20 -5
  132. package/api/layout/expand/expand.mjs +7 -5
  133. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  134. package/api/layout/grammar/grammar.mjs +2 -1
  135. package/api/layout/layoutCheck.doc.mjs +1 -0
  136. package/api/layout/layoutExpand.doc.mjs +2 -1
  137. package/api/layout/layoutGrammar.doc.mjs +1 -0
  138. package/api/search/search-return-type.test.mjs +54 -0
  139. package/api/search/search.d.mts +61 -10
  140. package/api/search/search.doc.mjs +8 -2
  141. package/api/search/search.mjs +471 -83
  142. package/api/search/search.test.mjs +124 -1
  143. package/api/search/search.type.d.mts +14 -2
  144. package/api/search/search.type.mjs +5 -2
  145. package/api/swizzle/copy/copy.mjs +28 -11
  146. package/api/swizzle/swizzle.doc.mjs +2 -1
  147. package/api/swizzle/swizzle.type.d.mts +2 -2
  148. package/api/swizzle/swizzle.type.mjs +2 -2
  149. package/api/template/copy/copy.mjs +17 -23
  150. package/api/template/copy/copy.test.mjs +17 -0
  151. package/api/template/list/list.mjs +1 -0
  152. package/api/template/table-floating-bulk-actions.test.mjs +66 -0
  153. package/api/template/template-integration.test.mjs +1072 -3
  154. package/api/template/template-suffix.test.mjs +41 -21
  155. package/api/template/template.doc.mjs +30 -8
  156. package/api/template/template.mjs +45 -8
  157. package/api/template/template.type.d.mts +11 -13
  158. package/api/template/template.type.mjs +15 -14
  159. package/api/theme/_adapter.d.mts +2 -3
  160. package/api/theme/_adapter.mjs +4 -5
  161. package/api/theme/add/add.binary.test.mjs +84 -0
  162. package/api/theme/add/add.mjs +31 -22
  163. package/api/theme/add/add.rollback.test.mjs +158 -0
  164. package/api/theme/add/add.staging.test.mjs +83 -0
  165. package/api/theme/add/add.test.mjs +14 -1
  166. package/api/theme/build/build.family.test.mjs +7 -12
  167. package/api/theme/build/build.mjs +140 -59
  168. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  169. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  170. package/api/theme/build/build.rollback.test.mjs +148 -0
  171. package/api/theme/build/build.test.mjs +127 -0
  172. package/api/theme/build/font-warning.mjs +3 -3
  173. package/api/theme/build/font-warning.test.mjs +5 -2
  174. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  175. package/api/theme/integration-themes.test.mjs +39 -28
  176. package/api/theme/list/list.test.mjs +19 -20
  177. package/api/theme/listThemes.doc.mjs +6 -5
  178. package/api/theme/palette/generate/generate.mjs +8 -3
  179. package/api/theme/palette/generate/generate.test.mjs +96 -0
  180. package/api/theme/palette/generate/generator.d.mts +10 -13
  181. package/api/theme/palette/generate/generator.mjs +15 -4
  182. package/api/theme/palette/generate/generator.test.mjs +10 -0
  183. package/api/theme/template/template.mjs +11 -2
  184. package/api/theme/template/template.test.mjs +20 -0
  185. package/api/theme/theme.type.d.mts +170 -11
  186. package/api/theme/theme.type.mjs +94 -27
  187. package/api/theme/themeAdd.doc.mjs +4 -3
  188. package/api/theme/themeBuild.doc.mjs +8 -4
  189. package/api/theme/themeList.doc.mjs +6 -3
  190. package/api/theme/themeListAvailable.doc.mjs +5 -3
  191. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  192. package/api/theme/themeTargets.doc.mjs +1 -0
  193. package/api/theme/themeTemplate.doc.mjs +6 -2
  194. package/api/upgrade/_adapter.d.mts +32 -5
  195. package/api/upgrade/_adapter.mjs +124 -73
  196. package/api/upgrade/list/list.mjs +2 -1
  197. package/api/upgrade/list/list.test.mjs +73 -0
  198. package/api/upgrade/provider-agreement.test.mjs +152 -0
  199. package/api/upgrade/run/run.mjs +356 -59
  200. package/api/upgrade/status/status.mjs +2 -2
  201. package/api/upgrade/upgrade.doc.mjs +8 -2
  202. package/api/upgrade/upgrade.type.d.mts +42 -4
  203. package/api/upgrade/upgrade.type.mjs +26 -10
  204. package/assets/codemods/__tests__/runner.test.mjs +330 -8
  205. package/assets/codemods/integration-discovery.mjs +48 -4
  206. package/assets/codemods/integration-discovery.test.mjs +73 -0
  207. package/assets/codemods/integration-runner.mjs +56 -4
  208. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  209. package/assets/codemods/run-codemod.mjs +177 -34
  210. package/assets/codemods/runner.mjs +350 -102
  211. package/assets/codemods/term-log.mjs +32 -8
  212. package/assets/codemods/term-log.test.mjs +19 -1
  213. package/assets/codemods/transform-prop.mjs +109 -0
  214. package/assets/codemods/transform-prop.test.mjs +95 -0
  215. package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  216. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  217. package/assets/codemods/transforms/next/index.mjs +19 -1
  218. package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
  219. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  220. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  221. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  222. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  223. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  224. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  225. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  226. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  227. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  228. package/assets/docs/getting-started.doc.mjs +2 -2
  229. package/assets/docs/internationalization.doc.mjs +7 -5
  230. package/assets/docs/layout.doc.dense.mjs +2 -2
  231. package/assets/docs/layout.doc.mjs +1 -1
  232. package/assets/docs/principles.doc.mjs +6 -6
  233. package/assets/docs/styling-libraries.doc.mjs +4 -4
  234. package/assets/docs/styling.doc.mjs +4 -4
  235. package/assets/docs/theme.doc.mjs +5 -5
  236. package/assets/docs/tokens.doc.mjs +1 -1
  237. package/assets/docs/tree/api.doc.mjs +30 -0
  238. package/assets/docs/tree/cli.doc.mjs +23 -0
  239. package/assets/docs/tree/commands.doc.mjs +25 -0
  240. package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +95 -39
  241. package/assets/docs/tree/integrations.test.mjs +62 -0
  242. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  243. package/assets/docs/working-with-ai.doc.mjs +4 -4
  244. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
  245. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
  246. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  247. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  248. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  249. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  250. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  251. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  252. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  253. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  254. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  255. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  256. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  257. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  258. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  259. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  260. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  261. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  262. package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
  263. package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
  264. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
  265. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
  266. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  267. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  268. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  269. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  270. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  271. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  272. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  273. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  274. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  275. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  276. package/authoring/_shared/contract.ts +22 -0
  277. package/authoring/codemod/codemod.doc.mjs +7 -2
  278. package/authoring/codemod/parse.d.mts +8 -8
  279. package/authoring/codemod/parse.mjs +8 -6
  280. package/authoring/codemod/type.ts +12 -0
  281. package/authoring/config/config.doc.mjs +10 -2
  282. package/authoring/config/debug-composition.test.mjs +92 -0
  283. package/authoring/config/parse.d.mts +15 -13
  284. package/authoring/config/parse.mjs +27 -8
  285. package/authoring/config/parse.test.mjs +8 -0
  286. package/authoring/config/type.ts +29 -6
  287. package/authoring/debug/debug.doc.d.mts +11 -0
  288. package/authoring/debug/debug.doc.mjs +182 -0
  289. package/authoring/debug/parse.d.mts +7 -7
  290. package/authoring/debug/parse.mjs +3 -3
  291. package/authoring/discover/discover.doc.d.mts +13 -0
  292. package/authoring/discover/discover.doc.mjs +138 -0
  293. package/authoring/discover/parse.d.mts +24 -0
  294. package/authoring/discover/parse.mjs +128 -0
  295. package/authoring/discover/parse.test.mjs +124 -0
  296. package/authoring/discover/type.ts +87 -0
  297. package/authoring/doctypes/_schema.d.mts +240 -128
  298. package/authoring/doctypes/_schema.mjs +198 -16
  299. package/authoring/doctypes/base/graph-fields.doc.mjs +15 -6
  300. package/authoring/doctypes/base/type.ts +9 -4
  301. package/authoring/doctypes/command/command.doc.mjs +4 -3
  302. package/authoring/doctypes/command/parse.d.mts +2 -2
  303. package/authoring/doctypes/command/parse.mjs +1 -1
  304. package/authoring/doctypes/command/type.ts +4 -4
  305. package/authoring/doctypes/component/component.doc.mjs +5 -2
  306. package/authoring/doctypes/component/parse.d.mts +2 -2
  307. package/authoring/doctypes/component/parse.mjs +1 -1
  308. package/authoring/doctypes/component/type.ts +3 -3
  309. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  310. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  311. package/authoring/doctypes/enum/parse.d.mts +2 -2
  312. package/authoring/doctypes/enum/parse.mjs +1 -1
  313. package/authoring/doctypes/enum/type.ts +2 -2
  314. package/authoring/doctypes/function/function.doc.mjs +7 -2
  315. package/authoring/doctypes/function/parse.d.mts +2 -2
  316. package/authoring/doctypes/function/parse.mjs +1 -1
  317. package/authoring/doctypes/function/type.ts +4 -3
  318. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  319. package/authoring/doctypes/hook/parse.d.mts +2 -2
  320. package/authoring/doctypes/hook/parse.mjs +1 -1
  321. package/authoring/doctypes/hook/type.ts +3 -3
  322. package/authoring/doctypes/legacy.d.mts +6 -6
  323. package/authoring/doctypes/legacy.mjs +3 -3
  324. package/authoring/doctypes/load-contract.test.mjs +233 -0
  325. package/authoring/doctypes/namespace/namespace.doc.mjs +9 -9
  326. package/authoring/doctypes/namespace/parse.d.mts +2 -2
  327. package/authoring/doctypes/namespace/parse.mjs +1 -1
  328. package/authoring/doctypes/namespace/parse.test.mjs +23 -25
  329. package/authoring/doctypes/namespace/type.ts +6 -3
  330. package/authoring/doctypes/parse.d.mts +22 -20
  331. package/authoring/doctypes/parse.mjs +19 -14
  332. package/authoring/doctypes/reference/parse.d.mts +2 -2
  333. package/authoring/doctypes/reference/parse.mjs +1 -1
  334. package/authoring/doctypes/reference/reference.doc.mjs +39 -6
  335. package/authoring/doctypes/reference/type.ts +31 -14
  336. package/authoring/doctypes/schema/parse.d.mts +2 -2
  337. package/authoring/doctypes/schema/parse.mjs +1 -1
  338. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  339. package/authoring/doctypes/schema/type.ts +3 -4
  340. package/authoring/doctypes/template/parse.d.mts +94 -1
  341. package/authoring/doctypes/template/parse.mjs +37 -1
  342. package/authoring/doctypes/template/parse.test.mjs +18 -0
  343. package/authoring/doctypes/template/template.doc.mjs +13 -3
  344. package/authoring/doctypes/template/type.ts +12 -1
  345. package/authoring/doctypes/theme/parse.d.mts +35 -0
  346. package/authoring/doctypes/theme/parse.mjs +76 -0
  347. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  348. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  349. package/authoring/doctypes/theme/type.ts +42 -0
  350. package/authoring/doctypes/types.ts +12 -11
  351. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  352. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  353. package/authoring/gap-report/parse.d.mts +9 -9
  354. package/authoring/gap-report/parse.mjs +6 -6
  355. package/authoring/gap-report/type.ts +1 -1
  356. package/authoring/identity/identity.doc.mjs +3 -2
  357. package/authoring/identity/type.ts +10 -10
  358. package/authoring/index.d.mts +2 -0
  359. package/authoring/index.d.ts +32 -19
  360. package/authoring/index.mjs +3 -1
  361. package/authoring/integration/integration.doc.mjs +2 -2
  362. package/authoring/integration/parse.d.mts +2 -2
  363. package/authoring/integration/parse.mjs +1 -1
  364. package/authoring/integration/schema.d.mts +4 -4
  365. package/authoring/integration/schema.mjs +3 -3
  366. package/authoring/integration/type.ts +5 -11
  367. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  368. package/clients/cli/command-load-failure.test.mjs +83 -0
  369. package/clients/cli/commands/blog.doc.mjs +1 -1
  370. package/clients/cli/commands/blog.mjs +23 -8
  371. package/clients/cli/commands/blog.test.mjs +42 -1
  372. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  373. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  374. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  375. package/clients/cli/commands/build-theme.mjs +16 -50
  376. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  377. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  378. package/clients/cli/commands/build.doc.mjs +16 -8
  379. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  380. package/clients/cli/commands/build.mjs +137 -114
  381. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  382. package/clients/cli/commands/build.text-fields.test.mjs +81 -0
  383. package/clients/cli/commands/component/index.mjs +3 -8
  384. package/clients/cli/commands/component-ownership.test.mjs +3 -3
  385. package/clients/cli/commands/component-package.test.mjs +46 -0
  386. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  387. package/clients/cli/commands/component.doc.mjs +1 -1
  388. package/clients/cli/commands/component.test.mjs +19 -0
  389. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  390. package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
  391. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  392. package/clients/cli/commands/discover.doc.mjs +55 -9
  393. package/clients/cli/commands/discover.mjs +393 -118
  394. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  395. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  396. package/clients/cli/commands/docs.doc.mjs +21 -9
  397. package/clients/cli/commands/docs.mjs +184 -70
  398. package/clients/cli/commands/docs.test.mjs +120 -16
  399. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  400. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
  401. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  402. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  403. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  404. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  405. package/clients/cli/commands/doctor-integration.test.mjs +90 -8
  406. package/clients/cli/commands/doctor.doc.mjs +1 -1
  407. package/clients/cli/commands/doctor.mjs +59 -32
  408. package/clients/cli/commands/doctor.test.mjs +42 -0
  409. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  410. package/clients/cli/commands/gap-report.test.mjs +72 -0
  411. package/clients/cli/commands/hook/index.mjs +7 -17
  412. package/clients/cli/commands/hook.doc.mjs +1 -1
  413. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  414. package/clients/cli/commands/init.doc.mjs +20 -9
  415. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  416. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  417. package/clients/cli/commands/integration-add.doc.mjs +32 -6
  418. package/clients/cli/commands/integration-authoring.test.mjs +13 -9
  419. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  420. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  421. package/clients/cli/commands/integration.doc.mjs +1 -1
  422. package/clients/cli/commands/integration.mjs +1 -0
  423. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  424. package/clients/cli/commands/json-contract.test.mjs +33 -0
  425. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  426. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  427. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  428. package/clients/cli/commands/layout.doc.mjs +3 -3
  429. package/clients/cli/commands/layout.mjs +21 -9
  430. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  431. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  432. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  433. package/clients/cli/commands/manifest.doc.mjs +1 -1
  434. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  435. package/clients/cli/commands/search.doc.mjs +7 -4
  436. package/clients/cli/commands/search.mjs +28 -9
  437. package/clients/cli/commands/search.test.mjs +75 -0
  438. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  439. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  440. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  441. package/clients/cli/commands/template.doc.mjs +52 -13
  442. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  443. package/clients/cli/commands/template.mjs +4 -91
  444. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  445. package/clients/cli/commands/text-json-parity.test.mjs +719 -0
  446. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  447. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  448. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  449. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
  450. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  451. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  452. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  453. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  454. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  455. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  456. package/clients/cli/commands/theme.doc.mjs +1 -1
  457. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  458. package/clients/cli/commands/upgrade.doc.mjs +20 -8
  459. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  460. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  461. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  462. package/clients/cli/commands/upgrade.mjs +29 -7
  463. package/clients/cli/formatters/index.mjs +2 -0
  464. package/clients/cli/formatters/index.test.mjs +6 -0
  465. package/clients/cli/index.mjs +21 -30
  466. package/clients/cli/latest-version-env.test.mjs +50 -0
  467. package/clients/cli/lib/cli-error.test.mjs +7 -0
  468. package/clients/cli/lib/component-format.mjs +9 -9
  469. package/clients/cli/lib/component-format.test.mjs +1 -1
  470. package/clients/cli/lib/define-command.mjs +32 -6
  471. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  472. package/clients/cli/lib/exit-codes.test.mjs +97 -0
  473. package/clients/cli/lib/hook-format.mjs +19 -10
  474. package/clients/cli/lib/json-shim.mjs +38 -2
  475. package/clients/cli/lib/json-shim.test.mjs +83 -0
  476. package/clients/cli/lib/manifest.d.ts +2 -0
  477. package/clients/cli/lib/manifest.mjs +32 -2
  478. package/clients/cli/lib/manifest.test.mjs +17 -0
  479. package/foundation/agent-docs/agent-docs.d.mts +7 -2
  480. package/foundation/agent-docs/agent-docs.mjs +82 -12
  481. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  482. package/foundation/agent-docs/agent-docs.test.mjs +19 -1
  483. package/foundation/config/integration-debug.test.mjs +28 -3
  484. package/foundation/config/project-themes.test.mjs +11 -19
  485. package/foundation/config/project.d.mts +20 -11
  486. package/foundation/config/project.mjs +246 -89
  487. package/foundation/config/project.test.mjs +270 -21
  488. package/foundation/discovery/authoring-self-docs.d.mts +18 -0
  489. package/foundation/discovery/authoring-self-docs.mjs +38 -15
  490. package/foundation/discovery/authoring-self-docs.test.mjs +87 -12
  491. package/foundation/discovery/authoring-surface.d.mts +74 -0
  492. package/foundation/discovery/authoring-surface.mjs +525 -0
  493. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  494. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  495. package/foundation/discovery/cli-self-docs.mjs +490 -0
  496. package/foundation/discovery/cli-self-docs.test.mjs +375 -0
  497. package/foundation/discovery/component-discovery.d.mts +38 -0
  498. package/foundation/discovery/component-discovery.mjs +48 -0
  499. package/foundation/discovery/component-loader.d.mts +35 -38
  500. package/foundation/discovery/component-loader.mjs +53 -222
  501. package/foundation/discovery/docs-discovery.d.mts +114 -9
  502. package/foundation/discovery/docs-discovery.mjs +239 -30
  503. package/foundation/discovery/docs-discovery.test.mjs +150 -35
  504. package/foundation/discovery/docs-output-budget.d.mts +2 -2
  505. package/foundation/discovery/docs-output-budget.mjs +1 -1
  506. package/foundation/discovery/docs-section-key.d.mts +28 -10
  507. package/foundation/discovery/docs-section-key.mjs +134 -33
  508. package/foundation/discovery/docs-section-key.test.mjs +41 -19
  509. package/foundation/discovery/template-adapter.d.mts +113 -11
  510. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  511. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  512. package/foundation/discovery/template-adapter.mjs +772 -82
  513. package/foundation/discovery/template-adapter.test.mjs +57 -0
  514. package/foundation/discovery/template-conflict-release.d.mts +13 -0
  515. package/foundation/discovery/template-conflict-release.mjs +40 -0
  516. package/foundation/discovery/template-conflict-release.test.mjs +40 -0
  517. package/foundation/discovery/theme-discovery.d.mts +67 -7
  518. package/foundation/discovery/theme-discovery.mjs +916 -186
  519. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  520. package/foundation/discovery/theming-targets.test.mjs +4 -0
  521. package/foundation/doc-compiler/bundle.d.mts +47 -0
  522. package/foundation/doc-compiler/bundle.mjs +278 -0
  523. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  524. package/foundation/doc-compiler/compile.d.mts +343 -0
  525. package/foundation/doc-compiler/compile.mjs +558 -0
  526. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  527. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  528. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  529. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  530. package/foundation/doc-compiler/import.d.mts +24 -0
  531. package/foundation/doc-compiler/import.mjs +59 -0
  532. package/foundation/doc-compiler/inputs.d.mts +102 -0
  533. package/foundation/doc-compiler/inputs.mjs +291 -0
  534. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  535. package/foundation/doc-compiler/ir.d.mts +22 -0
  536. package/foundation/doc-compiler/ir.mjs +471 -0
  537. package/foundation/doc-compiler/lenses.d.mts +36 -0
  538. package/foundation/doc-compiler/lenses.mjs +173 -0
  539. package/foundation/doc-compiler/links.d.mts +162 -0
  540. package/foundation/doc-compiler/links.mjs +294 -0
  541. package/foundation/doc-compiler/links.test.mjs +192 -0
  542. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  543. package/foundation/doc-compiler/overlays.d.mts +37 -0
  544. package/foundation/doc-compiler/overlays.mjs +206 -0
  545. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  546. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  547. package/foundation/doc-compiler/read.d.mts +127 -0
  548. package/foundation/doc-compiler/read.mjs +325 -0
  549. package/foundation/doc-compiler/read.test.mjs +313 -0
  550. package/foundation/doc-compiler/source.d.mts +33 -0
  551. package/foundation/doc-compiler/source.mjs +128 -0
  552. package/foundation/doc-compiler/tree.d.mts +288 -0
  553. package/foundation/doc-compiler/tree.mjs +876 -0
  554. package/foundation/doc-compiler/tree.test.mjs +598 -0
  555. package/foundation/fs/file-protection.d.mts +33 -0
  556. package/foundation/fs/file-protection.mjs +825 -0
  557. package/foundation/fs/file-protection.test.mjs +250 -0
  558. package/foundation/fs/module-loader.d.mts +1 -0
  559. package/foundation/fs/module-loader.mjs +50 -1
  560. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  561. package/foundation/fs/path-safety.d.mts +3 -2
  562. package/foundation/fs/path-safety.mjs +49 -19
  563. package/foundation/fs/path-safety.test.mjs +50 -0
  564. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  565. package/foundation/integrations/autolink.d.mts +58 -1
  566. package/foundation/integrations/autolink.mjs +143 -52
  567. package/foundation/integrations/autolink.test.mjs +1 -1
  568. package/foundation/integrations/cli-requirement.d.mts +45 -0
  569. package/foundation/integrations/cli-requirement.mjs +154 -0
  570. package/foundation/integrations/cli-requirement.test.mjs +84 -0
  571. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  572. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  573. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  574. package/foundation/integrations/contribution-inventory.mjs +27 -24
  575. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  576. package/foundation/integrations/integration-warnings.d.mts +9 -2
  577. package/foundation/integrations/integration-warnings.mjs +51 -26
  578. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  579. package/foundation/integrations/integrations.d.mts +17 -1
  580. package/foundation/integrations/integrations.mjs +52 -98
  581. package/foundation/integrations/integrations.test.mjs +31 -0
  582. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  583. package/foundation/integrations/provider-resolution.d.mts +152 -0
  584. package/foundation/integrations/provider-resolution.mjs +576 -0
  585. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  586. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  587. package/foundation/integrations/theme-descriptor.mjs +44 -0
  588. package/foundation/integrations/validate-contributions.mjs +121 -29
  589. package/foundation/response/base.d.ts +8 -4
  590. package/foundation/response/error-codes.d.mts +3 -1
  591. package/foundation/response/error-codes.d.ts +2 -0
  592. package/foundation/response/error-codes.doc.mjs +13 -4
  593. package/foundation/response/error-codes.mjs +8 -2
  594. package/foundation/response/error-codes.test.mjs +137 -10
  595. package/foundation/response/json-contract.test.mjs +11 -0
  596. package/foundation/response/json.d.mts +4 -2
  597. package/foundation/response/json.mjs +8 -10
  598. package/foundation/response/response-types.doc.d.mts +5 -1
  599. package/foundation/response/response-types.doc.mjs +37 -22
  600. package/foundation/response/response-types.doc.test.mjs +158 -0
  601. package/foundation/response/response.doc.mjs +1 -1
  602. package/foundation/text/string-utils.d.mts +8 -0
  603. package/foundation/text/string-utils.mjs +40 -10
  604. package/foundation/xle/expand.d.mts +2 -0
  605. package/foundation/xle/expand.mjs +4 -3
  606. package/foundation/xle/expand.test.mjs +54 -0
  607. package/foundation/xle/xle.test.mjs +13 -0
  608. package/package.json +10 -11
  609. package/assets/templates/themes/manifest.json +0 -95
  610. package/clients/cli/lib/update-check.mjs +0 -83
  611. package/clients/cli/lib/update-check.test.mjs +0 -137
  612. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -29,6 +29,8 @@ 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';
33
+ import {resolveProviders} from './provider-resolution.mjs';
32
34
 
33
35
  /**
34
36
  * A fully-resolved, loaded integration. Identity (`name`, `version`) comes from
@@ -79,6 +81,9 @@ import {parseGapReportHandler} from '../../authoring/gap-report/parse.mjs';
79
81
  * validated package-owned handler from the `gapReport` NAMED export.
80
82
  * @property {string} [__gapReportError] isolated named-handler validation error.
81
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.
82
87
  */
83
88
 
84
89
  /** Conventional manifest basenames, in load-precedence order. */
@@ -116,107 +121,20 @@ function providerIdForPackage(name) {
116
121
  * issues, Doctor, and the per-command warning name the one set aside instead of
117
122
  * dropping it without a word.
118
123
  *
124
+ * The conflict pass of {@link resolveProviders}, for a list that is already
125
+ * assembled.
126
+ *
119
127
  * @param {LoadedIntegration[]} integrations in precedence order
120
128
  * @returns {LoadedIntegration[]}
121
129
  */
122
130
  export function markProviderConflicts(integrations) {
123
- /** @type {Map<string, LoadedIntegration>} */
124
- const claims = new Map();
125
- for (const integration of integrations) {
126
- if (integration?.__local && claimsProvider(integration)) {
127
- const providerId = /** @type {string} */ (integration.providerId);
128
- if (!claims.has(providerId)) claims.set(providerId, integration);
129
- }
130
- }
131
- /** @type {LoadedIntegration[]} */
132
- const resolved = [];
133
- for (const integration of integrations) {
134
- if (!claimsProvider(integration)) {
135
- resolved.push(integration);
136
- continue;
137
- }
138
- const providerId = /** @type {string} */ (integration.providerId);
139
- const claimant = claims.get(providerId);
140
- if (claimant == null) {
141
- claims.set(providerId, integration);
142
- resolved.push(integration);
143
- } else if (claimant === integration) {
144
- resolved.push(integration);
145
- } else if (
146
- claimant.name !== integration.name ||
147
- claimant.version !== integration.version
148
- ) {
149
- resolved.push(providerConflict(integration, claimant));
150
- }
151
- }
152
- return resolved;
153
- }
154
-
155
- /**
156
- * Whether an entry contributes under its provider ID: it has one, its manifest
157
- * loaded, and it has not already been set aside.
158
- * @param {LoadedIntegration | undefined} integration
159
- * @returns {boolean}
160
- */
161
- function claimsProvider(integration) {
162
- return (
163
- integration?.providerId != null &&
164
- integration.__loadError == null &&
165
- integration.__providerConflict == null
166
- );
167
- }
168
-
169
- /**
170
- * @param {LoadedIntegration} integration
171
- * @returns {string}
172
- */
173
- function describeIntegration(integration) {
174
- const id = integration.version
175
- ? `${integration.name}@${integration.version}`
176
- : integration.name;
177
- return integration.__spec && integration.__spec !== integration.name
178
- ? `${id} (from "${integration.__spec}")`
179
- : id;
180
- }
181
-
182
- /**
183
- * An inert record for a package whose provider ID is already claimed. It keeps
184
- * the package's identity and location for reporting, and drops every
185
- * contribution root and handler.
186
- * @param {LoadedIntegration} integration
187
- * @param {LoadedIntegration} claimant
188
- * @returns {LoadedIntegration}
189
- */
190
- function providerConflict(integration, claimant) {
191
- const providerId =
192
- /** @type {import('../../authoring/identity/type').ProviderId} */ (
193
- integration.providerId
194
- );
195
- const winner = describeIntegration(claimant);
196
- const setAside = describeIntegration(integration);
197
- const reason = claimant.__local
198
- ? 'is the package being authored, so it is used'
199
- : 'loads first and is used';
200
- return {
201
- name: integration.name,
202
- providerId,
203
- version: integration.version,
204
- __spec: integration.__spec,
205
- __packageDir: integration.__packageDir,
206
- __manifestFile: integration.__manifestFile,
207
- ...(integration.__local ? {__local: true} : {}),
208
- ...(integration.__autolinked
209
- ? {__autolinked: true, __dependencyField: integration.__dependencyField}
210
- : {}),
211
- __providerConflict: {
212
- providerId,
213
- claimedBy: claimant.name,
214
- message:
215
- `${setAside} and ${winner} both claim provider ID "${providerId}". ` +
216
- `${winner} ${reason}; ${setAside} contributes nothing ` +
217
- 'until one package changes its providerId.',
218
- },
219
- };
131
+ return resolveProviders(
132
+ integrations.map(integration => ({
133
+ source: /** @type {const} */ ('configured'),
134
+ integration,
135
+ spec: integration?.__spec,
136
+ })),
137
+ ).integrations;
220
138
  }
221
139
 
222
140
  /**
@@ -253,6 +171,23 @@ function parseGapReportHandlerExport(value, label) {
253
171
  }
254
172
  }
255
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
+
256
191
  /**
257
192
  * Load and validate a manifest module's default export, while isolating the
258
193
  * optional `agentDocs` contribution from the manifest's other fields.
@@ -269,7 +204,7 @@ function parseGapReportHandlerExport(value, label) {
269
204
  * @param {string} file absolute manifest path
270
205
  * @param {string} [label] used in error messages
271
206
  * @param {{fresh?: boolean}} [options]
272
- * @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}>}
273
208
  */
274
209
  export async function loadManifest(
275
210
  file,
@@ -280,6 +215,7 @@ export async function loadManifest(
280
215
  const raw = mod?.default;
281
216
  const baseManifest = parseIntegrationBase(raw, label);
282
217
  const gapReport = parseGapReportHandlerExport(mod?.gapReport, label);
218
+ const discover = parseDiscoverSourceExport(mod?.discover, label);
283
219
  const hasAgentDocs =
284
220
  raw != null &&
285
221
  typeof raw === 'object' &&
@@ -314,6 +250,8 @@ export async function loadManifest(
314
250
  : undefined,
315
251
  gapReport: gapReport.handler,
316
252
  gapReportError: gapReport.error,
253
+ discover: discover.source,
254
+ discoverError: discover.error,
317
255
  agentDocsError,
318
256
  };
319
257
  }
@@ -431,6 +369,10 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
431
369
  let gapReportHandler;
432
370
  /** @type {string | undefined} */
433
371
  let gapReportError;
372
+ /** @type {import('../../authoring/discover/type').DiscoverSource | undefined} */
373
+ let discoverSource;
374
+ /** @type {string | undefined} */
375
+ let discoverError;
434
376
  /** @type {string | undefined} */
435
377
  let agentDocsError;
436
378
  try {
@@ -440,6 +382,8 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
440
382
  debug: debugHandler,
441
383
  gapReport: gapReportHandler,
442
384
  gapReportError,
385
+ discover: discoverSource,
386
+ discoverError,
443
387
  agentDocsError,
444
388
  } = await loadManifest(manifestFile, `Integration ${spec}`, {fresh}));
445
389
  } catch (err) {
@@ -483,6 +427,8 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
483
427
  __debug: debugHandler,
484
428
  __gapReport: gapReportHandler,
485
429
  __gapReportError: gapReportError,
430
+ __discover: discoverSource,
431
+ __discoverError: discoverError,
486
432
  __spec: spec,
487
433
  __packageDir: packageDir,
488
434
  __packageExports: pkg.exports ?? null,
@@ -534,6 +480,10 @@ export async function loadIntegrations(
534
480
  let gapReportHandler;
535
481
  /** @type {string | undefined} */
536
482
  let gapReportError;
483
+ /** @type {import('../../authoring/discover/type').DiscoverSource | undefined} */
484
+ let discoverSource;
485
+ /** @type {string | undefined} */
486
+ let discoverError;
537
487
  /** @type {string | undefined} */
538
488
  let agentDocsError;
539
489
  try {
@@ -543,6 +493,8 @@ export async function loadIntegrations(
543
493
  debug: debugHandler,
544
494
  gapReport: gapReportHandler,
545
495
  gapReportError,
496
+ discover: discoverSource,
497
+ discoverError,
546
498
  agentDocsError,
547
499
  } = await loadManifest(manifestFile, `Integration ${spec}`, {fresh}));
548
500
  } catch (err) {
@@ -593,6 +545,8 @@ export async function loadIntegrations(
593
545
  __debug: debugHandler,
594
546
  __gapReport: gapReportHandler,
595
547
  __gapReportError: gapReportError,
548
+ __discover: discoverSource,
549
+ __discoverError: discoverError,
596
550
  __spec: spec,
597
551
  __packageDir: packageDir,
598
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,275 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file The provider ledger property: over seeded, generated projects, the
5
+ * real Project.load and the real `upgrade` context account for every candidate
6
+ * exactly once, and agree on the winner of every provider ID except where the
7
+ * codemod policy says otherwise.
8
+ *
9
+ * The expected candidates come from the scenario description, never from the
10
+ * resolver. Fixtures live under a repo-local temp dir, not /tmp, because Vite
11
+ * refuses to dynamically import a module from outside the project root.
12
+ */
13
+
14
+ import {afterAll, beforeAll, describe, expect, it} from 'vitest';
15
+ import * as fs from 'node:fs';
16
+ import * as path from 'node:path';
17
+ import {Project, providerLedgerOf} from '../config/project.mjs';
18
+ import {loadProjectContext} from '../../api/upgrade/_adapter.mjs';
19
+ import {
20
+ expectedProjectInputs,
21
+ generateScenario,
22
+ isRunnable,
23
+ writeScenario,
24
+ } from '../../test-utils/provider-scenarios.mjs';
25
+
26
+ // 200 seeds keep this near 4 s; any seed range must hold.
27
+ const SEEDS = Array.from({length: 200}, (_, index) => index + 1);
28
+ const OUTCOMES = ['contributes', 'set-aside', 'load-failed', 'alias-of'];
29
+
30
+ /** @type {string} */
31
+ let root;
32
+ /** @type {string} */
33
+ let originalCwd;
34
+
35
+ beforeAll(() => {
36
+ originalCwd = process.cwd();
37
+ root = fs.mkdtempSync(path.join(process.cwd(), '.astryx-provider-ledger-'));
38
+ });
39
+
40
+ afterAll(() => {
41
+ process.chdir(originalCwd);
42
+ fs.rmSync(root, {recursive: true, force: true});
43
+ });
44
+
45
+ /**
46
+ * The contributing package for each provider ID. Fails when two contribute
47
+ * under one ID.
48
+ * @param {Map<string, any>} ledger
49
+ * @returns {Map<string, any>}
50
+ */
51
+ function winners(ledger) {
52
+ /** @type {Map<string, any>} */
53
+ const byProvider = new Map();
54
+ for (const entry of ledger.values()) {
55
+ if (entry.outcome !== 'contributes' || entry.providerId == null) continue;
56
+ expect(byProvider.has(entry.providerId)).toBe(false);
57
+ byProvider.set(entry.providerId, entry);
58
+ }
59
+ return byProvider;
60
+ }
61
+
62
+ /**
63
+ * Assert the ledger records one outcome for exactly the given inputs.
64
+ * @param {Map<string, any>} ledger
65
+ * @param {Array<{source: string, spec: string, key: string}>} inputs
66
+ */
67
+ function expectAccounted(ledger, inputs) {
68
+ const refs = [...ledger.values()].flatMap(entry =>
69
+ entry.refs.map(ref => ({entry, ref})),
70
+ );
71
+ for (const input of inputs) {
72
+ const holders = refs.filter(
73
+ ({ref}) => ref.source === input.source && ref.spec === input.spec,
74
+ );
75
+ expect(holders.map(({entry}) => entry.key)).toEqual([input.key]);
76
+ }
77
+ expect(refs).toHaveLength(inputs.length);
78
+ expect(new Set(ledger.keys())).toEqual(
79
+ new Set(inputs.map(input => input.key)),
80
+ );
81
+ for (const [key, entry] of ledger) {
82
+ expect(entry.key).toBe(key);
83
+ expect(OUTCOMES).toContain(entry.outcome);
84
+ if (entry.outcome === 'set-aside') {
85
+ expect(ledger.has(entry.winner)).toBe(true);
86
+ expect(entry.reason).toEqual(expect.any(String));
87
+ }
88
+ if (entry.outcome === 'alias-of') {
89
+ expect(ledger.has(entry.aliasOf)).toBe(true);
90
+ }
91
+ }
92
+ }
93
+
94
+ describe('provider ledger over generated projects', () => {
95
+ it('accounts for every candidate once and agrees across Project and upgrade', async () => {
96
+ const coverage = {
97
+ scenarios: 0,
98
+ setAside: 0,
99
+ aliasOf: 0,
100
+ loadFailed: 0,
101
+ replaced: 0,
102
+ agreed: 0,
103
+ standIn: 0,
104
+ extraReordered: 0,
105
+ };
106
+
107
+ for (const seed of SEEDS) {
108
+ const scenario = generateScenario(seed);
109
+ if (!isRunnable(scenario)) continue;
110
+ coverage.scenarios++;
111
+ const dir = path.join(root, `seed-${seed}`);
112
+ fs.mkdirSync(dir);
113
+ writeScenario(dir, scenario);
114
+ const context = `seed ${seed}: ${JSON.stringify(scenario)}`;
115
+
116
+ const project = await Project.load(dir, {fresh: true});
117
+ const ledger = providerLedgerOf(project);
118
+ const inputs = expectedProjectInputs(dir, scenario);
119
+ try {
120
+ expectAccounted(ledger, inputs);
121
+
122
+ // Nothing leaves the list without a recorded reason.
123
+ const listed = new Set(project.loadedIntegrations);
124
+ for (const integration of project.loadedIntegrations) {
125
+ expect(ledger.has(fs.realpathSync(integration.__packageDir))).toBe(
126
+ true,
127
+ );
128
+ }
129
+ for (const entry of ledger.values()) {
130
+ if (entry.integration != null) {
131
+ expect(listed.has(entry.integration)).toBe(true);
132
+ continue;
133
+ }
134
+ expect(entry.outcome).not.toBe('contributes');
135
+ if (entry.outcome === 'set-aside') {
136
+ expect(entry.reason).toBe('replaced-by-authored');
137
+ }
138
+ if (entry.outcome === 'load-failed') {
139
+ expect(entry.error).toEqual(expect.any(String));
140
+ }
141
+ }
142
+ } catch (error) {
143
+ throw new Error(`${context}\n${error}`, {cause: error});
144
+ }
145
+
146
+ for (const entry of ledger.values()) {
147
+ if (entry.outcome === 'set-aside') coverage.setAside++;
148
+ if (entry.outcome === 'alias-of') coverage.aliasOf++;
149
+ if (entry.outcome === 'load-failed') coverage.loadFailed++;
150
+ if (entry.reason === 'replaced-by-authored') coverage.replaced++;
151
+ }
152
+
153
+ // `--integration` specs resolve from the process cwd.
154
+ process.chdir(dir);
155
+ const upgrade = await loadProjectContext(dir, scenario.extras);
156
+ process.chdir(originalCwd);
157
+
158
+ const modules = path.join(dir, 'node_modules');
159
+ /** @param {string} spec */
160
+ const installedKey = spec =>
161
+ fs.realpathSync(path.join(modules, ...spec.split('/')));
162
+ /** @param {string} spec */
163
+ const installedName = spec =>
164
+ JSON.parse(
165
+ fs.readFileSync(
166
+ path.join(modules, ...spec.split('/'), 'package.json'),
167
+ 'utf8',
168
+ ),
169
+ ).name;
170
+ const configured = new Set(scenario.config ?? []);
171
+ const extras = [...new Set(scenario.extras)].filter(
172
+ spec => !configured.has(spec),
173
+ );
174
+ const {local} = scenario;
175
+ const localKey = fs.realpathSync(dir);
176
+ const selfListed = local != null && configured.has(local.name);
177
+ // The codemod policy: the installed copy stands in for the package being
178
+ // authored when it lists itself or is named with --integration.
179
+ const localStandsIn =
180
+ local != null &&
181
+ (selfListed || extras.some(spec => installedName(spec) === local.name));
182
+
183
+ try {
184
+ // Upgrade accounts for everything Project did, plus its own inputs.
185
+ expectAccounted(upgrade.ledger, [
186
+ ...inputs,
187
+ ...(selfListed
188
+ ? [
189
+ {
190
+ source: 'installed',
191
+ spec: local.name,
192
+ key: installedKey(local.name),
193
+ },
194
+ ]
195
+ : []),
196
+ ...extras.map(spec => ({
197
+ source: 'extra',
198
+ spec,
199
+ key: installedKey(spec),
200
+ })),
201
+ ]);
202
+ } catch (error) {
203
+ throw new Error(`${context}\n${error}`, {cause: error});
204
+ }
205
+
206
+ const projectWinners = winners(ledger);
207
+ const upgradeWinners = winners(upgrade.ledger);
208
+ for (const providerId of new Set([
209
+ ...projectWinners.keys(),
210
+ ...upgradeWinners.keys(),
211
+ ])) {
212
+ const inProject = projectWinners.get(providerId);
213
+ const inUpgrade = upgradeWinners.get(providerId);
214
+ const same =
215
+ inProject != null &&
216
+ inUpgrade != null &&
217
+ (inProject.key === inUpgrade.key ||
218
+ upgrade.ledger.get(inProject.key)?.aliasOf === inUpgrade.key);
219
+ if (same) {
220
+ coverage.agreed++;
221
+ continue;
222
+ }
223
+ // The one documented exception, asserted explicitly: an installed
224
+ // copy took the authored package's place, so either upgrade's winner
225
+ // is an installed copy of that package, or Project's winner is the
226
+ // authored package it replaced.
227
+ const upgradeName =
228
+ inUpgrade?.integration?.name ??
229
+ inUpgrade?.candidate.integration?.name;
230
+ const standInWins =
231
+ localStandsIn && inUpgrade != null && upgradeName === local?.name;
232
+ const localReplaced =
233
+ localStandsIn && inProject != null && inProject.key === localKey;
234
+ // Project never saw an extra, so an ID only an extra claims has no
235
+ // Project winner to agree with.
236
+ const extraOnly =
237
+ inProject == null && inUpgrade?.candidate.source === 'extra';
238
+ // Known disagreement, pinned by the `it.fails` repros in
239
+ // api/upgrade/provider-agreement.test.mjs: upgrade replaces an
240
+ // autolinked winner with any extra of the same name@version, from
241
+ // any directory, and orders it with the extras. Another extra can
242
+ // then win, or nothing does, in upgrade only.
243
+ const projectWinnerInUpgrade =
244
+ inProject == null ? undefined : upgrade.ledger.get(inProject.key);
245
+ const repeatedByExtra =
246
+ projectWinnerInUpgrade != null &&
247
+ (projectWinnerInUpgrade.refs.some(ref => ref.source === 'extra') ||
248
+ (projectWinnerInUpgrade.outcome === 'alias-of' &&
249
+ upgrade.ledger
250
+ .get(projectWinnerInUpgrade.aliasOf)
251
+ ?.refs.some(ref => ref.source === 'extra')));
252
+ const extraReordered =
253
+ inProject?.candidate.source === 'autolinked' && repeatedByExtra;
254
+ if (extraReordered) {
255
+ coverage.extraReordered++;
256
+ continue;
257
+ }
258
+ expect(
259
+ standInWins || localReplaced || extraOnly,
260
+ `${context}\nprovider ${providerId}: Project ${inProject?.label ?? 'none'} vs upgrade ${inUpgrade?.label ?? 'none'}`,
261
+ ).toBe(true);
262
+ if (standInWins || localReplaced) coverage.standIn++;
263
+ }
264
+ }
265
+
266
+ // The generator must keep reaching every shape, or the property is vacuous.
267
+ expect(coverage.scenarios).toBeGreaterThanOrEqual(190);
268
+ expect(coverage.setAside).toBeGreaterThan(0);
269
+ expect(coverage.aliasOf).toBeGreaterThan(0);
270
+ expect(coverage.loadFailed).toBeGreaterThan(0);
271
+ expect(coverage.replaced).toBeGreaterThan(0);
272
+ expect(coverage.agreed).toBeGreaterThan(0);
273
+ expect(coverage.standIn).toBeGreaterThan(0);
274
+ }, 120_000);
275
+ });