@astryxdesign/cli 0.6.3 → 0.6.4-canary.06c8fa3

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 (670) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/README.md +121 -85
  3. package/api/blog/blog.doc.mjs +1 -0
  4. package/api/build/_adapter.d.mts +50 -0
  5. package/api/build/_adapter.mjs +60 -0
  6. package/api/build/build.doc.mjs +16 -9
  7. package/api/build/build.test.mjs +197 -8
  8. package/api/build/build.type.d.mts +91 -2
  9. package/api/build/build.type.mjs +52 -8
  10. package/api/build/help/help.d.mts +12 -5
  11. package/api/build/help/help.mjs +69 -6
  12. package/api/build/kit/kit.d.mts +4 -1
  13. package/api/build/kit/kit.mjs +165 -49
  14. package/api/build/kit/rank.d.mts +44 -0
  15. package/api/build/kit/rank.mjs +432 -0
  16. package/api/build/kit/rank.test.mjs +196 -0
  17. package/api/component/_adapter.d.mts +31 -12
  18. package/api/component/_adapter.mjs +79 -15
  19. package/api/component/component.d.mts +6 -3
  20. package/api/component/component.doc.mjs +36 -13
  21. package/api/component/component.mjs +339 -22
  22. package/api/component/component.test.mjs +38 -0
  23. package/api/component/component.type.d.mts +47 -11
  24. package/api/component/component.type.mjs +76 -24
  25. package/api/component/detail/blocks/blocks.d.mts +2 -1
  26. package/api/component/detail/blocks/blocks.mjs +4 -3
  27. package/api/component/list/list.d.mts +0 -5
  28. package/api/component/list/list.mjs +40 -11
  29. package/api/discover/_adapter.d.mts +114 -6
  30. package/api/discover/_adapter.mjs +372 -17
  31. package/api/discover/_adapter.test.mjs +215 -0
  32. package/api/discover/_catalog-view.d.mts +115 -0
  33. package/api/discover/_catalog-view.mjs +203 -0
  34. package/api/discover/_catalog-view.test.mjs +128 -0
  35. package/api/discover/detail/detail.d.mts +18 -6
  36. package/api/discover/detail/detail.mjs +67 -13
  37. package/api/discover/detail/detail.test.mjs +85 -0
  38. package/api/discover/detail/item/item.d.mts +26 -0
  39. package/api/discover/detail/item/item.mjs +78 -0
  40. package/api/discover/detail/item/item.test.mjs +73 -0
  41. package/api/discover/discover.d.mts +3 -9
  42. package/api/discover/discover.doc.mjs +62 -18
  43. package/api/discover/discover.mjs +220 -36
  44. package/api/discover/discover.test.mjs +11 -2
  45. package/api/discover/discover.type.d.mts +150 -11
  46. package/api/discover/discover.type.mjs +107 -17
  47. package/api/discover/list/list.d.mts +20 -6
  48. package/api/discover/list/list.mjs +45 -12
  49. package/api/discover/list/list.test.mjs +46 -0
  50. package/api/discover/search/search.d.mts +18 -16
  51. package/api/discover/search/search.mjs +102 -56
  52. package/api/discover/search/search.test.mjs +144 -10
  53. package/api/docs/_adapter.d.mts +272 -41
  54. package/api/docs/_adapter.mjs +985 -108
  55. package/api/docs/compiled-topics.test.mjs +78 -0
  56. package/api/docs/detail/detail.mjs +22 -63
  57. package/api/docs/detail/section/section.d.mts +1 -1
  58. package/api/docs/detail/section/section.mjs +54 -19
  59. package/api/docs/detail/section/section.test.mjs +50 -0
  60. package/api/docs/docs.d.mts +10 -3
  61. package/api/docs/docs.doc.mjs +55 -16
  62. package/api/docs/docs.mjs +53 -10
  63. package/api/docs/docs.test.mjs +166 -4
  64. package/api/docs/docs.type.d.mts +221 -5
  65. package/api/docs/docs.type.mjs +153 -11
  66. package/api/docs/index/index.d.mts +18 -0
  67. package/api/docs/index/index.mjs +40 -0
  68. package/api/docs/index/index.test.mjs +62 -0
  69. package/api/docs/integration-tree.test.mjs +555 -0
  70. package/api/docs/integrationDocs.test.mjs +114 -8
  71. package/api/docs/list/list.mjs +28 -12
  72. package/api/docs/node/node.d.mts +43 -0
  73. package/api/docs/node/node.mjs +192 -0
  74. package/api/docs/reference-blocks.test.mjs +406 -0
  75. package/api/doctor/doctor.d.mts +104 -1
  76. package/api/doctor/doctor.doc.mjs +1 -0
  77. package/api/doctor/doctor.mjs +635 -7
  78. package/api/doctor/doctor.test.mjs +732 -11
  79. package/api/gap-report/gap-report.doc.mjs +8 -4
  80. package/api/hook/_adapter.mjs +19 -5
  81. package/api/hook/hook.doc.mjs +1 -0
  82. package/api/hook/hook.type.d.mts +3 -3
  83. package/api/hook/hook.type.mjs +11 -11
  84. package/api/hook/list/list.d.mts +2 -2
  85. package/api/hook/list/list.mjs +69 -17
  86. package/api/index.d.mts +2 -3
  87. package/api/index.mjs +5 -4
  88. package/api/init/init.doc.mjs +6 -1
  89. package/api/init/init.test.mjs +41 -1
  90. package/api/init/remove/remove.mjs +1 -1
  91. package/api/init/run/run.mjs +20 -10
  92. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  93. package/api/integration/add-contribution.d.mts +2 -1
  94. package/api/integration/add-contribution.mjs +130 -15
  95. package/api/integration/add-contribution.test.mjs +258 -7
  96. package/api/integration/add-helpers.d.mts +5 -2
  97. package/api/integration/add-helpers.mjs +36 -9
  98. package/api/integration/add-theme.mjs +34 -64
  99. package/api/integration/add-theme.test.mjs +105 -21
  100. package/api/integration/authoring-checks.mjs +138 -28
  101. package/api/integration/authoring-checks.test.mjs +179 -7
  102. package/api/integration/authoring-checks.type.mjs +6 -1
  103. package/api/integration/integration-authoring.type.d.mts +3 -1
  104. package/api/integration/integration-authoring.type.mjs +2 -0
  105. package/api/integration/integration-block-exports.test.mjs +10 -6
  106. package/api/integration/integrationAdd.doc.mjs +14 -4
  107. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  108. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  109. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  110. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  111. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  112. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  113. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  114. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  115. package/api/integration/integrationPackCheck.doc.mjs +2 -1
  116. package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
  117. package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
  118. package/api/integration/pack-check.lifecycle-output.test.mjs +105 -0
  119. package/api/integration/pack-check.mjs +111 -10
  120. package/api/integration/pack-check.test.mjs +387 -47
  121. package/api/integration/pack-check.type.d.mts +26 -2
  122. package/api/integration/pack-check.type.mjs +14 -1
  123. package/api/integration/summarizeIssues.doc.mjs +1 -0
  124. package/api/integration/template-conflict-compatibility.test.mjs +73 -0
  125. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  126. package/api/integration/validate-integration.mjs +52 -102
  127. package/api/integration/validate-integration.test.mjs +179 -26
  128. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  129. package/api/integration/validateIntegration.doc.mjs +3 -2
  130. package/api/json/assertResponse.doc.mjs +1 -0
  131. package/api/json/envelope-types.test.mjs +76 -0
  132. package/api/json/index.ts +2 -1
  133. package/api/json/isError.doc.mjs +1 -0
  134. package/api/json/parseResponse.doc.mjs +3 -2
  135. package/api/search/search-return-type.test.mjs +54 -0
  136. package/api/search/search.d.mts +62 -11
  137. package/api/search/search.doc.mjs +8 -2
  138. package/api/search/search.mjs +471 -83
  139. package/api/search/search.test.mjs +142 -1
  140. package/api/search/search.type.d.mts +15 -3
  141. package/api/search/search.type.mjs +5 -2
  142. package/api/swizzle/copy/copy.mjs +28 -11
  143. package/api/swizzle/swizzle.doc.mjs +2 -1
  144. package/api/swizzle/swizzle.type.d.mts +2 -2
  145. package/api/swizzle/swizzle.type.mjs +2 -2
  146. package/api/template/copy/copy.mjs +17 -23
  147. package/api/template/copy/copy.test.mjs +17 -0
  148. package/api/template/list/list.mjs +1 -0
  149. package/api/template/table-floating-bulk-actions.test.mjs +66 -0
  150. package/api/template/template-integration.test.mjs +1008 -3
  151. package/api/template/template-suffix.test.mjs +41 -21
  152. package/api/template/template.d.mts +1 -1
  153. package/api/template/template.doc.mjs +30 -8
  154. package/api/template/template.mjs +46 -9
  155. package/api/template/template.type.d.mts +12 -14
  156. package/api/template/template.type.mjs +15 -14
  157. package/api/theme/_adapter.d.mts +2 -3
  158. package/api/theme/_adapter.mjs +4 -5
  159. package/api/theme/add/add.binary.test.mjs +84 -0
  160. package/api/theme/add/add.mjs +31 -22
  161. package/api/theme/add/add.rollback.test.mjs +158 -0
  162. package/api/theme/add/add.staging.test.mjs +83 -0
  163. package/api/theme/add/add.test.mjs +14 -1
  164. package/api/theme/build/build.family.test.mjs +7 -12
  165. package/api/theme/build/build.mjs +140 -59
  166. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  167. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  168. package/api/theme/build/build.rollback.test.mjs +148 -0
  169. package/api/theme/build/build.test.mjs +127 -0
  170. package/api/theme/build/font-warning.mjs +3 -3
  171. package/api/theme/build/font-warning.test.mjs +5 -2
  172. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  173. package/api/theme/integration-themes.test.mjs +39 -28
  174. package/api/theme/list/list.test.mjs +19 -20
  175. package/api/theme/listThemes.doc.mjs +6 -5
  176. package/api/theme/palette/generate/generate.mjs +8 -3
  177. package/api/theme/palette/generate/generate.test.mjs +96 -0
  178. package/api/theme/palette/generate/generator.d.mts +10 -13
  179. package/api/theme/palette/generate/generator.mjs +15 -4
  180. package/api/theme/palette/generate/generator.test.mjs +10 -0
  181. package/api/theme/template/template.mjs +11 -2
  182. package/api/theme/template/template.test.mjs +20 -0
  183. package/api/theme/theme.type.d.mts +170 -11
  184. package/api/theme/theme.type.mjs +94 -27
  185. package/api/theme/themeAdd.doc.mjs +4 -3
  186. package/api/theme/themeBuild.doc.mjs +8 -4
  187. package/api/theme/themeList.doc.mjs +6 -3
  188. package/api/theme/themeListAvailable.doc.mjs +5 -3
  189. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  190. package/api/theme/themeTargets.doc.mjs +1 -0
  191. package/api/theme/themeTemplate.doc.mjs +6 -2
  192. package/api/upgrade/_adapter.d.mts +32 -5
  193. package/api/upgrade/_adapter.mjs +139 -22
  194. package/api/upgrade/list/list.mjs +2 -1
  195. package/api/upgrade/list/list.test.mjs +73 -0
  196. package/api/upgrade/project-context.test.mjs +272 -0
  197. package/api/upgrade/provider-agreement.test.mjs +152 -0
  198. package/api/upgrade/run/files-changed.test.mjs +111 -0
  199. package/api/upgrade/run/run.mjs +359 -60
  200. package/api/upgrade/status/status.mjs +2 -2
  201. package/api/upgrade/upgrade.doc.mjs +12 -5
  202. package/api/upgrade/upgrade.type.d.mts +43 -5
  203. package/api/upgrade/upgrade.type.mjs +29 -13
  204. package/assets/codemods/__tests__/registry.test.mjs +1 -0
  205. package/assets/codemods/__tests__/runner.test.mjs +332 -8
  206. package/assets/codemods/file-count.test.mjs +163 -0
  207. package/assets/codemods/integration-discovery.mjs +48 -4
  208. package/assets/codemods/integration-discovery.test.mjs +73 -0
  209. package/assets/codemods/integration-runner.mjs +59 -7
  210. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  211. package/assets/codemods/registry.mjs +1 -0
  212. package/assets/codemods/run-codemod.mjs +177 -34
  213. package/assets/codemods/runner.mjs +353 -104
  214. package/assets/codemods/term-log.mjs +32 -8
  215. package/assets/codemods/term-log.test.mjs +19 -1
  216. package/assets/codemods/transform-prop.mjs +109 -0
  217. package/assets/codemods/transform-prop.test.mjs +95 -0
  218. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  219. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  220. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  221. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  222. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  223. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  224. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  225. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  226. package/assets/codemods/transforms/v0.6.4/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  227. package/assets/codemods/transforms/v0.6.4/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  228. package/assets/codemods/transforms/v0.6.4/index.mjs +31 -0
  229. package/assets/codemods/transforms/v0.6.4/migrate-native-picker-to-presentation.mjs +148 -0
  230. package/assets/codemods/transforms/v0.6.4/migrate-theme-catalog-to-descriptors.mjs +141 -0
  231. package/assets/docs/README.md +9 -0
  232. package/assets/docs/authoring.doc.mjs +14 -0
  233. package/assets/docs/getting-started.doc.mjs +2 -2
  234. package/assets/docs/internationalization.doc.mjs +7 -5
  235. package/assets/docs/layout.doc.dense.mjs +2 -2
  236. package/assets/docs/layout.doc.mjs +1 -1
  237. package/assets/docs/principles.doc.mjs +6 -6
  238. package/assets/docs/styling-libraries.doc.mjs +4 -4
  239. package/assets/docs/styling.doc.mjs +4 -4
  240. package/assets/docs/theme.doc.mjs +5 -5
  241. package/assets/docs/tokens.doc.mjs +1 -1
  242. package/assets/docs/tree/api.doc.mjs +30 -0
  243. package/assets/docs/tree/cli.doc.mjs +23 -0
  244. package/assets/docs/tree/commands.doc.mjs +25 -0
  245. package/assets/docs/tree/component-lookups.doc.mjs +149 -0
  246. package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +144 -26
  247. package/assets/docs/tree/integrations.test.mjs +62 -0
  248. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  249. package/assets/docs/working-with-ai.doc.mjs +4 -4
  250. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
  251. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
  252. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  253. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  254. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  255. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  256. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  257. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  258. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  259. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  260. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  261. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  262. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  263. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  264. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  265. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  266. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  267. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  268. package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
  269. package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
  270. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
  271. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
  272. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  273. package/assets/templates/blocks/components/Timer/TimerFormats.doc.mjs +14 -0
  274. package/assets/templates/blocks/components/Timer/TimerFormats.tsx +34 -0
  275. package/assets/templates/blocks/components/Timer/TimerInline.doc.mjs +14 -0
  276. package/assets/templates/blocks/components/Timer/TimerInline.tsx +14 -0
  277. package/assets/templates/blocks/components/Timer/TimerShowcase.doc.mjs +13 -0
  278. package/assets/templates/blocks/components/Timer/TimerShowcase.tsx +47 -0
  279. package/assets/templates/blocks/components/Timer/TimerTypography.doc.mjs +14 -0
  280. package/assets/templates/blocks/components/Timer/TimerTypography.tsx +31 -0
  281. package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.doc.mjs +19 -3
  282. package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +383 -65
  283. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  284. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  285. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  286. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  287. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  288. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  289. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  290. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  291. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  292. package/authoring/_shared/contract.ts +22 -0
  293. package/authoring/codemod/codemod.doc.mjs +7 -2
  294. package/authoring/codemod/parse.d.mts +8 -8
  295. package/authoring/codemod/parse.mjs +8 -6
  296. package/authoring/codemod/type.ts +12 -0
  297. package/authoring/config/config.doc.mjs +11 -3
  298. package/authoring/config/debug-composition.test.mjs +92 -0
  299. package/authoring/config/parse.d.mts +15 -13
  300. package/authoring/config/parse.mjs +27 -8
  301. package/authoring/config/parse.test.mjs +8 -0
  302. package/authoring/config/type.ts +31 -8
  303. package/authoring/debug/debug.doc.d.mts +11 -0
  304. package/authoring/debug/debug.doc.mjs +182 -0
  305. package/authoring/debug/parse.d.mts +8 -8
  306. package/authoring/debug/parse.mjs +3 -3
  307. package/authoring/discover/discover.doc.d.mts +13 -0
  308. package/authoring/discover/discover.doc.mjs +138 -0
  309. package/authoring/discover/parse.d.mts +24 -0
  310. package/authoring/discover/parse.mjs +128 -0
  311. package/authoring/discover/parse.test.mjs +124 -0
  312. package/authoring/discover/type.ts +87 -0
  313. package/authoring/doctypes/_schema.d.mts +790 -23
  314. package/authoring/doctypes/_schema.mjs +543 -39
  315. package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
  316. package/authoring/doctypes/base/graph-fields.doc.mjs +64 -0
  317. package/authoring/doctypes/base/type.ts +41 -0
  318. package/authoring/doctypes/command/command.doc.mjs +5 -4
  319. package/authoring/doctypes/command/parse.d.mts +2 -2
  320. package/authoring/doctypes/command/parse.mjs +1 -1
  321. package/authoring/doctypes/command/type.ts +6 -5
  322. package/authoring/doctypes/component/component.doc.mjs +6 -3
  323. package/authoring/doctypes/component/parse.d.mts +2 -2
  324. package/authoring/doctypes/component/parse.mjs +1 -1
  325. package/authoring/doctypes/component/type.ts +6 -5
  326. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  327. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  328. package/authoring/doctypes/enum/parse.d.mts +2 -2
  329. package/authoring/doctypes/enum/parse.mjs +1 -1
  330. package/authoring/doctypes/enum/type.ts +4 -2
  331. package/authoring/doctypes/function/function.doc.mjs +7 -2
  332. package/authoring/doctypes/function/parse.d.mts +2 -2
  333. package/authoring/doctypes/function/parse.mjs +1 -1
  334. package/authoring/doctypes/function/type.ts +9 -4
  335. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  336. package/authoring/doctypes/hook/parse.d.mts +2 -2
  337. package/authoring/doctypes/hook/parse.mjs +1 -1
  338. package/authoring/doctypes/hook/type.ts +5 -4
  339. package/authoring/doctypes/legacy.d.mts +8 -6
  340. package/authoring/doctypes/legacy.mjs +5 -4
  341. package/authoring/doctypes/load-contract.test.mjs +233 -0
  342. package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
  343. package/authoring/doctypes/namespace/namespace.doc.mjs +128 -0
  344. package/authoring/doctypes/namespace/parse.d.mts +12 -0
  345. package/authoring/doctypes/namespace/parse.mjs +25 -0
  346. package/authoring/doctypes/namespace/parse.test.mjs +163 -0
  347. package/authoring/doctypes/namespace/type.ts +74 -0
  348. package/authoring/doctypes/parse.d.mts +22 -18
  349. package/authoring/doctypes/parse.mjs +22 -11
  350. package/authoring/doctypes/parse.test.mjs +77 -3
  351. package/authoring/doctypes/reference/parse.d.mts +2 -2
  352. package/authoring/doctypes/reference/parse.mjs +8 -5
  353. package/authoring/doctypes/reference/reference.doc.mjs +48 -6
  354. package/authoring/doctypes/reference/type.ts +70 -7
  355. package/authoring/doctypes/schema/parse.d.mts +2 -2
  356. package/authoring/doctypes/schema/parse.mjs +1 -1
  357. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  358. package/authoring/doctypes/schema/type.ts +4 -4
  359. package/authoring/doctypes/template/parse.d.mts +94 -1
  360. package/authoring/doctypes/template/parse.mjs +40 -2
  361. package/authoring/doctypes/template/parse.test.mjs +26 -2
  362. package/authoring/doctypes/template/template.doc.mjs +13 -3
  363. package/authoring/doctypes/template/type.ts +13 -2
  364. package/authoring/doctypes/theme/parse.d.mts +35 -0
  365. package/authoring/doctypes/theme/parse.mjs +76 -0
  366. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  367. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  368. package/authoring/doctypes/theme/type.ts +42 -0
  369. package/authoring/doctypes/types.ts +12 -10
  370. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  371. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  372. package/authoring/gap-report/parse.d.mts +10 -10
  373. package/authoring/gap-report/parse.mjs +6 -6
  374. package/authoring/gap-report/type.ts +1 -1
  375. package/authoring/identity/identity.doc.d.mts +9 -0
  376. package/authoring/identity/identity.doc.mjs +61 -0
  377. package/authoring/identity/type.ts +132 -0
  378. package/authoring/index.d.mts +3 -0
  379. package/authoring/index.d.ts +62 -17
  380. package/authoring/index.mjs +4 -1
  381. package/authoring/integration/integration.doc.mjs +15 -8
  382. package/authoring/integration/parse.d.mts +2 -2
  383. package/authoring/integration/parse.mjs +1 -1
  384. package/authoring/integration/parse.test.mjs +10 -1
  385. package/authoring/integration/schema.d.mts +6 -4
  386. package/authoring/integration/schema.mjs +9 -3
  387. package/authoring/integration/type.ts +19 -8
  388. package/authoring/shadcn/receipt.d.mts +6 -6
  389. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  390. package/clients/cli/command-load-failure.test.mjs +83 -0
  391. package/clients/cli/command-result-coverage.test.mjs +7 -7
  392. package/clients/cli/commands/blog.doc.mjs +1 -1
  393. package/clients/cli/commands/blog.mjs +23 -8
  394. package/clients/cli/commands/blog.test.mjs +42 -1
  395. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  396. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  397. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  398. package/clients/cli/commands/build-theme.mjs +16 -50
  399. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  400. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  401. package/clients/cli/commands/build.doc.mjs +16 -8
  402. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  403. package/clients/cli/commands/build.mjs +137 -114
  404. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  405. package/clients/cli/commands/build.text-fields.test.mjs +81 -0
  406. package/clients/cli/commands/component/index.mjs +153 -61
  407. package/clients/cli/commands/component-batch.test.mjs +341 -0
  408. package/clients/cli/commands/component-ownership.test.mjs +92 -3
  409. package/clients/cli/commands/component-package.test.mjs +46 -0
  410. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  411. package/clients/cli/commands/component.doc.mjs +24 -7
  412. package/clients/cli/commands/component.test.mjs +19 -0
  413. package/clients/cli/commands/debug-result-summary.test.mjs +2 -2
  414. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  415. package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
  416. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  417. package/clients/cli/commands/discover.doc.mjs +55 -9
  418. package/clients/cli/commands/discover.mjs +393 -118
  419. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  420. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  421. package/clients/cli/commands/docs.doc.mjs +28 -6
  422. package/clients/cli/commands/docs.mjs +240 -26
  423. package/clients/cli/commands/docs.test.mjs +222 -1
  424. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  425. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
  426. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  427. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  428. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  429. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  430. package/clients/cli/commands/doctor-integration.test.mjs +90 -8
  431. package/clients/cli/commands/doctor.doc.mjs +1 -1
  432. package/clients/cli/commands/doctor.mjs +59 -32
  433. package/clients/cli/commands/doctor.test.mjs +42 -0
  434. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  435. package/clients/cli/commands/gap-report.test.mjs +72 -0
  436. package/clients/cli/commands/hook/index.mjs +7 -17
  437. package/clients/cli/commands/hook.doc.mjs +1 -1
  438. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  439. package/clients/cli/commands/init.doc.mjs +20 -9
  440. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  441. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  442. package/clients/cli/commands/integration-add.doc.mjs +32 -6
  443. package/clients/cli/commands/integration-authoring.test.mjs +13 -9
  444. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  445. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  446. package/clients/cli/commands/integration.doc.mjs +1 -1
  447. package/clients/cli/commands/integration.mjs +1 -0
  448. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  449. package/clients/cli/commands/json-contract.test.mjs +33 -0
  450. package/clients/cli/commands/manifest.doc.mjs +1 -1
  451. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  452. package/clients/cli/commands/search.doc.mjs +7 -4
  453. package/clients/cli/commands/search.mjs +28 -9
  454. package/clients/cli/commands/search.test.mjs +75 -0
  455. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  456. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  457. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  458. package/clients/cli/commands/template.doc.mjs +52 -13
  459. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  460. package/clients/cli/commands/template.mjs +4 -91
  461. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  462. package/clients/cli/commands/text-json-parity.test.mjs +702 -0
  463. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  464. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  465. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  466. package/clients/cli/commands/theme-palette-generate.doc.mjs +9 -5
  467. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  468. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  469. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  470. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  471. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  472. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  473. package/clients/cli/commands/theme.doc.mjs +1 -1
  474. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  475. package/clients/cli/commands/upgrade.doc.mjs +22 -10
  476. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  477. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  478. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  479. package/clients/cli/commands/upgrade.mjs +29 -7
  480. package/clients/cli/formatters/index.mjs +164 -1
  481. package/clients/cli/formatters/index.test.mjs +97 -0
  482. package/clients/cli/index.mjs +21 -34
  483. package/clients/cli/latest-version-env.test.mjs +50 -0
  484. package/clients/cli/lib/cli-error.test.mjs +7 -0
  485. package/clients/cli/lib/component-format.mjs +9 -9
  486. package/clients/cli/lib/component-format.test.mjs +1 -1
  487. package/clients/cli/lib/define-command.mjs +32 -6
  488. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  489. package/clients/cli/lib/exit-codes.test.mjs +90 -0
  490. package/clients/cli/lib/hook-format.mjs +19 -10
  491. package/clients/cli/lib/json-shim.mjs +62 -16
  492. package/clients/cli/lib/json-shim.test.mjs +69 -0
  493. package/clients/cli/lib/manifest.d.ts +2 -0
  494. package/clients/cli/lib/manifest.mjs +39 -10
  495. package/clients/cli/lib/manifest.test.mjs +22 -2
  496. package/clients/cli/lib/parse-error-format.test.mjs +81 -0
  497. package/foundation/agent-docs/agent-docs.d.mts +7 -2
  498. package/foundation/agent-docs/agent-docs.mjs +82 -12
  499. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  500. package/foundation/agent-docs/agent-docs.test.mjs +19 -1
  501. package/foundation/config/integration-debug.test.mjs +28 -3
  502. package/foundation/config/project-themes.test.mjs +11 -19
  503. package/foundation/config/project.d.mts +20 -11
  504. package/foundation/config/project.mjs +263 -91
  505. package/foundation/config/project.test.mjs +270 -21
  506. package/foundation/discovery/authoring-self-docs.d.mts +87 -0
  507. package/foundation/discovery/authoring-self-docs.mjs +237 -0
  508. package/foundation/discovery/authoring-self-docs.test.mjs +170 -0
  509. package/foundation/discovery/authoring-surface.d.mts +74 -0
  510. package/foundation/discovery/authoring-surface.mjs +525 -0
  511. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  512. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  513. package/foundation/discovery/cli-self-docs.mjs +490 -0
  514. package/foundation/discovery/cli-self-docs.test.mjs +375 -0
  515. package/foundation/discovery/component-discovery.d.mts +39 -1
  516. package/foundation/discovery/component-discovery.mjs +50 -1
  517. package/foundation/discovery/component-loader.d.mts +35 -38
  518. package/foundation/discovery/component-loader.mjs +53 -222
  519. package/foundation/discovery/docs-discovery.d.mts +119 -11
  520. package/foundation/discovery/docs-discovery.mjs +423 -108
  521. package/foundation/discovery/docs-discovery.test.mjs +365 -20
  522. package/foundation/discovery/docs-output-budget.d.mts +28 -0
  523. package/foundation/discovery/docs-output-budget.mjs +50 -0
  524. package/foundation/discovery/docs-section-key.d.mts +116 -0
  525. package/foundation/discovery/docs-section-key.mjs +322 -0
  526. package/foundation/discovery/docs-section-key.test.mjs +246 -0
  527. package/foundation/discovery/template-adapter.d.mts +113 -11
  528. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  529. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  530. package/foundation/discovery/template-adapter.mjs +775 -84
  531. package/foundation/discovery/template-adapter.test.mjs +57 -0
  532. package/foundation/discovery/template-conflict-release.d.mts +13 -0
  533. package/foundation/discovery/template-conflict-release.mjs +40 -0
  534. package/foundation/discovery/template-conflict-release.test.mjs +40 -0
  535. package/foundation/discovery/theme-discovery.d.mts +67 -7
  536. package/foundation/discovery/theme-discovery.mjs +916 -186
  537. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  538. package/foundation/discovery/theming-targets.test.mjs +4 -0
  539. package/foundation/doc-compiler/bundle.d.mts +47 -0
  540. package/foundation/doc-compiler/bundle.mjs +278 -0
  541. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  542. package/foundation/doc-compiler/compile.d.mts +343 -0
  543. package/foundation/doc-compiler/compile.mjs +558 -0
  544. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  545. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  546. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  547. package/foundation/doc-compiler/doc-loads.test.mjs +1630 -0
  548. package/foundation/doc-compiler/import.d.mts +24 -0
  549. package/foundation/doc-compiler/import.mjs +59 -0
  550. package/foundation/doc-compiler/inputs.d.mts +102 -0
  551. package/foundation/doc-compiler/inputs.mjs +291 -0
  552. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  553. package/foundation/doc-compiler/ir.d.mts +22 -0
  554. package/foundation/doc-compiler/ir.mjs +471 -0
  555. package/foundation/doc-compiler/lenses.d.mts +36 -0
  556. package/foundation/doc-compiler/lenses.mjs +173 -0
  557. package/foundation/doc-compiler/links.d.mts +162 -0
  558. package/foundation/doc-compiler/links.mjs +294 -0
  559. package/foundation/doc-compiler/links.test.mjs +192 -0
  560. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  561. package/foundation/doc-compiler/overlays.d.mts +37 -0
  562. package/foundation/doc-compiler/overlays.mjs +206 -0
  563. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  564. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  565. package/foundation/doc-compiler/read.d.mts +127 -0
  566. package/foundation/doc-compiler/read.mjs +325 -0
  567. package/foundation/doc-compiler/read.test.mjs +313 -0
  568. package/foundation/doc-compiler/source.d.mts +33 -0
  569. package/foundation/doc-compiler/source.mjs +128 -0
  570. package/foundation/doc-compiler/tree.d.mts +288 -0
  571. package/foundation/doc-compiler/tree.mjs +876 -0
  572. package/foundation/doc-compiler/tree.test.mjs +606 -0
  573. package/foundation/fs/file-protection.d.mts +33 -0
  574. package/foundation/fs/file-protection.mjs +825 -0
  575. package/foundation/fs/file-protection.test.mjs +250 -0
  576. package/foundation/fs/module-loader.d.mts +1 -0
  577. package/foundation/fs/module-loader.mjs +50 -1
  578. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  579. package/foundation/fs/path-safety.d.mts +3 -2
  580. package/foundation/fs/path-safety.mjs +49 -19
  581. package/foundation/fs/path-safety.test.mjs +50 -0
  582. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  583. package/foundation/identity/provider-identity.d.mts +90 -0
  584. package/foundation/identity/provider-identity.mjs +320 -0
  585. package/foundation/identity/provider-identity.test.mjs +254 -0
  586. package/foundation/identity/providers.d.mts +7 -0
  587. package/foundation/identity/providers.mjs +16 -0
  588. package/foundation/integrations/autolink.d.mts +58 -1
  589. package/foundation/integrations/autolink.mjs +143 -45
  590. package/foundation/integrations/autolink.test.mjs +1 -1
  591. package/foundation/integrations/cli-requirement.d.mts +45 -0
  592. package/foundation/integrations/cli-requirement.mjs +154 -0
  593. package/foundation/integrations/cli-requirement.test.mjs +84 -0
  594. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  595. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  596. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  597. package/foundation/integrations/contribution-inventory.mjs +27 -24
  598. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  599. package/foundation/integrations/integration-warnings.d.mts +9 -2
  600. package/foundation/integrations/integration-warnings.mjs +52 -21
  601. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  602. package/foundation/integrations/integrations.d.mts +63 -3
  603. package/foundation/integrations/integrations.mjs +122 -9
  604. package/foundation/integrations/integrations.test.mjs +415 -1
  605. package/foundation/integrations/provider-conflicts.test.mjs +125 -0
  606. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  607. package/foundation/integrations/provider-resolution.d.mts +152 -0
  608. package/foundation/integrations/provider-resolution.mjs +576 -0
  609. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  610. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  611. package/foundation/integrations/theme-descriptor.mjs +44 -0
  612. package/foundation/integrations/validate-contributions.d.mts +2 -0
  613. package/foundation/integrations/validate-contributions.mjs +131 -29
  614. package/foundation/response/base.d.ts +8 -4
  615. package/foundation/response/batch.type.d.mts +33 -0
  616. package/foundation/response/batch.type.mjs +34 -0
  617. package/foundation/response/error-codes.d.mts +3 -1
  618. package/foundation/response/error-codes.d.ts +2 -0
  619. package/foundation/response/error-codes.doc.mjs +13 -4
  620. package/foundation/response/error-codes.mjs +8 -2
  621. package/foundation/response/error-codes.test.mjs +137 -10
  622. package/foundation/response/json-contract.test.mjs +57 -17
  623. package/foundation/response/json.d.mts +4 -2
  624. package/foundation/response/json.mjs +8 -10
  625. package/foundation/response/response-types.doc.d.mts +5 -1
  626. package/foundation/response/response-types.doc.mjs +46 -38
  627. package/foundation/response/response-types.doc.test.mjs +181 -0
  628. package/foundation/response/response.doc.mjs +1 -1
  629. package/foundation/text/string-utils.d.mts +8 -0
  630. package/foundation/text/string-utils.mjs +40 -10
  631. package/foundation/xle/browser.d.mts +3 -3
  632. package/foundation/xle/browser.mjs +3 -3
  633. package/foundation/xle/expand.d.mts +2 -0
  634. package/foundation/xle/expand.mjs +6 -5
  635. package/foundation/xle/expand.test.mjs +54 -0
  636. package/foundation/xle/parse.mjs +1 -1
  637. package/foundation/xle/print.mjs +2 -2
  638. package/foundation/xle/splice.mjs +1 -1
  639. package/foundation/xle/xle.test.mjs +13 -0
  640. package/package.json +10 -11
  641. package/api/layout/_adapter.d.mts +0 -34
  642. package/api/layout/_adapter.mjs +0 -133
  643. package/api/layout/check/check.d.mts +0 -16
  644. package/api/layout/check/check.mjs +0 -40
  645. package/api/layout/expand/expand.d.mts +0 -22
  646. package/api/layout/expand/expand.mjs +0 -153
  647. package/api/layout/grammar/grammar.d.mts +0 -13
  648. package/api/layout/grammar/grammar.mjs +0 -86
  649. package/api/layout/layout.d.mts +0 -6
  650. package/api/layout/layout.mjs +0 -17
  651. package/api/layout/layout.test.mjs +0 -297
  652. package/api/layout/layout.type.d.mts +0 -89
  653. package/api/layout/layout.type.mjs +0 -103
  654. package/api/layout/layoutCheck.doc.d.mts +0 -11
  655. package/api/layout/layoutCheck.doc.mjs +0 -84
  656. package/api/layout/layoutExpand.doc.d.mts +0 -11
  657. package/api/layout/layoutExpand.doc.mjs +0 -106
  658. package/api/layout/layoutGrammar.doc.d.mts +0 -11
  659. package/api/layout/layoutGrammar.doc.mjs +0 -56
  660. package/assets/templates/themes/manifest.json +0 -95
  661. package/clients/cli/commands/layout-check.doc.mjs +0 -54
  662. package/clients/cli/commands/layout-expand.doc.mjs +0 -66
  663. package/clients/cli/commands/layout-grammar.doc.mjs +0 -30
  664. package/clients/cli/commands/layout.doc.mjs +0 -34
  665. package/clients/cli/commands/layout.error-codes.test.mjs +0 -66
  666. package/clients/cli/commands/layout.exit-parity.test.mjs +0 -41
  667. package/clients/cli/commands/layout.mjs +0 -263
  668. package/clients/cli/lib/update-check.mjs +0 -83
  669. package/clients/cli/lib/update-check.test.mjs +0 -137
  670. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -0,0 +1,369 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Colocated tests for the provider resolver: one outcome per real package
