@astryxdesign/cli 0.6.3-canary.ea2f048 → 0.6.3-canary.f04b501

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 (505) hide show
  1. package/README.md +106 -72
  2. package/api/blog/blog.doc.mjs +1 -0
  3. package/api/build/build.doc.mjs +4 -3
  4. package/api/build/build.test.mjs +14 -3
  5. package/api/build/build.type.d.mts +36 -2
  6. package/api/build/build.type.mjs +25 -4
  7. package/api/build/help/help.d.mts +8 -5
  8. package/api/build/help/help.mjs +56 -6
  9. package/api/component/component.doc.mjs +13 -3
  10. package/api/component/component.mjs +31 -2
  11. package/api/component/component.test.mjs +38 -0
  12. package/api/component/component.type.d.mts +22 -11
  13. package/api/component/component.type.mjs +32 -24
  14. package/api/component/detail/blocks/blocks.d.mts +2 -1
  15. package/api/component/detail/blocks/blocks.mjs +4 -3
  16. package/api/component/list/list.d.mts +0 -5
  17. package/api/component/list/list.mjs +37 -9
  18. package/api/discover/discover.doc.mjs +2 -1
  19. package/api/discover/discover.type.d.mts +4 -4
  20. package/api/discover/discover.type.mjs +10 -10
  21. package/api/docs/_adapter.d.mts +32 -24
  22. package/api/docs/_adapter.mjs +81 -87
  23. package/api/docs/compiled-topics.test.mjs +78 -0
  24. package/api/docs/detail/detail.mjs +14 -63
  25. package/api/docs/detail/section/section.d.mts +1 -1
  26. package/api/docs/detail/section/section.mjs +44 -20
  27. package/api/docs/detail/section/section.test.mjs +41 -0
  28. package/api/docs/docs.d.mts +7 -2
  29. package/api/docs/docs.doc.mjs +28 -10
  30. package/api/docs/docs.mjs +16 -9
  31. package/api/docs/docs.test.mjs +6 -0
  32. package/api/docs/docs.type.d.mts +40 -3
  33. package/api/docs/docs.type.mjs +36 -8
  34. package/api/docs/index/index.d.mts +18 -0
  35. package/api/docs/index/index.mjs +32 -0
  36. package/api/docs/index/index.test.mjs +62 -0
  37. package/api/docs/integrationDocs.test.mjs +106 -0
  38. package/api/docs/list/list.mjs +3 -7
  39. package/api/doctor/doctor.d.mts +70 -0
  40. package/api/doctor/doctor.doc.mjs +1 -0
  41. package/api/doctor/doctor.mjs +404 -0
  42. package/api/doctor/doctor.test.mjs +522 -1
  43. package/api/gap-report/gap-report.doc.mjs +8 -4
  44. package/api/hook/_adapter.mjs +19 -5
  45. package/api/hook/hook.doc.mjs +1 -0
  46. package/api/hook/hook.type.d.mts +3 -3
  47. package/api/hook/hook.type.mjs +11 -11
  48. package/api/hook/list/list.d.mts +2 -2
  49. package/api/hook/list/list.mjs +69 -17
  50. package/api/init/init.doc.mjs +5 -0
  51. package/api/init/init.test.mjs +41 -1
  52. package/api/init/remove/remove.mjs +1 -1
  53. package/api/init/run/run.mjs +20 -10
  54. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  55. package/api/integration/add-contribution.mjs +23 -10
  56. package/api/integration/add-contribution.test.mjs +121 -7
  57. package/api/integration/add-theme.mjs +34 -64
  58. package/api/integration/add-theme.test.mjs +105 -21
  59. package/api/integration/authoring-checks.test.mjs +8 -4
  60. package/api/integration/integration-authoring.type.d.mts +1 -1
  61. package/api/integration/integration-block-exports.test.mjs +10 -6
  62. package/api/integration/integrationAdd.doc.mjs +8 -4
  63. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  64. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  65. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  66. package/api/integration/integrationAddDoc.doc.mjs +1 -0
  67. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  68. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  69. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  70. package/api/integration/integrationDocConflicts.doc.mjs +1 -0
  71. package/api/integration/integrationPackCheck.doc.mjs +1 -0
  72. package/api/integration/integrationTemplateConflicts.doc.mjs +1 -0
  73. package/api/integration/pack-check.mjs +49 -7
  74. package/api/integration/pack-check.test.mjs +266 -47
  75. package/api/integration/summarizeIssues.doc.mjs +1 -0
  76. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  77. package/api/integration/validate-integration.mjs +52 -102
  78. package/api/integration/validate-integration.test.mjs +176 -23
  79. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  80. package/api/integration/validateIntegration.doc.mjs +2 -1
  81. package/api/json/assertResponse.doc.mjs +1 -0
  82. package/api/json/envelope-types.test.mjs +76 -0
  83. package/api/json/isError.doc.mjs +1 -0
  84. package/api/json/parseResponse.doc.mjs +3 -2
  85. package/api/layout/expand/expand.mjs +7 -5
  86. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  87. package/api/layout/grammar/grammar.mjs +2 -1
  88. package/api/layout/layoutCheck.doc.mjs +1 -0
  89. package/api/layout/layoutExpand.doc.mjs +2 -1
  90. package/api/layout/layoutGrammar.doc.mjs +1 -0
  91. package/api/search/search-return-type.test.mjs +54 -0
  92. package/api/search/search.d.mts +3 -10
  93. package/api/search/search.doc.mjs +6 -1
  94. package/api/search/search.mjs +31 -14
  95. package/api/search/search.test.mjs +34 -0
  96. package/api/search/search.type.d.mts +2 -2
  97. package/api/search/search.type.mjs +1 -1
  98. package/api/swizzle/copy/copy.mjs +28 -11
  99. package/api/swizzle/swizzle.doc.mjs +2 -1
  100. package/api/swizzle/swizzle.type.d.mts +2 -2
  101. package/api/swizzle/swizzle.type.mjs +2 -2
  102. package/api/template/copy/copy.mjs +17 -23
  103. package/api/template/copy/copy.test.mjs +17 -0
  104. package/api/template/template-suffix.test.mjs +41 -21
  105. package/api/template/template.d.mts +1 -1
  106. package/api/template/template.doc.mjs +3 -1
  107. package/api/template/template.type.d.mts +6 -6
  108. package/api/template/template.type.mjs +12 -12
  109. package/api/theme/_adapter.d.mts +2 -3
  110. package/api/theme/_adapter.mjs +4 -5
  111. package/api/theme/add/add.binary.test.mjs +84 -0
  112. package/api/theme/add/add.mjs +20 -3
  113. package/api/theme/add/add.staging.test.mjs +66 -0
  114. package/api/theme/add/add.test.mjs +14 -1
  115. package/api/theme/build/build.mjs +133 -42
  116. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  117. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  118. package/api/theme/build/build.test.mjs +127 -0
  119. package/api/theme/build/font-warning.mjs +3 -3
  120. package/api/theme/build/font-warning.test.mjs +5 -2
  121. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  122. package/api/theme/integration-themes.test.mjs +39 -28
  123. package/api/theme/list/list.test.mjs +19 -20
  124. package/api/theme/listThemes.doc.mjs +6 -5
  125. package/api/theme/palette/generate/generate.mjs +8 -3
  126. package/api/theme/palette/generate/generate.test.mjs +96 -0
  127. package/api/theme/palette/generate/generator.d.mts +10 -13
  128. package/api/theme/palette/generate/generator.mjs +15 -4
  129. package/api/theme/palette/generate/generator.test.mjs +10 -0
  130. package/api/theme/template/template.mjs +11 -2
  131. package/api/theme/template/template.test.mjs +15 -0
  132. package/api/theme/theme.type.d.mts +170 -11
  133. package/api/theme/theme.type.mjs +94 -27
  134. package/api/theme/themeAdd.doc.mjs +4 -3
  135. package/api/theme/themeBuild.doc.mjs +8 -4
  136. package/api/theme/themeList.doc.mjs +6 -3
  137. package/api/theme/themeListAvailable.doc.mjs +5 -3
  138. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  139. package/api/theme/themeTargets.doc.mjs +1 -0
  140. package/api/theme/themeTemplate.doc.mjs +5 -1
  141. package/api/upgrade/_adapter.d.mts +12 -3
  142. package/api/upgrade/_adapter.mjs +123 -19
  143. package/api/upgrade/list/list.mjs +2 -1
  144. package/api/upgrade/list/list.test.mjs +73 -0
  145. package/api/upgrade/project-context.test.mjs +272 -0
  146. package/api/upgrade/provider-agreement.test.mjs +152 -0
  147. package/api/upgrade/run/run.mjs +1 -0
  148. package/api/upgrade/status/status.mjs +2 -2
  149. package/api/upgrade/upgrade.doc.mjs +7 -4
  150. package/api/upgrade/upgrade.type.d.mts +9 -5
  151. package/api/upgrade/upgrade.type.mjs +12 -11
  152. package/assets/codemods/integration-discovery.mjs +48 -4
  153. package/assets/codemods/integration-discovery.test.mjs +73 -0
  154. package/assets/codemods/runner.mjs +115 -5
  155. package/assets/codemods/term-log.mjs +32 -8
  156. package/assets/codemods/term-log.test.mjs +19 -1
  157. package/assets/codemods/transform-prop.mjs +109 -0
  158. package/assets/codemods/transform-prop.test.mjs +95 -0
  159. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +216 -0
  160. package/assets/codemods/transforms/next/index.mjs +11 -1
  161. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  162. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  163. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  164. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  165. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  166. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  167. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  168. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  169. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  170. package/assets/docs/README.md +9 -0
  171. package/assets/docs/authoring.doc.mjs +14 -0
  172. package/assets/docs/cli-integrations.doc.mjs +78 -20
  173. package/assets/docs/cli.doc.mjs +15 -0
  174. package/assets/docs/styling-libraries.doc.mjs +1 -1
  175. package/assets/docs/theme.doc.mjs +1 -1
  176. package/assets/docs/working-with-ai.doc.mjs +1 -1
  177. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  178. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  179. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  180. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  181. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  182. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  183. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  184. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  185. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  186. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  187. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  188. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  189. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  190. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  191. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  192. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  193. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  194. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  195. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  196. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  197. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  198. package/authoring/_shared/contract.ts +22 -0
  199. package/authoring/codemod/codemod.doc.mjs +7 -2
  200. package/authoring/codemod/parse.d.mts +8 -8
  201. package/authoring/codemod/parse.mjs +8 -6
  202. package/authoring/config/config.doc.mjs +2 -2
  203. package/authoring/config/debug-composition.test.mjs +92 -0
  204. package/authoring/config/parse.d.mts +13 -13
  205. package/authoring/config/parse.mjs +8 -8
  206. package/authoring/config/type.ts +18 -6
  207. package/authoring/debug/debug.doc.d.mts +11 -0
  208. package/authoring/debug/debug.doc.mjs +182 -0
  209. package/authoring/debug/parse.d.mts +5 -5
  210. package/authoring/debug/parse.mjs +3 -3
  211. package/authoring/doctypes/_schema.d.mts +788 -23
  212. package/authoring/doctypes/_schema.mjs +492 -39
  213. package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
  214. package/authoring/doctypes/base/graph-fields.doc.mjs +62 -0
  215. package/authoring/doctypes/base/type.ts +40 -0
  216. package/authoring/doctypes/command/command.doc.mjs +4 -3
  217. package/authoring/doctypes/command/parse.d.mts +2 -2
  218. package/authoring/doctypes/command/parse.mjs +1 -1
  219. package/authoring/doctypes/command/type.ts +4 -3
  220. package/authoring/doctypes/component/component.doc.mjs +6 -3
  221. package/authoring/doctypes/component/parse.d.mts +2 -2
  222. package/authoring/doctypes/component/parse.mjs +1 -1
  223. package/authoring/doctypes/component/type.ts +6 -5
  224. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  225. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  226. package/authoring/doctypes/enum/parse.d.mts +2 -2
  227. package/authoring/doctypes/enum/parse.mjs +1 -1
  228. package/authoring/doctypes/enum/type.ts +4 -2
  229. package/authoring/doctypes/function/function.doc.mjs +5 -1
  230. package/authoring/doctypes/function/parse.d.mts +2 -2
  231. package/authoring/doctypes/function/parse.mjs +1 -1
  232. package/authoring/doctypes/function/type.ts +7 -3
  233. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  234. package/authoring/doctypes/hook/parse.d.mts +2 -2
  235. package/authoring/doctypes/hook/parse.mjs +1 -1
  236. package/authoring/doctypes/hook/type.ts +5 -4
  237. package/authoring/doctypes/legacy.d.mts +8 -6
  238. package/authoring/doctypes/legacy.mjs +5 -4
  239. package/authoring/doctypes/load-contract.test.mjs +208 -0
  240. package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
  241. package/authoring/doctypes/namespace/namespace.doc.mjs +132 -0
  242. package/authoring/doctypes/namespace/parse.d.mts +12 -0
  243. package/authoring/doctypes/namespace/parse.mjs +25 -0
  244. package/authoring/doctypes/namespace/parse.test.mjs +165 -0
  245. package/authoring/doctypes/namespace/type.ts +71 -0
  246. package/authoring/doctypes/parse.d.mts +22 -18
  247. package/authoring/doctypes/parse.mjs +22 -12
  248. package/authoring/doctypes/parse.test.mjs +77 -3
  249. package/authoring/doctypes/reference/parse.d.mts +2 -2
  250. package/authoring/doctypes/reference/parse.mjs +8 -5
  251. package/authoring/doctypes/reference/reference.doc.mjs +18 -5
  252. package/authoring/doctypes/reference/type.ts +53 -7
  253. package/authoring/doctypes/schema/parse.d.mts +2 -2
  254. package/authoring/doctypes/schema/parse.mjs +1 -1
  255. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  256. package/authoring/doctypes/schema/type.ts +4 -4
  257. package/authoring/doctypes/template/parse.d.mts +92 -1
  258. package/authoring/doctypes/template/parse.mjs +36 -2
  259. package/authoring/doctypes/template/parse.test.mjs +8 -2
  260. package/authoring/doctypes/template/template.doc.mjs +7 -3
  261. package/authoring/doctypes/template/type.ts +5 -2
  262. package/authoring/doctypes/theme/parse.d.mts +35 -0
  263. package/authoring/doctypes/theme/parse.mjs +76 -0
  264. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  265. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  266. package/authoring/doctypes/theme/type.ts +42 -0
  267. package/authoring/doctypes/types.ts +12 -10
  268. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  269. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  270. package/authoring/gap-report/parse.d.mts +10 -10
  271. package/authoring/gap-report/parse.mjs +6 -6
  272. package/authoring/gap-report/type.ts +1 -1
  273. package/authoring/identity/identity.doc.d.mts +9 -0
  274. package/authoring/identity/identity.doc.mjs +61 -0
  275. package/authoring/identity/type.ts +132 -0
  276. package/authoring/index.d.mts +2 -0
  277. package/authoring/index.d.ts +51 -17
  278. package/authoring/index.mjs +3 -1
  279. package/authoring/integration/integration.doc.mjs +15 -8
  280. package/authoring/integration/parse.d.mts +2 -2
  281. package/authoring/integration/parse.mjs +1 -1
  282. package/authoring/integration/parse.test.mjs +10 -1
  283. package/authoring/integration/schema.d.mts +6 -4
  284. package/authoring/integration/schema.mjs +9 -3
  285. package/authoring/integration/type.ts +18 -7
  286. package/authoring/shadcn/receipt.d.mts +6 -6
  287. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  288. package/clients/cli/command-load-failure.test.mjs +83 -0
  289. package/clients/cli/commands/blog.doc.mjs +1 -1
  290. package/clients/cli/commands/blog.mjs +23 -8
  291. package/clients/cli/commands/blog.test.mjs +42 -1
  292. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  293. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  294. package/clients/cli/commands/build-theme.mjs +5 -5
  295. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  296. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  297. package/clients/cli/commands/build.doc.mjs +5 -2
  298. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  299. package/clients/cli/commands/build.mjs +32 -47
  300. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  301. package/clients/cli/commands/build.text-fields.test.mjs +40 -0
  302. package/clients/cli/commands/component/index.mjs +2 -7
  303. package/clients/cli/commands/component-package.test.mjs +46 -0
  304. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  305. package/clients/cli/commands/component.doc.mjs +1 -1
  306. package/clients/cli/commands/component.test.mjs +19 -0
  307. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  308. package/clients/cli/commands/discover.broken-integration.test.mjs +48 -0
  309. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  310. package/clients/cli/commands/discover.doc.mjs +5 -3
  311. package/clients/cli/commands/discover.mjs +3 -3
  312. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  313. package/clients/cli/commands/docs.doc.mjs +14 -4
  314. package/clients/cli/commands/docs.mjs +121 -21
  315. package/clients/cli/commands/docs.test.mjs +88 -0
  316. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  317. package/clients/cli/commands/doctor-integration-docs.doc.mjs +1 -1
  318. package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -1
  319. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  320. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  321. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  322. package/clients/cli/commands/doctor-integration.test.mjs +15 -7
  323. package/clients/cli/commands/doctor.doc.mjs +1 -1
  324. package/clients/cli/commands/doctor.mjs +6 -16
  325. package/clients/cli/commands/doctor.test.mjs +42 -0
  326. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  327. package/clients/cli/commands/gap-report.test.mjs +72 -0
  328. package/clients/cli/commands/hook/index.mjs +7 -17
  329. package/clients/cli/commands/hook.doc.mjs +1 -1
  330. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  331. package/clients/cli/commands/init.doc.mjs +20 -9
  332. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  333. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  334. package/clients/cli/commands/integration-add.doc.mjs +22 -6
  335. package/clients/cli/commands/integration-authoring.test.mjs +13 -9
  336. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  337. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  338. package/clients/cli/commands/integration.doc.mjs +1 -1
  339. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  340. package/clients/cli/commands/json-contract.test.mjs +33 -0
  341. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  342. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  343. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  344. package/clients/cli/commands/layout.doc.mjs +3 -3
  345. package/clients/cli/commands/layout.mjs +21 -9
  346. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  347. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  348. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  349. package/clients/cli/commands/manifest.doc.mjs +1 -1
  350. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  351. package/clients/cli/commands/search.doc.mjs +7 -4
  352. package/clients/cli/commands/search.mjs +17 -7
  353. package/clients/cli/commands/search.test.mjs +75 -0
  354. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  355. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  356. package/clients/cli/commands/template.doc.mjs +29 -7
  357. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  358. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  359. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  360. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  361. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  362. package/clients/cli/commands/theme-palette-generate.doc.mjs +9 -5
  363. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  364. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  365. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  366. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  367. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  368. package/clients/cli/commands/theme.doc.mjs +1 -1
  369. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  370. package/clients/cli/commands/upgrade.doc.mjs +20 -9
  371. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  372. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  373. package/clients/cli/formatters/index.mjs +162 -1
  374. package/clients/cli/formatters/index.test.mjs +91 -0
  375. package/clients/cli/index.mjs +13 -30
  376. package/clients/cli/latest-version-env.test.mjs +50 -0
  377. package/clients/cli/lib/cli-error.test.mjs +7 -0
  378. package/clients/cli/lib/component-format.mjs +9 -9
  379. package/clients/cli/lib/component-format.test.mjs +1 -1
  380. package/clients/cli/lib/define-command.mjs +32 -6
  381. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  382. package/clients/cli/lib/exit-codes.test.mjs +97 -0
  383. package/clients/cli/lib/hook-format.mjs +19 -10
  384. package/clients/cli/lib/json-shim.mjs +38 -2
  385. package/clients/cli/lib/json-shim.test.mjs +83 -0
  386. package/clients/cli/lib/manifest.d.ts +2 -0
  387. package/clients/cli/lib/manifest.mjs +29 -2
  388. package/clients/cli/lib/manifest.test.mjs +17 -0
  389. package/foundation/agent-docs/agent-docs.d.mts +4 -0
  390. package/foundation/agent-docs/agent-docs.mjs +69 -3
  391. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  392. package/foundation/config/integration-debug.test.mjs +28 -3
  393. package/foundation/config/project-themes.test.mjs +11 -19
  394. package/foundation/config/project.d.mts +8 -0
  395. package/foundation/config/project.mjs +190 -32
  396. package/foundation/config/project.test.mjs +129 -16
  397. package/foundation/discovery/authoring-self-docs.d.mts +75 -0
  398. package/foundation/discovery/authoring-self-docs.mjs +224 -0
  399. package/foundation/discovery/authoring-self-docs.test.mjs +154 -0
  400. package/foundation/discovery/authoring-surface.d.mts +74 -0
  401. package/foundation/discovery/authoring-surface.mjs +525 -0
  402. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  403. package/foundation/discovery/cli-self-docs.d.mts +113 -0
  404. package/foundation/discovery/cli-self-docs.mjs +514 -0
  405. package/foundation/discovery/cli-self-docs.test.mjs +437 -0
  406. package/foundation/discovery/component-discovery.d.mts +1 -1
  407. package/foundation/discovery/component-discovery.mjs +2 -1
  408. package/foundation/discovery/component-loader.d.mts +35 -38
  409. package/foundation/discovery/component-loader.mjs +53 -222
  410. package/foundation/discovery/docs-discovery.d.mts +12 -4
  411. package/foundation/discovery/docs-discovery.mjs +214 -98
  412. package/foundation/discovery/docs-discovery.test.mjs +284 -15
  413. package/foundation/discovery/docs-output-budget.d.mts +28 -0
  414. package/foundation/discovery/docs-output-budget.mjs +50 -0
  415. package/foundation/discovery/docs-section-key.d.mts +98 -0
  416. package/foundation/discovery/docs-section-key.mjs +221 -0
  417. package/foundation/discovery/docs-section-key.test.mjs +224 -0
  418. package/foundation/discovery/template-adapter.d.mts +21 -5
  419. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  420. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  421. package/foundation/discovery/template-adapter.mjs +321 -66
  422. package/foundation/discovery/template-adapter.test.mjs +15 -0
  423. package/foundation/discovery/theme-discovery.d.mts +67 -7
  424. package/foundation/discovery/theme-discovery.mjs +916 -186
  425. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  426. package/foundation/discovery/theming-targets.test.mjs +4 -0
  427. package/foundation/doc-compiler/bundle.d.mts +47 -0
  428. package/foundation/doc-compiler/bundle.mjs +218 -0
  429. package/foundation/doc-compiler/bundle.test.mjs +255 -0
  430. package/foundation/doc-compiler/compile.d.mts +362 -0
  431. package/foundation/doc-compiler/compile.mjs +511 -0
  432. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  433. package/foundation/doc-compiler/diagnostics.mjs +277 -0
  434. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  435. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  436. package/foundation/doc-compiler/import.d.mts +24 -0
  437. package/foundation/doc-compiler/import.mjs +59 -0
  438. package/foundation/doc-compiler/inputs.d.mts +102 -0
  439. package/foundation/doc-compiler/inputs.mjs +286 -0
  440. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  441. package/foundation/doc-compiler/ir.d.mts +22 -0
  442. package/foundation/doc-compiler/ir.mjs +464 -0
  443. package/foundation/doc-compiler/lenses.d.mts +33 -0
  444. package/foundation/doc-compiler/lenses.mjs +127 -0
  445. package/foundation/doc-compiler/lower-doc.test.mjs +492 -0
  446. package/foundation/doc-compiler/overlays.d.mts +37 -0
  447. package/foundation/doc-compiler/overlays.mjs +206 -0
  448. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  449. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  450. package/foundation/doc-compiler/read.d.mts +126 -0
  451. package/foundation/doc-compiler/read.mjs +320 -0
  452. package/foundation/doc-compiler/read.test.mjs +313 -0
  453. package/foundation/doc-compiler/source.d.mts +33 -0
  454. package/foundation/doc-compiler/source.mjs +128 -0
  455. package/foundation/fs/module-loader.d.mts +1 -0
  456. package/foundation/fs/module-loader.mjs +50 -1
  457. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  458. package/foundation/fs/path-safety.d.mts +3 -2
  459. package/foundation/fs/path-safety.mjs +49 -19
  460. package/foundation/fs/path-safety.test.mjs +50 -0
  461. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  462. package/foundation/identity/provider-identity.d.mts +90 -0
  463. package/foundation/identity/provider-identity.mjs +320 -0
  464. package/foundation/identity/provider-identity.test.mjs +254 -0
  465. package/foundation/identity/providers.d.mts +7 -0
  466. package/foundation/identity/providers.mjs +16 -0
  467. package/foundation/integrations/autolink.d.mts +58 -1
  468. package/foundation/integrations/autolink.mjs +143 -45
  469. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  470. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  471. package/foundation/integrations/contribution-inventory.d.mts +1 -1
  472. package/foundation/integrations/contribution-inventory.mjs +17 -20
  473. package/foundation/integrations/contribution-inventory.test.mjs +67 -27
  474. package/foundation/integrations/integration-warnings.mjs +6 -0
  475. package/foundation/integrations/integrations.d.mts +49 -2
  476. package/foundation/integrations/integrations.mjs +81 -8
  477. package/foundation/integrations/integrations.test.mjs +384 -1
  478. package/foundation/integrations/provider-conflicts.test.mjs +125 -0
  479. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  480. package/foundation/integrations/provider-resolution.d.mts +152 -0
  481. package/foundation/integrations/provider-resolution.mjs +576 -0
  482. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  483. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  484. package/foundation/integrations/theme-descriptor.mjs +44 -0
  485. package/foundation/integrations/validate-contributions.d.mts +2 -0
  486. package/foundation/integrations/validate-contributions.mjs +114 -10
  487. package/foundation/response/base.d.ts +8 -4
  488. package/foundation/response/error-codes.doc.mjs +3 -4
  489. package/foundation/response/error-codes.mjs +2 -2
  490. package/foundation/response/error-codes.test.mjs +83 -0
  491. package/foundation/response/json-contract.test.mjs +57 -17
  492. package/foundation/response/json.d.mts +4 -2
  493. package/foundation/response/json.mjs +8 -10
  494. package/foundation/response/response-types.doc.mjs +16 -11
  495. package/foundation/response/response-types.doc.test.mjs +158 -0
  496. package/foundation/response/response.doc.mjs +1 -1
  497. package/foundation/text/string-utils.mjs +22 -10
  498. package/foundation/xle/expand.d.mts +2 -0
  499. package/foundation/xle/expand.mjs +3 -2
  500. package/foundation/xle/expand.test.mjs +54 -0
  501. package/package.json +9 -11
  502. package/assets/templates/themes/manifest.json +0 -95
  503. package/clients/cli/lib/update-check.mjs +0 -83
  504. package/clients/cli/lib/update-check.test.mjs +0 -137
  505. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -15,7 +15,7 @@