5
+ * directory, precedence, and the wrappers that keep their old results.
6
+ *
7
+ * Fixtures live under a repo-local temp dir, not /tmp, because Vite refuses to
8
+ * dynamically import a module from outside the project root.
9
+ */
10
+
11
+ import {afterEach, beforeEach, describe, expect, it} from 'vitest';
12
+ import * as fs from 'node:fs';
13
+ import * as path from 'node:path';
14
+ import {packageKey, resolveProviders} from './provider-resolution.mjs';
15
+ import {markProviderConflicts} from './integrations.mjs';
16
+ import {autolinkIntegrations} from './autolink.mjs';
17
+ import {Project, providerLedgerOf} from '../config/project.mjs';
18
+
19
+ let tmpDir;
20
+
21
+ beforeEach(() => {
22
+ tmpDir = fs.mkdtempSync(
23
+ path.join(process.cwd(), '.astryx-provider-resolution-'),
24
+ );
25
+ });
26
+
27
+ afterEach(() => {
28
+ fs.rmSync(tmpDir, {recursive: true, force: true});
29
+ });
30
+
31
+ /**
32
+ * A loaded-integration record in a real directory.
33
+ * @param {string} dir directory under the temp root
34
+ * @param {Record<string, unknown>} fields
35
+ * @returns {any}
36
+ */
37
+ function record(dir, fields) {
38
+ const packageDir = path.join(tmpDir, dir);
39
+ fs.mkdirSync(packageDir, {recursive: true});
40
+ return {
41
+ providerId: fields.name,
42
+ __spec: fields.name,
43
+ __packageDir: packageDir,
44
+ __manifestFile: path.join(packageDir, 'astryx.integration.mjs'),
45
+ ...fields,
46
+ };
47
+ }
48
+
49
+ /**
50
+ * @param {string} source
51
+ * @param {any} integration
52
+ */
53
+ const candidate = (source, integration) => ({
54
+ source,
55
+ integration,
56
+ spec: integration.__spec,
57
+ });
58
+
59
+ /** @param {Map<string, any>} ledger */
60
+ function outcomes(ledger) {
61
+ return [...ledger.values()].map(entry => [entry.label, entry.outcome]);
62
+ }
63
+
64
+ describe('resolveProviders ledger', () => {
65
+ it('records one outcome for every candidate, keyed by real directory', () => {
66
+ const widgets = record('widgets', {
67
+ name: '@acme/widgets',
68
+ version: '1.0.0',
69
+ });
70
+ const renamed = record('renamed', {
71
+ name: '@acme/renamed',
72
+ version: '2.0.0',
73
+ providerId: '@acme/widgets',
74
+ });
75
+ const broken = record('broken', {
76
+ name: '@acme/broken',
77
+ version: '1.0.0',
78
+ __loadError: 'boom',
79
+ });
80
+ const {integrations, ledger} = resolveProviders([
81
+ candidate('configured', widgets),
82
+ candidate('configured', renamed),
83
+ candidate('configured', broken),
84
+ ]);
85
+
86
+ expect([...ledger.keys()]).toEqual(
87
+ [widgets, renamed, broken].map(entry => packageKey(entry.__packageDir)),
88
+ );
89
+ expect(outcomes(ledger)).toEqual([
90
+ ['@acme/widgets@1.0.0', 'contributes'],
91
+ ['@acme/renamed@2.0.0', 'set-aside'],
92
+ ['@acme/broken@1.0.0', 'load-failed'],
93
+ ]);
94
+ const setAside = ledger.get(packageKey(renamed.__packageDir));
95
+ expect(setAside).toMatchObject({
96
+ winner: packageKey(widgets.__packageDir),
97
+ reason: 'claimed-earlier',
98
+ integration: integrations[1],
99
+ });
100
+ expect(integrations[1].__providerConflict.claimedBy).toBe('@acme/widgets');
101
+ });
102
+
103
+ it('keeps two packages that share a name apart', () => {
104
+ const old = record('widgets-old', {
105
+ name: '@acme/widgets',
106
+ version: '1.0.0',
107
+ __spec: 'widgets-old',
108
+ });
109
+ const next = record('widgets-next', {
110
+ name: '@acme/widgets',
111
+ version: '2.0.0',
112
+ __spec: 'widgets-next',
113
+ });
114
+ const {ledger} = resolveProviders([
115
+ candidate('configured', old),
116
+ candidate('configured', next),
117
+ ]);
118
+
119
+ expect(outcomes(ledger)).toEqual([
120
+ ['@acme/widgets@1.0.0', 'contributes'],
121
+ ['@acme/widgets@2.0.0', 'set-aside'],
122
+ ]);
123
+ });
124
+
125
+ it('folds every spelling of one real directory into one entry', () => {
126
+ const ui = record('ui', {name: '@acme/ui', version: '0.1.22'});
127
+ const link = path.join(tmpDir, 'legacy-ui');
128
+ fs.symlinkSync(ui.__packageDir, link, 'dir');
129
+ const legacy = {...ui, __spec: '@acme/legacy-ui', __packageDir: link};
130
+ const {integrations, ledger} = resolveProviders([
131
+ candidate('configured', ui),
132
+ candidate('configured', legacy),
133
+ ]);
134
+
135
+ expect(integrations).toEqual([ui]);
136
+ expect([...ledger.keys()]).toEqual([packageKey(ui.__packageDir)]);
137
+ const [entry] = ledger.values();
138
+ expect(entry.outcome).toBe('contributes');
139
+ expect(entry.refs.map(ref => ref.spec)).toEqual([
140
+ '@acme/ui',
141
+ '@acme/legacy-ui',
142
+ ]);
143
+ });
144
+
145
+ it('records an autolinked copy of a loaded package as alias-of it', () => {
146
+ const ui = record('ui', {name: '@acme/ui', version: '0.1.22'});
147
+ const copy = record('legacy-ui', {
148
+ name: '@acme/ui',
149
+ version: '0.1.22',
150
+ __spec: '@acme/legacy-ui',
151
+ __autolinked: true,
152
+ });
153
+ const {integrations, ledger} = resolveProviders([
154
+ candidate('configured', ui),
155
+ candidate('autolinked', copy),
156
+ ]);
157
+
158
+ expect(integrations).toEqual([ui]);
159
+ expect(ledger.get(packageKey(copy.__packageDir))).toMatchObject({
160
+ outcome: 'alias-of',
161
+ aliasOf: packageKey(ui.__packageDir),
162
+ });
163
+ });
164
+
165
+ it('records an autolinked package that failed to load, and lists it nowhere', () => {
166
+ const packageDir = path.join(tmpDir, 'unreadable');
167
+ const {integrations, ledger} = resolveProviders([
168
+ {
169
+ source: 'autolinked',
170
+ spec: '@acme/unreadable',
171
+ packageDir,
172
+ error: 'bad json',
173
+ },
174
+ ]);
175
+
176
+ expect(integrations).toEqual([]);
177
+ expect(ledger.get(packageKey(packageDir))).toMatchObject({
178
+ outcome: 'load-failed',
179
+ error: 'bad json',
180
+ });
181
+ });
182
+
183
+ it('lets the package being authored replace its installed copy and claim first', () => {
184
+ const installed = record('installed', {
185
+ name: '@acme/widgets',
186
+ version: '1.0.0',
187
+ });
188
+ const rival = record('rival', {
189
+ name: '@acme/rival',
190
+ version: '1.0.0',
191
+ providerId: '@acme/widgets',
192
+ });
193
+ const local = record('local', {
194
+ name: '@acme/widgets',
195
+ version: '2.0.0-dev',
196
+ __local: true,
197
+ });
198
+ const {integrations, ledger} = resolveProviders([
199
+ candidate('configured', rival),
200
+ candidate('configured', installed),
201
+ candidate('local', local),
202
+ ]);
203
+
204
+ expect(integrations.map(entry => entry.name)).toEqual([
205
+ '@acme/rival',
206
+ '@acme/widgets',
207
+ ]);
208
+ expect(integrations[1]).toBe(local);
209
+ expect(ledger.get(packageKey(installed.__packageDir))).toMatchObject({
210
+ outcome: 'set-aside',
211
+ reason: 'replaced-by-authored',
212
+ winner: packageKey(local.__packageDir),
213
+ });
214
+ expect(ledger.get(packageKey(rival.__packageDir))).toMatchObject({
215
+ outcome: 'set-aside',
216
+ reason: 'authored-claims',
217
+ winner: packageKey(local.__packageDir),
218
+ });
219
+ });
220
+
221
+ it('keeps configured precedence ahead of autolinked', () => {
222
+ const configured = record('configured', {
223
+ name: '@acme/one',
224
+ version: '1.0.0',
225
+ });
226
+ const autolinked = record('autolinked', {
227
+ name: '@acme/two',
228
+ version: '1.0.0',
229
+ providerId: '@acme/one',
230
+ __autolinked: true,
231
+ });
232
+ const {ledger} = resolveProviders([
233
+ candidate('configured', configured),
234
+ candidate('autolinked', autolinked),
235
+ ]);
236
+
237
+ expect(outcomes(ledger)).toEqual([
238
+ ['@acme/one@1.0.0', 'contributes'],
239
+ ['@acme/two@1.0.0', 'set-aside'],
240
+ ]);
241
+ });
242
+
243
+ it('under the codemod policy, records the installed copy standing in', () => {
244
+ const local = record('local', {
245
+ name: '@acme/widgets',
246
+ version: '2.0.0-dev',
247
+ __local: true,
248
+ });
249
+ const installed = record('installed', {
250
+ name: '@acme/widgets',
251
+ version: '1.0.0',
252
+ });
253
+ const {integrations, ledger} = resolveProviders(
254
+ [candidate('configured', local), candidate('installed', installed)],
255
+ {codemods: true},
256
+ );
257
+
258
+ expect(integrations).toEqual([installed]);
259
+ expect(ledger.get(packageKey(local.__packageDir))).toMatchObject({
260
+ outcome: 'set-aside',
261
+ reason: 'installed-stands-in',
262
+ winner: packageKey(installed.__packageDir),
263
+ });
264
+ });
265
+ });
266
+
267
+ describe('markProviderConflicts', () => {
268
+ const a = {name: 'a', version: '1', providerId: 'x', __spec: 'a'};
269
+ const b = {name: 'b', version: '1', providerId: 'x', __spec: 'b'};
270
+ const alias = {name: 'a', version: '1', providerId: 'x', __spec: 'a-alias'};
271
+ const local = {
272
+ name: 'l',
273
+ version: '1',
274
+ providerId: 'x',
275
+ __spec: 'l',
276
+ __local: true,
277
+ };
278
+ /** @param {any[]} list */
279
+ const claimsOf = list =>
280
+ markProviderConflicts(list).map(entry => [
281
+ entry?.name ?? null,
282
+ entry?.__providerConflict?.claimedBy ?? null,
283
+ ]);
284
+
285
+ it('drops an alias of the winner and keeps a record listed twice', () => {
286
+ expect(claimsOf([a, b, alias, a, undefined])).toEqual([
287
+ ['a', null],
288
+ ['b', 'a'],
289
+ ['a', null],
290
+ [null, null],
291
+ ]);
292
+ });
293
+
294
+ it('lets the package being authored claim first', () => {
295
+ expect(claimsOf([a, undefined, b, alias, a, local])).toEqual([
296
+ ['a', 'l'],
297
+ [null, null],
298
+ ['b', 'l'],
299
+ ['a', 'l'],
300
+ ['a', 'l'],
301
+ ['l', null],
302
+ ]);
303
+ });
304
+ });
305
+
306
+ describe('Project.load keeps a ledger', () => {
307
+ /**
308
+ * @param {string} dir node_modules key
309
+ * @param {{name: string, version: string}} pkg
310
+ */
311
+ function install(dir, pkg) {
312
+ const pkgDir = path.join(tmpDir, 'node_modules', ...dir.split('/'));
313
+ fs.mkdirSync(pkgDir, {recursive: true});
314
+ fs.writeFileSync(path.join(pkgDir, 'package.json'), JSON.stringify(pkg));
315
+ fs.writeFileSync(
316
+ path.join(pkgDir, 'astryx.integration.mjs'),
317
+ 'export default {};\n',
318
+ );
319
+ return pkgDir;
320
+ }
321
+
322
+ it('records the autolink alias it drops as alias-of the loaded copy', async () => {
323
+ fs.writeFileSync(
324
+ path.join(tmpDir, 'package.json'),
325
+ JSON.stringify({
326
+ name: 'consumer',
327
+ dependencies: {
328
+ '@acme/legacy-ui': 'npm:@acme/ui@0.1.22',
329
+ '@acme/ui': '0.1.22',
330
+ },
331
+ }),
332
+ );
333
+ const legacy = install('@acme/legacy-ui', {
334
+ name: '@acme/ui',
335
+ version: '0.1.22',
336
+ });
337
+ const ui = install('@acme/ui', {name: '@acme/ui', version: '0.1.22'});
338
+
339
+ const project = await Project.load(tmpDir, {fresh: true});
340
+ expect(project.loadedIntegrations.map(entry => entry.__spec)).toEqual([
341
+ '@acme/legacy-ui',
342
+ ]);
343
+ const ledger = providerLedgerOf(project);
344
+ expect(ledger.get(packageKey(ui))).toMatchObject({
345
+ outcome: 'alias-of',
346
+ aliasOf: packageKey(legacy),
347
+ });
348
+ expect(await autolinkIntegrations({projectDir: tmpDir})).toHaveLength(1);
349
+ });
350
+
351
+ it('records a dependency key that repeats a configured package', async () => {
352
+ fs.writeFileSync(
353
+ path.join(tmpDir, 'package.json'),
354
+ JSON.stringify({name: 'consumer', dependencies: {'@acme/ui': '0.1.22'}}),
355
+ );
356
+ fs.writeFileSync(
357
+ path.join(tmpDir, 'astryx.config.mjs'),
358
+ "export default {integrations: ['@acme/ui']};\n",
359
+ );
360
+ const ui = install('@acme/ui', {name: '@acme/ui', version: '0.1.22'});
361
+
362
+ const ledger = providerLedgerOf(await Project.load(tmpDir, {fresh: true}));
363
+ expect([...ledger.keys()]).toEqual([packageKey(ui)]);
364
+ expect(ledger.get(packageKey(ui))?.refs.map(ref => ref.source)).toEqual([
365
+ 'configured',
366
+ 'autolinked',
367
+ ]);
368
+ });
369
+ });
@@ -0,0 +1,8 @@
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
+ * @param {import('../../authoring/doctypes/theme/type.js').ThemeDoc} doc
6
+ * @returns {string}
7
+ */
8
+ export function themeDescriptorSource(doc: import("../../authoring/doctypes/theme/type.js").ThemeDoc): string;
@@ -0,0 +1,44 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file The source text of a typed integration theme descriptor.
5
+ *
6
+ * @input A theme's descriptor fields.
7
+ * @output The `.doc.mjs` source that declares them under their ThemeDoc type.
8
+ * @position Shared by `integration add theme`, which scaffolds a descriptor,
9
+ * and the codemod that turns a 0.6 theme catalog into descriptors, so both
10
+ * write the same bytes.
11
+ */
12
+
13
+ /**
14
+ * A single-quoted JavaScript string literal for any text.
15
+ * @param {string} value
16
+ */
17
+ function quote(value) {
18
+ const escaped = value
19
+ .replace(/\\/gu, '\\\\')
20
+ .replace(/'/gu, "\\'")
21
+ .replace(/\n/gu, '\\n')
22
+ .replace(/\r/gu, '\\r')
23
+ .replace(/\u2028/gu, '\\u2028')
24
+ .replace(/\u2029/gu, '\\u2029');
25
+ return `'${escaped}'`;
26
+ }
27
+
28
+ /**
29
+ * @param {import('../../authoring/doctypes/theme/type.js').ThemeDoc} doc
30
+ * @returns {string}
31
+ */
32
+ export function themeDescriptorSource(doc) {
33
+ return [
34
+ "/** @type {import('@astryxdesign/cli/authoring').ThemeDoc} */",
35
+ 'export default {',
36
+ " type: 'theme',",
37
+ ` name: ${quote(doc.name)},`,
38
+ ` displayName: ${quote(doc.displayName)},`,
39
+ ` description: ${quote(doc.description)},`,
40
+ ` maintained: ${doc.maintained},`,
41
+ '};',
42
+ '',
43
+ ].join('\n');
44
+ }
@@ -22,5 +22,7 @@ export function validateLoadedIntegration(loaded: LoadedIntegration): Promise<Is
22
22
  */
23
23
  /** Stable issue code for an invalid optional agent-doc contribution. */
24
24
  export const INVALID_AGENT_DOCS: "invalid_agent_docs";
25
+ /** Stable issue code for a package whose provider ID is already claimed. */
26
+ export const DUPLICATE_PROVIDER: "duplicate_provider";
25
27
  export type Issue = import("./issue").AstryxIntegrationIssue;
26
28
  export type LoadedIntegration = import("./integrations.mjs").LoadedIntegration;
@@ -25,6 +25,23 @@ import * as fs from 'node:fs';
25
25
  import * as path from 'node:path';
26
26
  import {isValidSemver} from '../env/semver.mjs';
27
27
  import {findSourceOnlyCandidates} from './contribution-inventory.mjs';
28
+ import {
29
+ CODEMOD_FILE_RE,
30
+ CODEMOD_SKIP_DIRS,
31
+ CODEMOD_TEST_RE,
32
+ createFixContext,
33
+ DOC_CANDIDATE_RE,
34
+ heldRootFix,
35
+ newComponentDocNote,
36
+ notACodemodFix,
37
+ notAComponentFix,
38
+ readContributionStamp,
39
+ sharedCodemodsRootFix,
40
+ stampOf,
41
+ themeImporting,
42
+ TEMPLATE_CANDIDATE_RE,
43
+ } from './contribution-fixes.mjs';
44
+ import {MANIFEST_BASENAMES} from './integrations.mjs';
28
45
  import {discoverIntegrationCodemods} from '../../assets/codemods/integration-discovery.mjs';
29
46
  import {discoverIntegrationTemplatesForOne} from '../discovery/template-adapter.mjs';
30
47
  import * as componentDiscovery from '../discovery/component-discovery.mjs';
@@ -39,6 +56,9 @@ import {discoverIntegrationThemes} from '../discovery/theme-discovery.mjs';
39
56
  /** Stable issue code for an invalid optional agent-doc contribution. */
40
57
  export const INVALID_AGENT_DOCS = 'invalid_agent_docs';
41
58
 
59
+ /** Stable issue code for a package whose provider ID is already claimed. */
60
+ export const DUPLICATE_PROVIDER = 'duplicate_provider';
61
+
42
62
  /** @param {string} code @param {string} message @returns {Issue} */
43
63
  export function issueError(code, message) {
44
64
  return {code, severity: 'error', message};
@@ -116,32 +136,82 @@ function checkRoots(resolved, issues) {
116
136
  */
117
137
  async function checkCodemods(integration, issues) {
118
138
  if (!integration.codemods || !fs.existsSync(integration.codemods)) return;
139
+ const context = integration.__packageDir
140
+ ? createFixContext(integration.__packageDir, integration)
141
+ : null;
142
+ const shared = context && sharedCodemodsRootFix(context);
119
143
  for (const entry of fs.readdirSync(integration.codemods, {
120
144
  withFileTypes: true,
121
145
  })) {
122
146
  if (
123
147
  entry.isFile() &&
124
- /\.(?:ts|mjs|js)$/u.test(entry.name) &&
125
- !/\.(?:test|spec|fixture)\.(?:ts|mjs|js)$/u.test(entry.name)
148
+ CODEMOD_FILE_RE.test(entry.name) &&
149
+ !CODEMOD_TEST_RE.test(entry.name) &&
150
+ // The manifest sits beside package.json and is never a codemod.
151
+ !(
152
+ integration.codemods === integration.__packageDir &&
153
+ MANIFEST_BASENAMES.includes(entry.name)
154
+ )
126
155
  ) {
156
+ const shown = path
157
+ .relative(
158
+ integration.__packageDir ?? path.dirname(integration.codemods),
159
+ path.join(integration.codemods, entry.name),
160
+ )
161
+ .split(path.sep)
162
+ .join('/');
163
+ const root = path.dirname(shown);
164
+ const full = path.join(integration.codemods, entry.name);
165
+ const stamp =
166
+ context &&
167
+ (DOC_CANDIDATE_RE.test(entry.name) ||
168
+ TEMPLATE_CANDIDATE_RE.test(entry.name))
169
+ ? stampOf(context, full)
170
+ : null;
171
+ // A theme's entry module may sit beside its descriptor.
172
+ const themeDoc = ['.doc.mjs', '.doc.ts', '.doc.js']
173
+ .map(suffix => full.replace(/\.(?:ts|mjs|js)$/u, suffix))
174
+ .find(candidate => candidate !== full && fs.existsSync(candidate));
175
+ const themeStamp =
176
+ context && !stamp && themeDoc ? stampOf(context, themeDoc) : null;
177
+ let fix = `Fix: move it into the folder named for the version it migrates to, for example ${root}/1.2.0/${entry.name}.`;
178
+ if (shared) fix = sharedCodemodsRootFix(context, entry.name) ?? fix;
179
+ else if (context && stamp) fix = notACodemodFix(context, full, stamp);
180
+ else if (context && themeDoc && themeStamp?.type === 'theme') {
181
+ fix = notACodemodFix(context, themeDoc, themeStamp, entry.name);
182
+ } else if (context) {
183
+ const owner = themeImporting(context, full);
184
+ if (owner) {
185
+ fix = notACodemodFix(
186
+ context,
187
+ owner.doc,
188
+ owner.stamp,
189
+ owner.source,
190
+ entry.name,
191
+ );
192
+ }
193
+ }
127
194
  issues.push(
128
195
  issueWarning(
129
196
  'codemod_outside_version',
130
- `Codemod file "${path.join(integration.codemods, entry.name)}" is outside a version folder, so upgrade will never load it.`,
197
+ `Codemod file "${shown}" is outside a version folder, so upgrade will never load it. ${fix}`,
131
198
  ),
132
199
  );
133
200
  }
134
201
  if (
135
202
  entry.isDirectory() &&
136
- !['node_modules', '.git', '__tests__', '__fixtures__'].includes(
137
- entry.name,
138
- ) &&
203
+ !CODEMOD_SKIP_DIRS.has(entry.name) &&
139
204
  !isValidSemver(entry.name)
140
205
  ) {
206
+ const fix =
207
+ shared ??
208
+ (context &&
209
+ heldRootFix(context, path.join(integration.codemods, entry.name))) ??
210
+ 'Fix: rename it to the exact version its codemods migrate to.';
141
211
  issues.push(
142
212
  issueError(
143
213
  'invalid_codemod_version',
144
- `Codemod folder "${entry.name}" is not an exact semver version such as 1.2.0.`,
214
+ `Codemod folder "${entry.name}" is not an exact semver version such as 1.2.0. ${fix}`,
145
215
  ),
146
216
  );
147
217
  }
@@ -166,7 +236,11 @@ async function checkTemplates(integration, issues) {
166
236
  try {
167
237
  const {errors} = await discoverIntegrationTemplatesForOne(integration);
168
238
  for (const e of errors) {
169
- issues.push(issueError('invalid_template', e.message));
239
+ issues.push({
240
+ code: e.code ?? 'invalid_template',
241
+ severity: e.severity ?? 'error',
242
+ message: e.message,
243
+ });
170
244
  }
171
245
  } catch (err) {
172
246
  issues.push(
@@ -176,41 +250,62 @@ async function checkTemplates(integration, issues) {
176
250
  }
177
251
 
178
252
  /**
179
- * Validate the integration's components via the landed ownership discovery.
180
- * Feature-detected: if the component-ownership export isn't present in this
181
- * build (sibling PR not yet merged), component validation is skipped rather
182
- * than hard-failing.
183
- *
184
- * `discoverIntegrationComponents` returns ownership records and does not throw
185
- * on a missing same-stem source — it records `sourcePath: null`. We surface
186
- * each such record as an `invalid_component` error.
253
+ * Validate the integration's components through the same load-and-parse boundary
254
+ * that component detail uses. Missing source and invalid metadata are reported
255
+ * per component so valid siblings remain available.
187
256
  * @param {LoadedIntegration} integration loaded-integration-shaped object
188
257
  * @param {Issue[]} issues
189
258
  */
190
259
  async function checkComponents(integration, issues) {
191
260
  if (!integration.components || !fs.existsSync(integration.components)) return;
192
- const discover = componentDiscovery.discoverIntegrationComponents;
261
+ const discover = componentDiscovery.discoverValidIntegrationComponents;
193
262
  if (typeof discover !== 'function') return; // feature not present yet
194
263
  try {
195
- const records = (await discover(integration)) ?? [];
196
- for (const record of records) {
197
- if (record?.sourcePath == null) {
198
- issues.push(
199
- issueError(
200
- 'invalid_component',
201
- `Component "${record?.name}" is missing its same-stem source file ${record?.name}.tsx.`,
202
- ),
203
- );
264
+ const {discovered, errors} = await discover(integration);
265
+ /** @type {import('./contribution-fixes.mjs').FixContext | undefined} */
266
+ let context;
267
+ const byName = new Map(discovered.map(record => [record.name, record]));
268
+ for (const error of errors) {
269
+ const record = byName.get(error.name);
270
+ if (record == null || record.sourcePath != null) {
271
+ issues.push(issueError('invalid_component', error.message));
272
+ continue;
204
273
  }
274
+ const docPath = record.docPath;
275
+ let fix = `Fix: add ${record.name}.tsx beside ${docPath ? path.basename(docPath) : `${record.name}.doc.mjs`}.`;
276
+ const stamp = docPath ? readContributionStamp(docPath, false) : null;
277
+ if (stamp && stamp.type !== 'component' && integration.__packageDir) {
278
+ context ??= createFixContext(integration.__packageDir, integration);
279
+ fix = notAComponentFix(context, docPath, stamp);
280
+ }
281
+ issues.push(issueError('invalid_component', `${error.message} ${fix}`));
205
282
  }
283
+ const overlap = integration.__packageDir
284
+ ? newComponentDocNote(
285
+ (context ??= createFixContext(integration.__packageDir, integration)),
286
+ )
287
+ : '';
206
288
  for (const name of findSourceOnlyCandidates(
207
289
  integration.components,
208
- records.map(record => record.name),
290
+ discovered.map(record => record.name),
209
291
  )) {
292
+ // A hidden doc still pairs with its source; discovery just skips it.
293
+ if (
294
+ ['.doc.ts', '.doc.mjs', '.doc.js'].some(suffix =>
295
+ fs.existsSync(
296
+ path.join(
297
+ /** @type {string} */ (integration.components),
298
+ `${name}${suffix}`,
299
+ ),
300
+ ),
301
+ )
302
+ ) {
303
+ continue;
304
+ }
210
305
  issues.push(
211
306
  issueWarning(
212
307
  'source_without_component_doc',
213
- `Component source "${name}.tsx" has no same-stem metadata file ${name}.doc.mjs, so Astryx ignores it.`,
308
+ `Component source "${name}.tsx" has no same-stem metadata file ${name}.doc.mjs, so Astryx ignores it. Fix: add ${name}.doc.mjs beside it with type: 'component'; \`astryx docs authoring component-doc\` lists its fields.${overlap}`,
214
309
  ),
215
310
  );
216
311
  }
@@ -247,7 +342,7 @@ async function checkDocs(integration, issues) {
247
342
  }
248
343
 
249
344
  /**
250
- * Validate the integration's source-theme catalog. The same discovery function
345
+ * Validate the integration's source-theme descriptors. The same discovery function
251
346
  * powers Project and theme list/add, so validation cannot accept a shape that
252
347
  * consumers later fail to use.
253
348
  * @param {LoadedIntegration} integration
@@ -289,6 +384,13 @@ export async function validateLoadedIntegration(loaded) {
289
384
  /** @type {Issue[]} */
290
385
  const issues = [];
291
386
  if (!loaded || typeof loaded !== 'object') return issues;
387
+ // A package set aside for claiming another package's provider ID has no
388
+ // contribution roots to check; the conflict itself is what to report.
389
+ if (loaded.__providerConflict) {
390
+ return [
391
+ issueWarning(DUPLICATE_PROVIDER, loaded.__providerConflict.message),
392
+ ];
393
+ }
292
394
  // A manifest that threw on import (or failed the schema) carries a load-error
293
395
  // marker and no contribution roots, so every check below would find nothing
294
396
  // and report a clean integration — which is how a stale manifest used to go