15
15
  */
16
16
  /**
17
17
  * Compute the files the tarball must contain for an integration's
18
- * contributions to be visible. Reads catalogs and walks directories;
18
+ * contributions to be visible. Walks descriptor-owned directories;
19
19
  * never imports or executes authored modules.
20
20
  *
21
21
  * @param {import('./integrations.mjs').LoadedIntegration} loaded
@@ -14,8 +14,11 @@
14
14
  import * as fs from 'node:fs';
15
15
  import * as path from 'node:path';
16
16
  import {isDeepStrictEqual} from 'node:util';
17
- import {THEME_MANIFEST_BASENAME} from '../discovery/theme-discovery.mjs';
18
- import {discoverIntegrationThemes} from '../discovery/theme-discovery.mjs';
17
+ import {
18
+ discoverIntegrationThemes,
19
+ isThemeFolder,
20
+ listThemeFiles,
21
+ } from '../discovery/theme-discovery.mjs';
19
22
  import {discoverIntegrationComponents} from '../discovery/component-discovery.mjs';
20
23
  import {loadComponentDoc} from '../discovery/component-loader.mjs';
21
24
  import {discoverIntegrationTemplatesForOne} from '../discovery/template-adapter.mjs';
@@ -65,27 +68,21 @@ function rel(packageDir, file) {
65
68
 
66
69
  /** @param {string} root @param {string} pkgDir */
67
70
  function enumerateThemeFiles(root, pkgDir) {
71
+ if (!root || !fs.existsSync(root) || !fs.statSync(root).isDirectory()) {
72
+ return [];
73
+ }
74
+ // Exactly what `theme add` copies: each theme folder's files, including
75
+ // tests and fixtures, but no dot entry or file npm never publishes. Files
76
+ // beside the theme folders belong to no theme.
68
77
  /** @type {string[]} */
69
78
  const files = [];
70
- const catalog = path.join(root, THEME_MANIFEST_BASENAME);
71
- if (!fs.existsSync(catalog)) return files;
72
- files.push(rel(pkgDir, catalog));
73
- try {
74
- const data = JSON.parse(fs.readFileSync(catalog, 'utf-8'));
75
- if (data?.version !== 1 || !Array.isArray(data.themes)) return files;
76
- for (const theme of data.themes) {
77
- if (typeof theme.slug !== 'string' || !Array.isArray(theme.files))
78
- continue;
79
- for (const f of theme.files) {
80
- if (typeof f === 'string') {
81
- files.push(rel(pkgDir, path.join(root, theme.slug, f)));
82
- }
83
- }
79
+ for (const entry of fs.readdirSync(root, {withFileTypes: true})) {
80
+ const full = path.join(root, entry.name);
81
+ if (entry.isDirectory() && isThemeFolder(full)) {
82
+ files.push(...listThemeFiles(full).map(file => path.join(full, file)));
84
83
  }
85
- } catch {
86
- /* Phase 1 catches structural issues */
87
84
  }
88
- return files;
85
+ return files.sort().map(file => rel(pkgDir, file));
89
86
  }
90
87
 
91
88
  /** @param {string} root @param {string} pkgDir */
@@ -158,7 +155,7 @@ const ROOT_KINDS = /** @type {const} */ ([
158
155
 
159
156
  /**
160
157
  * Compute the files the tarball must contain for an integration's
161
- * contributions to be visible. Reads catalogs and walks directories;
158
+ * contributions to be visible. Walks descriptor-owned directories;
162
159
  * never imports or executes authored modules.
163
160
  *
164
161
  * @param {import('./integrations.mjs').LoadedIntegration} loaded
@@ -37,30 +37,37 @@ function loaded(overrides = {}) {
37
37
 
38
38
  function writeTheme(slug, files = [`${slug}Theme.ts`]) {
39
39
  const root = path.join(tmpDir, 'themes');
40
- fs.mkdirSync(path.join(root, slug), {recursive: true});
41
- for (const f of files) {
42
- fs.writeFileSync(path.join(root, slug, f), `// ${f}\n`);
40
+ const themeDir = path.join(root, slug);
41
+ fs.mkdirSync(themeDir, {recursive: true});
42
+ for (const file of files) {
43
+ const target = path.join(themeDir, file);
44
+ fs.mkdirSync(path.dirname(target), {recursive: true});
45
+ fs.writeFileSync(target, `// ${file}\n`);
43
46
  }
44
- const catalogPath = path.join(root, 'manifest.json');
45
- let catalog = {version: 1, themes: []};
46
- if (fs.existsSync(catalogPath)) {
47
- catalog = JSON.parse(fs.readFileSync(catalogPath, 'utf-8'));
48
- }
49
- catalog.themes.push({
50
- slug,
51
- displayName: slug,
52
- description: `${slug} theme.`,
53
- maintained: true,
54
- entry: files[0],
55
- exportName: `${slug}Theme`,
56
- files,
57
- });
58
- fs.writeFileSync(catalogPath, JSON.stringify(catalog, null, 2) + '\n');
47
+ fs.writeFileSync(
48
+ path.join(themeDir, `${slug}Theme.doc.mjs`),
49
+ `/** @type {import('@astryxdesign/cli/authoring').ThemeDoc} */\nexport default {type: 'theme', name: '${slug}', displayName: '${slug}', description: '${slug} theme.', maintained: true};\n`,
50
+ );
59
51
  return root;
60
52
  }
61
53
 
54
+ const UNPUBLISHED = [
55
+ '.DS_Store',
56
+ '._oceanTheme.ts',
57
+ '.gitignore',
58
+ '.npmignore',
59
+ '.npmrc',
60
+ 'oceanTheme.ts.orig',
61
+ 'npm-debug.log',
62
+ 'palette/.DS_Store',
63
+ 'palette/npm-debug.log',
64
+ '.git/HEAD',
65
+ 'CVS/Entries',
66
+ 'node_modules/dep/index.js',
67
+ ];
68
+
62
69
  describe('computeRequiredFiles', () => {
63
- it('enumerates manifest + theme catalog files', () => {
70
+ it('enumerates each complete descriptor-owned theme directory', () => {
64
71
  const root = writeTheme('ocean', ['oceanTheme.ts', 'tokens.ts']);
65
72
  const inv = computeRequiredFiles(loaded({themes: root}));
66
73
 
@@ -69,13 +76,46 @@ describe('computeRequiredFiles', () => {
69
76
  expect(inv.roots[0].kind).toBe('themes');
70
77
  expect(inv.roots[0].files).toEqual(
71
78
  expect.arrayContaining([
72
- 'themes/manifest.json',
79
+ 'themes/ocean/oceanTheme.doc.mjs',
73
80
  'themes/ocean/oceanTheme.ts',
74
81
  'themes/ocean/tokens.ts',
75
82
  ]),
76
83
  );
77
84
  expect(inv.allFiles).toContain('astryx.integration.mjs');
78
- expect(inv.allFiles).toContain('themes/manifest.json');
85
+ expect(inv.allFiles).toContain('themes/ocean/oceanTheme.doc.mjs');
86
+ expect(inv.allFiles).not.toContain('themes/manifest.json');
87
+ });
88
+
89
+ it('requires no file npm leaves out, at any depth, and none beside the themes', () => {
90
+ const root = writeTheme('ocean', ['oceanTheme.ts', 'palette/tokens.ts']);
91
+ for (const file of [
92
+ ...UNPUBLISHED.map(name => `ocean/${name}`),
93
+ 'README.md',
94
+ 'npm-debug.log',
95
+ ]) {
96
+ fs.mkdirSync(path.dirname(path.join(root, file)), {recursive: true});
97
+ fs.writeFileSync(path.join(root, file), 'x\n');
98
+ }
99
+ expect(computeRequiredFiles(loaded({themes: root})).roots[0].files).toEqual(
100
+ [
101
+ 'themes/ocean/oceanTheme.doc.mjs',
102
+ 'themes/ocean/oceanTheme.ts',
103
+ 'themes/ocean/palette/tokens.ts',
104
+ ],
105
+ );
106
+ });
107
+
108
+ it('requires only the folders theme discovery reads', () => {
109
+ const root = writeTheme('ocean');
110
+ for (const file of ['shared/palette.ts', '.cache/state.json']) {
111
+ fs.mkdirSync(path.dirname(path.join(root, file)), {recursive: true});
112
+ fs.writeFileSync(path.join(root, file), '{}\n');
113
+ }
114
+ const inv = computeRequiredFiles(loaded({themes: root}));
115
+ expect(inv.roots[0].files).toEqual([
116
+ 'themes/ocean/oceanTheme.doc.mjs',
117
+ 'themes/ocean/oceanTheme.ts',
118
+ ]);
79
119
  });
80
120
 
81
121
  it('enumerates paired component metadata and source files', () => {
@@ -139,31 +179,31 @@ describe('computeRequiredFiles', () => {
139
179
  const root = path.join(tmpDir, 'templates');
140
180
  fs.mkdirSync(path.join(root, 'dashboard'), {recursive: true});
141
181
  fs.writeFileSync(
142
- path.join(root, 'dashboard', 'dashboard.template.mjs'),
182
+ path.join(root, 'dashboard', 'dashboard.doc.mjs'),
143
183
  '// tmpl\n',
144
184
  );
145
185
  fs.writeFileSync(path.join(root, 'dashboard', 'dashboard.tsx'), '// src\n');
146
186
  const inv = computeRequiredFiles(loaded({templates: root}));
147
187
 
148
188
  expect(inv.roots[0].files).toContain(
149
- 'templates/dashboard/dashboard.template.mjs',
189
+ 'templates/dashboard/dashboard.doc.mjs',
150
190
  );
151
191
  expect(inv.roots[0].files).toContain('templates/dashboard/dashboard.tsx');
152
192
  });
153
193
 
154
- it('enumerates legacy .doc template metadata with paired sources', () => {
194
+ it('enumerates released .template compatibility metadata with paired sources', () => {
155
195
  const root = path.join(tmpDir, 'templates');
156
196
  fs.mkdirSync(path.join(root, 'dashboard'), {recursive: true});
157
197
  fs.writeFileSync(
158
- path.join(root, 'dashboard', 'dashboard.doc.mjs'),
159
- '// legacy template\n',
198
+ path.join(root, 'dashboard', 'dashboard.template.mjs'),
199
+ '// released compatibility template\n',
160
200
  );
161
201
  fs.writeFileSync(path.join(root, 'dashboard', 'dashboard.tsx'), '// src\n');
162
202
 
163
203
  const inv = computeRequiredFiles(loaded({templates: root}));
164
204
 
165
205
  expect(inv.roots[0].files).toEqual([
166
- 'templates/dashboard/dashboard.doc.mjs',
206
+ 'templates/dashboard/dashboard.template.mjs',
167
207
  'templates/dashboard/dashboard.tsx',
168
208
  ]);
169
209
  });
@@ -41,6 +41,12 @@ export async function warnOnIntegrationIssues(loadedIntegrations, {json = false}
41
41
  }
42
42
  for (const integration of loadedIntegrations) {
43
43
  if (!integration || typeof integration !== 'object') continue;
44
+ // A package set aside for a provider-ID conflict is fine in isolation,
45
+ // so `doctor integration validate` would not explain it. Say it here.
46
+ if (integration.__providerConflict) {
47
+ console.error(`Warning: ${integration.__providerConflict.message}`);
48
+ continue;
49
+ }
44
50
  let issues;
45
51
  try {
46
52
  issues = await validateLoadedIntegration(integration);
@@ -1,6 +1,26 @@
1
1
  // @generated by scripts/sync-api-types.mjs from the JSDoc in foundation/**/*.mjs.
2
2
  // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
3
 
4
+ /**
5
+ * Resolve provider identity across loaded integrations, in precedence order.
6
+ *
7
+ * Artifact and document IDs are provider-scoped, so two packages cannot both
8
+ * contribute under one provider ID. The same package reached twice (an npm
9
+ * alias beside the package it aliases, with the same name and version) loads
10
+ * once. Any other later claimant, including the same package at another
11
+ * version, stays as an inert entry that carries the conflict. The package being
12
+ * authored claims its ID before precedence order is considered, because the
13
+ * source being edited is authoritative. The winner still contributes; Project
14
+ * issues, Doctor, and the per-command warning name the one set aside instead of
15
+ * dropping it without a word.
16
+ *
17
+ * The conflict pass of {@link resolveProviders}, for a list that is already
18
+ * assembled.
19
+ *
20
+ * @param {LoadedIntegration[]} integrations in precedence order
21
+ * @returns {LoadedIntegration[]}
22
+ */
23
+ export function markProviderConflicts(integrations: LoadedIntegration[]): LoadedIntegration[];
4
24
  /**
5
25
  * Return the conventional root manifest paths present in `dir`, in
6
26
  * load-precedence order. Unlike {@link resolveManifestPath} this never throws —
@@ -75,12 +95,15 @@ export function loadLocalIntegration(packageDir: string, { fresh }?: {
75
95
  * Load configured integrations.
76
96
  *
77
97
  * @param {string[]} [specs] package names
78
- * @param {{cwd?: string, fresh?: boolean}} [options]
98
+ * @param {{cwd?: string, fresh?: boolean, resolveProviders?: boolean}} [options]
99
+ * `resolveProviders: false` leaves provider identity to a caller that
100
+ * resolves it once over a larger set (Project.load)
79
101
  * @returns {Promise<LoadedIntegration[]>}
80
102
  */
81
- export function loadIntegrations(specs?: string[], { cwd, fresh }?: {
103
+ export function loadIntegrations(specs?: string[], { cwd, fresh, resolveProviders }?: {
82
104
  cwd?: string;
83
105
  fresh?: boolean;
106
+ resolveProviders?: boolean;
84
107
  }): Promise<LoadedIntegration[]>;
85
108
  /**
86
109
  * A fully-resolved, loaded integration. Identity (`name`, `version`) comes from
@@ -89,6 +112,10 @@ export function loadIntegrations(specs?: string[], { cwd, fresh }?: {
89
112
  * are internal bookkeeping used by Doctor integration validation and Project.
90
113
  * @typedef {object} LoadedIntegration
91
114
  * @property {string} name
115
+ * @property {import('../../authoring/identity/type').ProviderId} [providerId]
116
+ * normalized stable provider identity; absent only for a legacy unnamed local
117
+ * package. Unique among contributing integrations: a later claimant is kept
118
+ * inert with `__providerConflict` (see {@link markProviderConflicts})
92
119
  * @property {string} [version]
93
120
  * @property {string} [components]
94
121
  * @property {string} [templates]
@@ -107,6 +134,10 @@ export function loadIntegrations(specs?: string[], { cwd, fresh }?: {
107
134
  * @property {string} __manifestFile
108
135
  * @property {string} [__loadError] set when the manifest failed to load/validate;
109
136
  * such an integration contributes nothing and is surfaced via Project.issues()
137
+ * @property {{providerId: import('../../authoring/identity/type').ProviderId, claimedBy: string, message: string}} [__providerConflict]
138
+ * set on a package whose provider ID an earlier-loaded package already
139
+ * claims; it contributes nothing and is reported as a `duplicate_provider`
140
+ * warning
110
141
  * @property {string[]} [__unknownKeys] manifest keys this CLI does not know —
111
142
  * surfaced as a warning; the rest of the manifest still contributes
112
143
  * @property {boolean} [__autolinked] loaded because the project declares the
@@ -134,6 +165,12 @@ export const MANIFEST_BASENAMES: string[];
134
165
  */
135
166
  export type LoadedIntegration = {
136
167
  name: string;
168
+ /**
169
+ * normalized stable provider identity; absent only for a legacy unnamed local
170
+ * package. Unique among contributing integrations: a later claimant is kept
171
+ * inert with `__providerConflict` (see {@link markProviderConflicts})
172
+ */
173
+ providerId?: import("../../authoring/identity/type").ProviderId | undefined;
137
174
  version?: string | undefined;
138
175
  components?: string | undefined;
139
176
  templates?: string | undefined;
@@ -163,6 +200,16 @@ export type LoadedIntegration = {
163
200
  * such an integration contributes nothing and is surfaced via Project.issues()
164
201
  */
165
202
  __loadError?: string | undefined;
203
+ /**
204
+ * set on a package whose provider ID an earlier-loaded package already
205
+ * claims; it contributes nothing and is reported as a `duplicate_provider`
206
+ * warning
207
+ */
208
+ __providerConflict?: {
209
+ providerId: import("../../authoring/identity/type").ProviderId;
210
+ claimedBy: string;
211
+ message: string;
212
+ } | undefined;
166
213
  /**
167
214
  * manifest keys this CLI does not know —
168
215
  * surfaced as a warning; the rest of the manifest still contributes
@@ -6,13 +6,19 @@
6
6
  * Integrations are PACKAGE NAMES listed in astryx.config.{ts,mjs,js}. Each
7
7
  * package declares a single conventional root manifest sibling to its
8
8
  * package.json — astryx.integration.{ts,mjs,js} — which contributes
9
- * components/templates/codemods/docs/themes roots and an optional issuesUrl. Identity
10
- * (name, version) comes from the package's package.json, not the manifest.
9
+ * components/templates/codemods/docs/themes roots and an optional issuesUrl.
10
+ * Stable provider identity and package metadata come from package.json, not the
11
+ * manifest.
12
+ *
13
+ * @input Integration package names, package.json files, and root manifests.
14
+ * @output LoadedIntegration records with normalized provider identity and roots.
15
+ * @position foundation/integrations — package contribution loading boundary.
11
16
  */
12
17
 
13
18
  import * as fs from 'node:fs';
14
19
  import * as path from 'node:path';
15
20
  import {assertWithin} from '../fs/path-safety.mjs';
21
+ import {normalizeProviderId} from '../identity/provider-identity.mjs';
16
22
  // The key census and contribution parsers are internal to the schema module on
17
23
  // purpose: the public parser still validates the complete authored type, while
18
24
  // the loader can isolate an invalid optional contribution from valid roots.
@@ -23,6 +29,7 @@ import {
23
29
  } from '../../authoring/integration/schema.mjs';
24
30
  import {importUserModule, findPresentFiles} from '../fs/module-loader.mjs';
25
31
  import {parseGapReportHandler} from '../../authoring/gap-report/parse.mjs';
32
+ import {resolveProviders} from './provider-resolution.mjs';
26
33
 
27
34
  /**
28
35
  * A fully-resolved, loaded integration. Identity (`name`, `version`) comes from
@@ -31,6 +38,10 @@ import {parseGapReportHandler} from '../../authoring/gap-report/parse.mjs';
31
38
  * are internal bookkeeping used by Doctor integration validation and Project.
32
39
  * @typedef {object} LoadedIntegration
33
40
  * @property {string} name
41
+ * @property {import('../../authoring/identity/type').ProviderId} [providerId]
42
+ * normalized stable provider identity; absent only for a legacy unnamed local
43
+ * package. Unique among contributing integrations: a later claimant is kept
44
+ * inert with `__providerConflict` (see {@link markProviderConflicts})
34
45
  * @property {string} [version]
35
46
  * @property {string} [components]
36
47
  * @property {string} [templates]
@@ -49,6 +60,10 @@ import {parseGapReportHandler} from '../../authoring/gap-report/parse.mjs';
49
60
  * @property {string} __manifestFile
50
61
  * @property {string} [__loadError] set when the manifest failed to load/validate;
51
62
  * such an integration contributes nothing and is surfaced via Project.issues()
63
+ * @property {{providerId: import('../../authoring/identity/type').ProviderId, claimedBy: string, message: string}} [__providerConflict]
64
+ * set on a package whose provider ID an earlier-loaded package already
65
+ * claims; it contributes nothing and is reported as a `duplicate_provider`
66
+ * warning
52
67
  * @property {string[]} [__unknownKeys] manifest keys this CLI does not know —
53
68
  * surfaced as a warning; the rest of the manifest still contributes
54
69
  * @property {boolean} [__autolinked] loaded because the project declares the
@@ -74,6 +89,50 @@ export const MANIFEST_BASENAMES = [
74
89
  'astryx.integration.js',
75
90
  ];
76
91
 
92
+ /**
93
+ * Normalize a package-owned provider ID without rejecting legacy unnamed local
94
+ * packages at this compatibility boundary.
95
+ * @param {unknown} name
96
+ * @returns {import('../../authoring/identity/type').ProviderId | undefined}
97
+ */
98
+ function providerIdForPackage(name) {
99
+ if (typeof name !== 'string' || name.length === 0) return undefined;
100
+ try {
101
+ return normalizeProviderId(name);
102
+ } catch {
103
+ return undefined;
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Resolve provider identity across loaded integrations, in precedence order.
109
+ *
110
+ * Artifact and document IDs are provider-scoped, so two packages cannot both
111
+ * contribute under one provider ID. The same package reached twice (an npm
112
+ * alias beside the package it aliases, with the same name and version) loads
113
+ * once. Any other later claimant, including the same package at another
114
+ * version, stays as an inert entry that carries the conflict. The package being
115
+ * authored claims its ID before precedence order is considered, because the
116
+ * source being edited is authoritative. The winner still contributes; Project
117
+ * issues, Doctor, and the per-command warning name the one set aside instead of
118
+ * dropping it without a word.
119
+ *
120
+ * The conflict pass of {@link resolveProviders}, for a list that is already
121
+ * assembled.
122
+ *
123
+ * @param {LoadedIntegration[]} integrations in precedence order
124
+ * @returns {LoadedIntegration[]}
125
+ */
126
+ export function markProviderConflicts(integrations) {
127
+ return resolveProviders(
128
+ integrations.map(integration => ({
129
+ source: /** @type {const} */ ('configured'),
130
+ integration,
131
+ spec: integration?.__spec,
132
+ })),
133
+ ).integrations;
134
+ }
135
+
77
136
  /**
78
137
  * Return the conventional root manifest paths present in `dir`, in
79
138
  * load-precedence order. Unlike {@link resolveManifestPath} this never throws —
@@ -274,6 +333,7 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
274
333
  typeof pkg.name === 'string' && pkg.name.length > 0
275
334
  ? pkg.name
276
335
  : '(local integration)';
336
+ const packageProviderId = providerIdForPackage(pkg.name);
277
337
  const manifestFile = resolveManifestPath(packageDir, spec);
278
338
 
279
339
  let manifest;
@@ -299,6 +359,7 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
299
359
  } catch (err) {
300
360
  return {
301
361
  name: spec,
362
+ ...(packageProviderId == null ? {} : {providerId: packageProviderId}),
302
363
  version: pkg.version,
303
364
  __spec: spec,
304
365
  __packageDir: packageDir,
@@ -308,6 +369,8 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
308
369
  };
309
370
  }
310
371
 
372
+ const providerId = providerIdForPackage(manifest.providerId ?? pkg.name);
373
+
311
374
  /** @param {string | null | undefined} value */
312
375
  const resolveRoot = value => {
313
376
  if (value == null) return undefined;
@@ -320,6 +383,7 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
320
383
 
321
384
  return {
322
385
  name: spec,
386
+ ...(providerId == null ? {} : {providerId}),
323
387
  version: pkg.version,
324
388
  components: resolveRoot(manifest.components),
325
389
  templates: resolveRoot(manifest.templates),
@@ -345,20 +409,22 @@ export async function loadLocalIntegration(packageDir, {fresh = false} = {}) {
345
409
  * Load configured integrations.
346
410
  *
347
411
  * @param {string[]} [specs] package names
348
- * @param {{cwd?: string, fresh?: boolean}} [options]
412
+ * @param {{cwd?: string, fresh?: boolean, resolveProviders?: boolean}} [options]
413
+ * `resolveProviders: false` leaves provider identity to a caller that
414
+ * resolves it once over a larger set (Project.load)
349
415
  * @returns {Promise<LoadedIntegration[]>}
350
416
  */
351
417
  export async function loadIntegrations(
352
418
  specs = [],
353
- {cwd = process.cwd(), fresh = false} = {},
419
+ {cwd = process.cwd(), fresh = false, resolveProviders = true} = {},
354
420
  ) {
355
421
  /** @type {LoadedIntegration[]} */
356
422
  const integrations = [];
357
- const seen = new Set();
423
+ const seenSpecs = new Set();
358
424
 
359
425
  for (const spec of specs) {
360
- if (!spec || seen.has(spec)) continue;
361
- seen.add(spec);
426
+ if (!spec || seenSpecs.has(spec)) continue;
427
+ seenSpecs.add(spec);
362
428
 
363
429
  const packageDir = resolvePackageDir(spec, cwd);
364
430
  const pkgPath = path.join(packageDir, 'package.json');
@@ -371,6 +437,7 @@ export async function loadIntegrations(
371
437
  );
372
438
  }
373
439
 
440
+ const packageProviderId = providerIdForPackage(pkg.name ?? spec);
374
441
  const manifestFile = resolveManifestPath(packageDir, spec);
375
442
  let manifest;
376
443
  /** @type {string[]} */
@@ -399,6 +466,7 @@ export async function loadIntegrations(
399
466
  // discovery loops naturally skip it (no components/templates/codemods).
400
467
  integrations.push({
401
468
  name: pkg.name ?? spec,
469
+ ...(packageProviderId == null ? {} : {providerId: packageProviderId}),
402
470
  version: pkg.version,
403
471
  __spec: spec,
404
472
  __packageDir: packageDir,
@@ -408,6 +476,10 @@ export async function loadIntegrations(
408
476
  continue;
409
477
  }
410
478
 
479
+ const providerId = providerIdForPackage(
480
+ manifest.providerId ?? pkg.name ?? spec,
481
+ );
482
+
411
483
  /** @param {string | null | undefined} value */
412
484
  const resolveRoot = value => {
413
485
  if (value == null) return undefined;
@@ -421,6 +493,7 @@ export async function loadIntegrations(
421
493
 
422
494
  integrations.push({
423
495
  name: pkg.name ?? spec,
496
+ ...(providerId == null ? {} : {providerId}),
424
497
  version: pkg.version,
425
498
  components: resolveRoot(manifest.components),
426
499
  templates: resolveRoot(manifest.templates),
@@ -441,5 +514,5 @@ export async function loadIntegrations(
441
514
  });
442
515
  }
443
516
 
444
- return integrations;
517
+ return resolveProviders ? markProviderConflicts(integrations) : integrations;
445
518
  }