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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (643) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/README.md +117 -78
  3. package/api/blog/blog.doc.mjs +1 -0
  4. package/api/build/_adapter.d.mts +50 -0
  5. package/api/build/_adapter.mjs +60 -0
  6. package/api/build/build.doc.mjs +16 -9
  7. package/api/build/build.test.mjs +197 -8
  8. package/api/build/build.type.d.mts +91 -2
  9. package/api/build/build.type.mjs +52 -8
  10. package/api/build/help/help.d.mts +12 -5
  11. package/api/build/help/help.mjs +69 -6
  12. package/api/build/kit/kit.d.mts +4 -1
  13. package/api/build/kit/kit.mjs +165 -49
  14. package/api/build/kit/rank.d.mts +44 -0
  15. package/api/build/kit/rank.mjs +432 -0
  16. package/api/build/kit/rank.test.mjs +196 -0
  17. package/api/component/_adapter.d.mts +6 -12
  18. package/api/component/_adapter.mjs +20 -10
  19. package/api/component/component.doc.mjs +13 -3
  20. package/api/component/component.mjs +91 -14
  21. package/api/component/component.test.mjs +38 -0
  22. package/api/component/component.type.d.mts +22 -11
  23. package/api/component/component.type.mjs +32 -24
  24. package/api/component/detail/blocks/blocks.d.mts +2 -1
  25. package/api/component/detail/blocks/blocks.mjs +4 -3
  26. package/api/component/list/list.d.mts +0 -5
  27. package/api/component/list/list.mjs +40 -11
  28. package/api/discover/_adapter.d.mts +114 -6
  29. package/api/discover/_adapter.mjs +372 -17
  30. package/api/discover/_adapter.test.mjs +215 -0
  31. package/api/discover/_catalog-view.d.mts +115 -0
  32. package/api/discover/_catalog-view.mjs +203 -0
  33. package/api/discover/_catalog-view.test.mjs +128 -0
  34. package/api/discover/detail/detail.d.mts +18 -6
  35. package/api/discover/detail/detail.mjs +67 -13
  36. package/api/discover/detail/detail.test.mjs +85 -0
  37. package/api/discover/detail/item/item.d.mts +26 -0
  38. package/api/discover/detail/item/item.mjs +78 -0
  39. package/api/discover/detail/item/item.test.mjs +73 -0
  40. package/api/discover/discover.d.mts +3 -9
  41. package/api/discover/discover.doc.mjs +62 -18
  42. package/api/discover/discover.mjs +220 -36
  43. package/api/discover/discover.test.mjs +11 -2
  44. package/api/discover/discover.type.d.mts +150 -11
  45. package/api/discover/discover.type.mjs +107 -17
  46. package/api/discover/list/list.d.mts +20 -6
  47. package/api/discover/list/list.mjs +45 -12
  48. package/api/discover/list/list.test.mjs +46 -0
  49. package/api/discover/search/search.d.mts +18 -16
  50. package/api/discover/search/search.mjs +102 -56
  51. package/api/discover/search/search.test.mjs +144 -10
  52. package/api/docs/_adapter.d.mts +272 -41
  53. package/api/docs/_adapter.mjs +985 -108
  54. package/api/docs/compiled-topics.test.mjs +78 -0
  55. package/api/docs/detail/detail.mjs +22 -63
  56. package/api/docs/detail/section/section.d.mts +1 -1
  57. package/api/docs/detail/section/section.mjs +54 -19
  58. package/api/docs/detail/section/section.test.mjs +50 -0
  59. package/api/docs/docs.d.mts +10 -3
  60. package/api/docs/docs.doc.mjs +55 -16
  61. package/api/docs/docs.mjs +53 -10
  62. package/api/docs/docs.test.mjs +164 -4
  63. package/api/docs/docs.type.d.mts +221 -5
  64. package/api/docs/docs.type.mjs +153 -11
  65. package/api/docs/index/index.d.mts +18 -0
  66. package/api/docs/index/index.mjs +40 -0
  67. package/api/docs/index/index.test.mjs +62 -0
  68. package/api/docs/integration-tree.test.mjs +555 -0
  69. package/api/docs/integrationDocs.test.mjs +114 -8
  70. package/api/docs/list/list.mjs +28 -12
  71. package/api/docs/node/node.d.mts +43 -0
  72. package/api/docs/node/node.mjs +192 -0
  73. package/api/docs/reference-blocks.test.mjs +406 -0
  74. package/api/doctor/doctor.d.mts +99 -1
  75. package/api/doctor/doctor.doc.mjs +1 -0
  76. package/api/doctor/doctor.mjs +548 -1
  77. package/api/doctor/doctor.test.mjs +610 -1
  78. package/api/gap-report/gap-report.doc.mjs +8 -4
  79. package/api/hook/_adapter.mjs +19 -5
  80. package/api/hook/hook.doc.mjs +1 -0
  81. package/api/hook/hook.type.d.mts +3 -3
  82. package/api/hook/hook.type.mjs +11 -11
  83. package/api/hook/list/list.d.mts +2 -2
  84. package/api/hook/list/list.mjs +69 -17
  85. package/api/index.d.mts +1 -1
  86. package/api/index.mjs +1 -0
  87. package/api/init/init.doc.mjs +6 -1
  88. package/api/init/init.test.mjs +41 -1
  89. package/api/init/remove/remove.mjs +1 -1
  90. package/api/init/run/run.mjs +20 -10
  91. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  92. package/api/integration/add-contribution.d.mts +2 -1
  93. package/api/integration/add-contribution.mjs +130 -15
  94. package/api/integration/add-contribution.test.mjs +258 -7
  95. package/api/integration/add-helpers.d.mts +5 -2
  96. package/api/integration/add-helpers.mjs +36 -9
  97. package/api/integration/add-theme.mjs +34 -64
  98. package/api/integration/add-theme.test.mjs +105 -21
  99. package/api/integration/authoring-checks.mjs +138 -28
  100. package/api/integration/authoring-checks.test.mjs +179 -7
  101. package/api/integration/authoring-checks.type.mjs +6 -1
  102. package/api/integration/integration-authoring.type.d.mts +3 -1
  103. package/api/integration/integration-authoring.type.mjs +2 -0
  104. package/api/integration/integration-block-exports.test.mjs +10 -6
  105. package/api/integration/integrationAdd.doc.mjs +14 -4
  106. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  107. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  108. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  109. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  110. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  111. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  112. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  113. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  114. package/api/integration/integrationPackCheck.doc.mjs +2 -1
  115. package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
  116. package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
  117. package/api/integration/pack-check.mjs +83 -7
  118. package/api/integration/pack-check.test.mjs +387 -47
  119. package/api/integration/pack-check.type.d.mts +26 -2
  120. package/api/integration/pack-check.type.mjs +14 -1
  121. package/api/integration/summarizeIssues.doc.mjs +1 -0
  122. package/api/integration/template-conflict-compatibility.test.mjs +73 -0
  123. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  124. package/api/integration/validate-integration.mjs +52 -102
  125. package/api/integration/validate-integration.test.mjs +179 -26
  126. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  127. package/api/integration/validateIntegration.doc.mjs +3 -2
  128. package/api/json/assertResponse.doc.mjs +1 -0
  129. package/api/json/envelope-types.test.mjs +76 -0
  130. package/api/json/index.ts +2 -0
  131. package/api/json/isError.doc.mjs +1 -0
  132. package/api/json/parseResponse.doc.mjs +3 -2
  133. package/api/layout/_adapter.mjs +20 -5
  134. package/api/layout/expand/expand.mjs +7 -5
  135. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  136. package/api/layout/grammar/grammar.mjs +2 -1
  137. package/api/layout/layoutCheck.doc.mjs +1 -0
  138. package/api/layout/layoutExpand.doc.mjs +2 -1
  139. package/api/layout/layoutGrammar.doc.mjs +1 -0
  140. package/api/search/search-return-type.test.mjs +54 -0
  141. package/api/search/search.d.mts +62 -11
  142. package/api/search/search.doc.mjs +8 -2
  143. package/api/search/search.mjs +471 -83
  144. package/api/search/search.test.mjs +124 -1
  145. package/api/search/search.type.d.mts +15 -3
  146. package/api/search/search.type.mjs +5 -2
  147. package/api/swizzle/copy/copy.mjs +28 -11
  148. package/api/swizzle/swizzle.doc.mjs +2 -1
  149. package/api/swizzle/swizzle.type.d.mts +2 -2
  150. package/api/swizzle/swizzle.type.mjs +2 -2
  151. package/api/template/copy/copy.mjs +17 -23
  152. package/api/template/copy/copy.test.mjs +17 -0
  153. package/api/template/list/list.mjs +1 -0
  154. package/api/template/table-floating-bulk-actions.test.mjs +66 -0
  155. package/api/template/template-integration.test.mjs +1072 -3
  156. package/api/template/template-suffix.test.mjs +41 -21
  157. package/api/template/template.d.mts +1 -1
  158. package/api/template/template.doc.mjs +30 -8
  159. package/api/template/template.mjs +45 -8
  160. package/api/template/template.type.d.mts +12 -14
  161. package/api/template/template.type.mjs +15 -14
  162. package/api/theme/_adapter.d.mts +2 -3
  163. package/api/theme/_adapter.mjs +4 -5
  164. package/api/theme/add/add.binary.test.mjs +84 -0
  165. package/api/theme/add/add.mjs +31 -22
  166. package/api/theme/add/add.rollback.test.mjs +158 -0
  167. package/api/theme/add/add.staging.test.mjs +83 -0
  168. package/api/theme/add/add.test.mjs +14 -1
  169. package/api/theme/build/build.family.test.mjs +7 -12
  170. package/api/theme/build/build.mjs +140 -59
  171. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  172. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  173. package/api/theme/build/build.rollback.test.mjs +148 -0
  174. package/api/theme/build/build.test.mjs +127 -0
  175. package/api/theme/build/font-warning.mjs +3 -3
  176. package/api/theme/build/font-warning.test.mjs +5 -2
  177. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  178. package/api/theme/integration-themes.test.mjs +39 -28
  179. package/api/theme/list/list.test.mjs +19 -20
  180. package/api/theme/listThemes.doc.mjs +6 -5
  181. package/api/theme/palette/generate/generate.mjs +8 -3
  182. package/api/theme/palette/generate/generate.test.mjs +96 -0
  183. package/api/theme/palette/generate/generator.d.mts +10 -13
  184. package/api/theme/palette/generate/generator.mjs +15 -4
  185. package/api/theme/palette/generate/generator.test.mjs +10 -0
  186. package/api/theme/template/template.mjs +11 -2
  187. package/api/theme/template/template.test.mjs +20 -0
  188. package/api/theme/theme.type.d.mts +170 -11
  189. package/api/theme/theme.type.mjs +94 -27
  190. package/api/theme/themeAdd.doc.mjs +4 -3
  191. package/api/theme/themeBuild.doc.mjs +8 -4
  192. package/api/theme/themeList.doc.mjs +6 -3
  193. package/api/theme/themeListAvailable.doc.mjs +5 -3
  194. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  195. package/api/theme/themeTargets.doc.mjs +1 -0
  196. package/api/theme/themeTemplate.doc.mjs +6 -2
  197. package/api/upgrade/_adapter.d.mts +32 -5
  198. package/api/upgrade/_adapter.mjs +139 -22
  199. package/api/upgrade/list/list.mjs +2 -1
  200. package/api/upgrade/list/list.test.mjs +73 -0
  201. package/api/upgrade/project-context.test.mjs +272 -0
  202. package/api/upgrade/provider-agreement.test.mjs +152 -0
  203. package/api/upgrade/run/run.mjs +356 -59
  204. package/api/upgrade/status/status.mjs +2 -2
  205. package/api/upgrade/upgrade.doc.mjs +12 -5
  206. package/api/upgrade/upgrade.type.d.mts +43 -5
  207. package/api/upgrade/upgrade.type.mjs +27 -11
  208. package/assets/codemods/__tests__/registry.test.mjs +1 -0
  209. package/assets/codemods/__tests__/runner.test.mjs +330 -8
  210. package/assets/codemods/integration-discovery.mjs +48 -4
  211. package/assets/codemods/integration-discovery.test.mjs +73 -0
  212. package/assets/codemods/integration-runner.mjs +56 -4
  213. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  214. package/assets/codemods/registry.mjs +1 -0
  215. package/assets/codemods/run-codemod.mjs +177 -34
  216. package/assets/codemods/runner.mjs +350 -102
  217. package/assets/codemods/term-log.mjs +32 -8
  218. package/assets/codemods/term-log.test.mjs +19 -1
  219. package/assets/codemods/transform-prop.mjs +109 -0
  220. package/assets/codemods/transform-prop.test.mjs +95 -0
  221. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  222. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  223. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  224. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  225. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  226. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  227. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  228. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  229. package/assets/codemods/transforms/v0.6.4/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  230. package/assets/codemods/transforms/v0.6.4/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  231. package/assets/codemods/transforms/v0.6.4/index.mjs +31 -0
  232. package/assets/codemods/transforms/v0.6.4/migrate-native-picker-to-presentation.mjs +148 -0
  233. package/assets/codemods/transforms/v0.6.4/migrate-theme-catalog-to-descriptors.mjs +141 -0
  234. package/assets/docs/README.md +9 -0
  235. package/assets/docs/authoring.doc.mjs +14 -0
  236. package/assets/docs/getting-started.doc.mjs +2 -2
  237. package/assets/docs/internationalization.doc.mjs +7 -5
  238. package/assets/docs/layout.doc.dense.mjs +2 -2
  239. package/assets/docs/layout.doc.mjs +1 -1
  240. package/assets/docs/principles.doc.mjs +6 -6
  241. package/assets/docs/styling-libraries.doc.mjs +4 -4
  242. package/assets/docs/styling.doc.mjs +4 -4
  243. package/assets/docs/theme.doc.mjs +5 -5
  244. package/assets/docs/tokens.doc.mjs +1 -1
  245. package/assets/docs/tree/api.doc.mjs +30 -0
  246. package/assets/docs/tree/cli.doc.mjs +23 -0
  247. package/assets/docs/tree/commands.doc.mjs +25 -0
  248. package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +144 -26
  249. package/assets/docs/tree/integrations.test.mjs +62 -0
  250. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  251. package/assets/docs/working-with-ai.doc.mjs +4 -4
  252. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
  253. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
  254. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  255. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  256. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  257. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  258. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  259. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  260. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  261. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  262. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  263. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  264. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  265. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  266. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  267. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  268. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  269. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  270. package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
  271. package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
  272. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
  273. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
  274. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  275. package/assets/templates/blocks/components/Timer/TimerFormats.doc.mjs +14 -0
  276. package/assets/templates/blocks/components/Timer/TimerFormats.tsx +34 -0
  277. package/assets/templates/blocks/components/Timer/TimerInline.doc.mjs +14 -0
  278. package/assets/templates/blocks/components/Timer/TimerInline.tsx +14 -0
  279. package/assets/templates/blocks/components/Timer/TimerShowcase.doc.mjs +13 -0
  280. package/assets/templates/blocks/components/Timer/TimerShowcase.tsx +47 -0
  281. package/assets/templates/blocks/components/Timer/TimerTypography.doc.mjs +14 -0
  282. package/assets/templates/blocks/components/Timer/TimerTypography.tsx +31 -0
  283. package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.doc.mjs +19 -3
  284. package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +383 -65
  285. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  286. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  287. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  288. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  289. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  290. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  291. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  292. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  293. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  294. package/authoring/_shared/contract.ts +22 -0
  295. package/authoring/codemod/codemod.doc.mjs +7 -2
  296. package/authoring/codemod/parse.d.mts +8 -8
  297. package/authoring/codemod/parse.mjs +8 -6
  298. package/authoring/codemod/type.ts +12 -0
  299. package/authoring/config/config.doc.mjs +10 -2
  300. package/authoring/config/debug-composition.test.mjs +92 -0
  301. package/authoring/config/parse.d.mts +15 -13
  302. package/authoring/config/parse.mjs +27 -8
  303. package/authoring/config/parse.test.mjs +8 -0
  304. package/authoring/config/type.ts +29 -6
  305. package/authoring/debug/debug.doc.d.mts +11 -0
  306. package/authoring/debug/debug.doc.mjs +182 -0
  307. package/authoring/debug/parse.d.mts +8 -8
  308. package/authoring/debug/parse.mjs +3 -3
  309. package/authoring/discover/discover.doc.d.mts +13 -0
  310. package/authoring/discover/discover.doc.mjs +138 -0
  311. package/authoring/discover/parse.d.mts +24 -0
  312. package/authoring/discover/parse.mjs +128 -0
  313. package/authoring/discover/parse.test.mjs +124 -0
  314. package/authoring/discover/type.ts +87 -0
  315. package/authoring/doctypes/_schema.d.mts +790 -23
  316. package/authoring/doctypes/_schema.mjs +543 -39
  317. package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
  318. package/authoring/doctypes/base/graph-fields.doc.mjs +64 -0
  319. package/authoring/doctypes/base/type.ts +41 -0
  320. package/authoring/doctypes/command/command.doc.mjs +4 -3
  321. package/authoring/doctypes/command/parse.d.mts +2 -2
  322. package/authoring/doctypes/command/parse.mjs +1 -1
  323. package/authoring/doctypes/command/type.ts +5 -4
  324. package/authoring/doctypes/component/component.doc.mjs +6 -3
  325. package/authoring/doctypes/component/parse.d.mts +2 -2
  326. package/authoring/doctypes/component/parse.mjs +1 -1
  327. package/authoring/doctypes/component/type.ts +6 -5
  328. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  329. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  330. package/authoring/doctypes/enum/parse.d.mts +2 -2
  331. package/authoring/doctypes/enum/parse.mjs +1 -1
  332. package/authoring/doctypes/enum/type.ts +4 -2
  333. package/authoring/doctypes/function/function.doc.mjs +7 -2
  334. package/authoring/doctypes/function/parse.d.mts +2 -2
  335. package/authoring/doctypes/function/parse.mjs +1 -1
  336. package/authoring/doctypes/function/type.ts +9 -4
  337. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  338. package/authoring/doctypes/hook/parse.d.mts +2 -2
  339. package/authoring/doctypes/hook/parse.mjs +1 -1
  340. package/authoring/doctypes/hook/type.ts +5 -4
  341. package/authoring/doctypes/legacy.d.mts +8 -6
  342. package/authoring/doctypes/legacy.mjs +5 -4
  343. package/authoring/doctypes/load-contract.test.mjs +233 -0
  344. package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
  345. package/authoring/doctypes/namespace/namespace.doc.mjs +128 -0
  346. package/authoring/doctypes/namespace/parse.d.mts +12 -0
  347. package/authoring/doctypes/namespace/parse.mjs +25 -0
  348. package/authoring/doctypes/namespace/parse.test.mjs +163 -0
  349. package/authoring/doctypes/namespace/type.ts +74 -0
  350. package/authoring/doctypes/parse.d.mts +22 -18
  351. package/authoring/doctypes/parse.mjs +22 -11
  352. package/authoring/doctypes/parse.test.mjs +77 -3
  353. package/authoring/doctypes/reference/parse.d.mts +2 -2
  354. package/authoring/doctypes/reference/parse.mjs +8 -5
  355. package/authoring/doctypes/reference/reference.doc.mjs +48 -6
  356. package/authoring/doctypes/reference/type.ts +70 -7
  357. package/authoring/doctypes/schema/parse.d.mts +2 -2
  358. package/authoring/doctypes/schema/parse.mjs +1 -1
  359. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  360. package/authoring/doctypes/schema/type.ts +4 -4
  361. package/authoring/doctypes/template/parse.d.mts +94 -1
  362. package/authoring/doctypes/template/parse.mjs +40 -2
  363. package/authoring/doctypes/template/parse.test.mjs +26 -2
  364. package/authoring/doctypes/template/template.doc.mjs +13 -3
  365. package/authoring/doctypes/template/type.ts +13 -2
  366. package/authoring/doctypes/theme/parse.d.mts +35 -0
  367. package/authoring/doctypes/theme/parse.mjs +76 -0
  368. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  369. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  370. package/authoring/doctypes/theme/type.ts +42 -0
  371. package/authoring/doctypes/types.ts +12 -10
  372. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  373. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  374. package/authoring/gap-report/parse.d.mts +10 -10
  375. package/authoring/gap-report/parse.mjs +6 -6
  376. package/authoring/gap-report/type.ts +1 -1
  377. package/authoring/identity/identity.doc.d.mts +9 -0
  378. package/authoring/identity/identity.doc.mjs +61 -0
  379. package/authoring/identity/type.ts +132 -0
  380. package/authoring/index.d.mts +3 -0
  381. package/authoring/index.d.ts +62 -17
  382. package/authoring/index.mjs +4 -1
  383. package/authoring/integration/integration.doc.mjs +15 -8
  384. package/authoring/integration/parse.d.mts +2 -2
  385. package/authoring/integration/parse.mjs +1 -1
  386. package/authoring/integration/parse.test.mjs +10 -1
  387. package/authoring/integration/schema.d.mts +6 -4
  388. package/authoring/integration/schema.mjs +9 -3
  389. package/authoring/integration/type.ts +19 -8
  390. package/authoring/shadcn/receipt.d.mts +6 -6
  391. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  392. package/clients/cli/command-load-failure.test.mjs +83 -0
  393. package/clients/cli/commands/blog.doc.mjs +1 -1
  394. package/clients/cli/commands/blog.mjs +23 -8
  395. package/clients/cli/commands/blog.test.mjs +42 -1
  396. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  397. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  398. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  399. package/clients/cli/commands/build-theme.mjs +16 -50
  400. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  401. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  402. package/clients/cli/commands/build.doc.mjs +16 -8
  403. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  404. package/clients/cli/commands/build.mjs +137 -114
  405. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  406. package/clients/cli/commands/build.text-fields.test.mjs +81 -0
  407. package/clients/cli/commands/component/index.mjs +3 -8
  408. package/clients/cli/commands/component-ownership.test.mjs +3 -3
  409. package/clients/cli/commands/component-package.test.mjs +46 -0
  410. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  411. package/clients/cli/commands/component.doc.mjs +1 -1
  412. package/clients/cli/commands/component.test.mjs +19 -0
  413. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  414. package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
  415. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  416. package/clients/cli/commands/discover.doc.mjs +55 -9
  417. package/clients/cli/commands/discover.mjs +393 -118
  418. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  419. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  420. package/clients/cli/commands/docs.doc.mjs +28 -6
  421. package/clients/cli/commands/docs.mjs +240 -26
  422. package/clients/cli/commands/docs.test.mjs +193 -1
  423. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  424. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
  425. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  426. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  427. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  428. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  429. package/clients/cli/commands/doctor-integration.test.mjs +90 -8
  430. package/clients/cli/commands/doctor.doc.mjs +1 -1
  431. package/clients/cli/commands/doctor.mjs +59 -32
  432. package/clients/cli/commands/doctor.test.mjs +42 -0
  433. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  434. package/clients/cli/commands/gap-report.test.mjs +72 -0
  435. package/clients/cli/commands/hook/index.mjs +7 -17
  436. package/clients/cli/commands/hook.doc.mjs +1 -1
  437. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  438. package/clients/cli/commands/init.doc.mjs +20 -9
  439. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  440. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  441. package/clients/cli/commands/integration-add.doc.mjs +32 -6
  442. package/clients/cli/commands/integration-authoring.test.mjs +13 -9
  443. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  444. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  445. package/clients/cli/commands/integration.doc.mjs +1 -1
  446. package/clients/cli/commands/integration.mjs +1 -0
  447. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  448. package/clients/cli/commands/json-contract.test.mjs +33 -0
  449. package/clients/cli/commands/layout-check.doc.mjs +15 -4
  450. package/clients/cli/commands/layout-expand.doc.mjs +22 -5
  451. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  452. package/clients/cli/commands/layout.doc.mjs +3 -3
  453. package/clients/cli/commands/layout.mjs +21 -9
  454. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  455. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  456. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  457. package/clients/cli/commands/manifest.doc.mjs +1 -1
  458. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  459. package/clients/cli/commands/search.doc.mjs +7 -4
  460. package/clients/cli/commands/search.mjs +28 -9
  461. package/clients/cli/commands/search.test.mjs +75 -0
  462. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  463. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  464. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  465. package/clients/cli/commands/template.doc.mjs +52 -13
  466. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  467. package/clients/cli/commands/template.mjs +4 -91
  468. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  469. package/clients/cli/commands/text-json-parity.test.mjs +719 -0
  470. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  471. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  472. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  473. package/clients/cli/commands/theme-palette-generate.doc.mjs +9 -5
  474. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  475. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  476. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  477. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  478. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  479. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  480. package/clients/cli/commands/theme.doc.mjs +1 -1
  481. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  482. package/clients/cli/commands/upgrade.doc.mjs +22 -10
  483. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  484. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  485. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  486. package/clients/cli/commands/upgrade.mjs +29 -7
  487. package/clients/cli/formatters/index.mjs +164 -1
  488. package/clients/cli/formatters/index.test.mjs +97 -0
  489. package/clients/cli/index.mjs +21 -30
  490. package/clients/cli/latest-version-env.test.mjs +50 -0
  491. package/clients/cli/lib/cli-error.test.mjs +7 -0
  492. package/clients/cli/lib/component-format.mjs +9 -9
  493. package/clients/cli/lib/component-format.test.mjs +1 -1
  494. package/clients/cli/lib/define-command.mjs +32 -6
  495. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  496. package/clients/cli/lib/exit-codes.test.mjs +97 -0
  497. package/clients/cli/lib/hook-format.mjs +19 -10
  498. package/clients/cli/lib/json-shim.mjs +38 -2
  499. package/clients/cli/lib/json-shim.test.mjs +83 -0
  500. package/clients/cli/lib/manifest.d.ts +2 -0
  501. package/clients/cli/lib/manifest.mjs +37 -2
  502. package/clients/cli/lib/manifest.test.mjs +17 -0
  503. package/foundation/agent-docs/agent-docs.d.mts +7 -2
  504. package/foundation/agent-docs/agent-docs.mjs +82 -12
  505. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  506. package/foundation/agent-docs/agent-docs.test.mjs +19 -1
  507. package/foundation/config/integration-debug.test.mjs +28 -3
  508. package/foundation/config/project-themes.test.mjs +11 -19
  509. package/foundation/config/project.d.mts +20 -11
  510. package/foundation/config/project.mjs +263 -91
  511. package/foundation/config/project.test.mjs +270 -21
  512. package/foundation/discovery/authoring-self-docs.d.mts +87 -0
  513. package/foundation/discovery/authoring-self-docs.mjs +237 -0
  514. package/foundation/discovery/authoring-self-docs.test.mjs +170 -0
  515. package/foundation/discovery/authoring-surface.d.mts +74 -0
  516. package/foundation/discovery/authoring-surface.mjs +525 -0
  517. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  518. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  519. package/foundation/discovery/cli-self-docs.mjs +490 -0
  520. package/foundation/discovery/cli-self-docs.test.mjs +375 -0
  521. package/foundation/discovery/component-discovery.d.mts +39 -1
  522. package/foundation/discovery/component-discovery.mjs +50 -1
  523. package/foundation/discovery/component-loader.d.mts +35 -38
  524. package/foundation/discovery/component-loader.mjs +53 -222
  525. package/foundation/discovery/docs-discovery.d.mts +119 -11
  526. package/foundation/discovery/docs-discovery.mjs +423 -108
  527. package/foundation/discovery/docs-discovery.test.mjs +365 -20
  528. package/foundation/discovery/docs-output-budget.d.mts +28 -0
  529. package/foundation/discovery/docs-output-budget.mjs +50 -0
  530. package/foundation/discovery/docs-section-key.d.mts +116 -0
  531. package/foundation/discovery/docs-section-key.mjs +322 -0
  532. package/foundation/discovery/docs-section-key.test.mjs +246 -0
  533. package/foundation/discovery/template-adapter.d.mts +113 -11
  534. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  535. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  536. package/foundation/discovery/template-adapter.mjs +774 -83
  537. package/foundation/discovery/template-adapter.test.mjs +57 -0
  538. package/foundation/discovery/template-conflict-release.d.mts +13 -0
  539. package/foundation/discovery/template-conflict-release.mjs +40 -0
  540. package/foundation/discovery/template-conflict-release.test.mjs +40 -0
  541. package/foundation/discovery/theme-discovery.d.mts +67 -7
  542. package/foundation/discovery/theme-discovery.mjs +916 -186
  543. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  544. package/foundation/discovery/theming-targets.test.mjs +4 -0
  545. package/foundation/doc-compiler/bundle.d.mts +47 -0
  546. package/foundation/doc-compiler/bundle.mjs +278 -0
  547. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  548. package/foundation/doc-compiler/compile.d.mts +343 -0
  549. package/foundation/doc-compiler/compile.mjs +558 -0
  550. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  551. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  552. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  553. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  554. package/foundation/doc-compiler/import.d.mts +24 -0
  555. package/foundation/doc-compiler/import.mjs +59 -0
  556. package/foundation/doc-compiler/inputs.d.mts +102 -0
  557. package/foundation/doc-compiler/inputs.mjs +291 -0
  558. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  559. package/foundation/doc-compiler/ir.d.mts +22 -0
  560. package/foundation/doc-compiler/ir.mjs +471 -0
  561. package/foundation/doc-compiler/lenses.d.mts +36 -0
  562. package/foundation/doc-compiler/lenses.mjs +173 -0
  563. package/foundation/doc-compiler/links.d.mts +162 -0
  564. package/foundation/doc-compiler/links.mjs +294 -0
  565. package/foundation/doc-compiler/links.test.mjs +192 -0
  566. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  567. package/foundation/doc-compiler/overlays.d.mts +37 -0
  568. package/foundation/doc-compiler/overlays.mjs +206 -0
  569. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  570. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  571. package/foundation/doc-compiler/read.d.mts +127 -0
  572. package/foundation/doc-compiler/read.mjs +325 -0
  573. package/foundation/doc-compiler/read.test.mjs +313 -0
  574. package/foundation/doc-compiler/source.d.mts +33 -0
  575. package/foundation/doc-compiler/source.mjs +128 -0
  576. package/foundation/doc-compiler/tree.d.mts +288 -0
  577. package/foundation/doc-compiler/tree.mjs +876 -0
  578. package/foundation/doc-compiler/tree.test.mjs +598 -0
  579. package/foundation/fs/file-protection.d.mts +33 -0
  580. package/foundation/fs/file-protection.mjs +825 -0
  581. package/foundation/fs/file-protection.test.mjs +250 -0
  582. package/foundation/fs/module-loader.d.mts +1 -0
  583. package/foundation/fs/module-loader.mjs +50 -1
  584. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  585. package/foundation/fs/path-safety.d.mts +3 -2
  586. package/foundation/fs/path-safety.mjs +49 -19
  587. package/foundation/fs/path-safety.test.mjs +50 -0
  588. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  589. package/foundation/identity/provider-identity.d.mts +90 -0
  590. package/foundation/identity/provider-identity.mjs +320 -0
  591. package/foundation/identity/provider-identity.test.mjs +254 -0
  592. package/foundation/identity/providers.d.mts +7 -0
  593. package/foundation/identity/providers.mjs +16 -0
  594. package/foundation/integrations/autolink.d.mts +58 -1
  595. package/foundation/integrations/autolink.mjs +143 -45
  596. package/foundation/integrations/autolink.test.mjs +1 -1
  597. package/foundation/integrations/cli-requirement.d.mts +45 -0
  598. package/foundation/integrations/cli-requirement.mjs +154 -0
  599. package/foundation/integrations/cli-requirement.test.mjs +84 -0
  600. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  601. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  602. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  603. package/foundation/integrations/contribution-inventory.mjs +27 -24
  604. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  605. package/foundation/integrations/integration-warnings.d.mts +9 -2
  606. package/foundation/integrations/integration-warnings.mjs +52 -21
  607. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  608. package/foundation/integrations/integrations.d.mts +63 -3
  609. package/foundation/integrations/integrations.mjs +122 -9
  610. package/foundation/integrations/integrations.test.mjs +415 -1
  611. package/foundation/integrations/provider-conflicts.test.mjs +125 -0
  612. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  613. package/foundation/integrations/provider-resolution.d.mts +152 -0
  614. package/foundation/integrations/provider-resolution.mjs +576 -0
  615. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  616. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  617. package/foundation/integrations/theme-descriptor.mjs +44 -0
  618. package/foundation/integrations/validate-contributions.d.mts +2 -0
  619. package/foundation/integrations/validate-contributions.mjs +131 -29
  620. package/foundation/response/base.d.ts +8 -4
  621. package/foundation/response/error-codes.d.mts +3 -1
  622. package/foundation/response/error-codes.d.ts +2 -0
  623. package/foundation/response/error-codes.doc.mjs +13 -4
  624. package/foundation/response/error-codes.mjs +8 -2
  625. package/foundation/response/error-codes.test.mjs +137 -10
  626. package/foundation/response/json-contract.test.mjs +57 -17
  627. package/foundation/response/json.d.mts +4 -2
  628. package/foundation/response/json.mjs +8 -10
  629. package/foundation/response/response-types.doc.d.mts +5 -1
  630. package/foundation/response/response-types.doc.mjs +41 -21
  631. package/foundation/response/response-types.doc.test.mjs +158 -0
  632. package/foundation/response/response.doc.mjs +1 -1
  633. package/foundation/text/string-utils.d.mts +8 -0
  634. package/foundation/text/string-utils.mjs +40 -10
  635. package/foundation/xle/expand.d.mts +2 -0
  636. package/foundation/xle/expand.mjs +4 -3
  637. package/foundation/xle/expand.test.mjs +54 -0
  638. package/foundation/xle/xle.test.mjs +13 -0
  639. package/package.json +10 -11
  640. package/assets/templates/themes/manifest.json +0 -95
  641. package/clients/cli/lib/update-check.mjs +0 -83
  642. package/clients/cli/lib/update-check.test.mjs +0 -137
  643. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -27,6 +27,11 @@ import {spawnSync} from 'node:child_process';
27
27
  import jscodeshift from 'jscodeshift';
28
28
  import {assertWithin} from '../../foundation/fs/path-safety.mjs';
29
29
  import {resolvePackageDir} from '../../foundation/integrations/integrations.mjs';
30
+ import {
31
+ docsTreeCliProblem,
32
+ replacesCliProblem,
33
+ } from '../../foundation/integrations/cli-requirement.mjs';
34
+ import {discoverIntegrationDocs} from '../../foundation/discovery/docs-discovery.mjs';
30
35
  import {
31
36
  discoverIntegrationComponents,
32
37
  resolveIntegrationImportPath,
@@ -388,6 +393,14 @@ async function validatePackedComponentExports(integration, scratchBase) {
388
393
  components.map(component => component.specifier),
389
394
  scratchBase,
390
395
  );
396
+ issues.push(
397
+ ...validateSpecifierExtensions(
398
+ components.map(({name, specifier}) => ({
399
+ label: `Component "${name}"`,
400
+ specifier,
401
+ })),
402
+ ),
403
+ );
391
404
  for (const {name, specifier} of components) {
392
405
  const result = resolved.get(specifier);
393
406
  if (!result?.url || result.error) {
@@ -427,19 +440,27 @@ async function validatePackedComponentExports(integration, scratchBase) {
427
440
  */
428
441
  async function validatePackedTemplateExports(integration, scratchBase) {
429
442
  const {templates} = await discoverIntegrationTemplatesForOne(integration);
430
- const entries = templates.map(template => ({
431
- id: template.dirName,
432
- specifier: `${integration.name}/${path
443
+ const entries = templates.map(template => {
444
+ const relPath = path
433
445
  .relative(integration.__packageDir, template.filePath)
434
446
  .split(path.sep)
435
- .join('/')}`,
436
- }));
447
+ .join('/');
448
+ const extensionless = relPath.replace(/\.tsx?$/u, '');
449
+ return {
450
+ id: template.dirName,
451
+ specifier: `${integration.name}/${extensionless}`,
452
+ };
453
+ });
437
454
  const resolved = resolveConsumerSpecifiers(
438
455
  entries.map(entry => entry.specifier),
439
456
  scratchBase,
440
457
  );
441
- /** @type {Issue[]} */
442
- const issues = [];
458
+ const issues = validateSpecifierExtensions(
459
+ entries.map(({id, specifier}) => ({
460
+ label: `Template "${id}"`,
461
+ specifier,
462
+ })),
463
+ );
443
464
  for (const {id, specifier} of entries) {
444
465
  const result = resolved.get(specifier);
445
466
  if (!result?.url || result.error) {
@@ -469,6 +490,32 @@ async function validatePackedTemplateExports(integration, scratchBase) {
469
490
  return issues;
470
491
  }
471
492
 
493
+ const TS_EXTENSION_RE = /\.tsx?$/u;
494
+
495
+ /**
496
+ * Reject specifiers that end in a TypeScript extension — they fail under
497
+ * default `moduleResolution` with TS5097/TS2307 unless the consumer enables
498
+ * `allowImportingTsExtensions`.
499
+ *
500
+ * @param {Array<{label: string, specifier: string}>} entries
501
+ * @returns {Issue[]}
502
+ */
503
+ function validateSpecifierExtensions(entries) {
504
+ /** @type {Issue[]} */
505
+ const issues = [];
506
+ for (const {label, specifier} of entries) {
507
+ if (TS_EXTENSION_RE.test(specifier)) {
508
+ issues.push(
509
+ error(
510
+ 'typescript_extension_in_specifier',
511
+ `${label} advertises import "${specifier}", which ends in a TypeScript extension. A consumer with default moduleResolution will reject it (TS5097). Use an extensionless specifier mapped through the package exports.`,
512
+ ),
513
+ );
514
+ }
515
+ }
516
+ return issues;
517
+ }
518
+
472
519
  /**
473
520
  * Verify an integration package is ready to publish.
474
521
  *
@@ -549,6 +596,35 @@ export async function integrationPackCheck(options = {}) {
549
596
  );
550
597
  }
551
598
  }
599
+ // A namespace doc or a placed guide needs a CLI that reads the docs tree
600
+ // (spec:AST-046 FR11): an older CLI can hide every doc topic the package
601
+ // ships, so the declared CLI range must admit only CLIs that read it.
602
+ if (loaded.docs) {
603
+ const {namespaces, guides} = await discoverIntegrationDocs(loaded).catch(
604
+ () => ({namespaces: [], guides: []}),
605
+ );
606
+ const problem =
607
+ namespaces.length > 0 || guides.length > 0
608
+ ? docsTreeCliProblem(pkg)
609
+ : null;
610
+ if (problem != null) {
611
+ issues.push(error('docs_tree_needs_cli', problem));
612
+ }
613
+ }
614
+ // A template that sets `replaces` needs a CLI that reads the field
615
+ // (spec:AST-035): an older CLI withholds the package's templates and docs.
616
+ if (loaded.templates) {
617
+ const found = await discoverIntegrationTemplatesForOne(loaded).catch(
618
+ () => ({templates: [], errors: []}),
619
+ );
620
+ const setsReplaces =
621
+ found.templates.some(template => template.replaces != null) ||
622
+ found.errors.some(
623
+ (/** @type {any} */ issue) => issue.replacementTarget != null,
624
+ );
625
+ const problem = setsReplaces ? replacesCliProblem(pkg) : null;
626
+ if (problem != null) issues.push(error('replaces_needs_cli', problem));
627
+ }
552
628
 
553
629
  // Temp resources — always cleaned up
554
630
  const tgzTmpDir = fs.mkdtempSync(
@@ -53,25 +53,10 @@ function writePackage({
53
53
  "import {defineTheme} from '@astryxdesign/core/theme';\n\nexport const oceanTheme = defineTheme({name: 'ocean'});\n",
54
54
  );
55
55
  fs.writeFileSync(
56
- path.join(root, 'manifest.json'),
57
- JSON.stringify(
58
- {
59
- version: 1,
60
- themes: [
61
- {
62
- slug: 'ocean',
63
- displayName: 'Ocean',
64
- description: 'Ocean theme.',
65
- maintained: true,
66
- entry: 'oceanTheme.ts',
67
- exportName: 'oceanTheme',
68
- files: ['oceanTheme.ts'],
69
- },
70
- ],
71
- },
72
- null,
73
- 2,
74
- ) + '\n',
56
+ path.join(root, 'ocean', 'oceanTheme.doc.mjs'),
57
+ `/** @type {import('@astryxdesign/cli/authoring').ThemeDoc} */
58
+ export default {type: 'theme', name: 'ocean', displayName: 'Ocean', description: 'Ocean theme.', maintained: true};
59
+ `,
75
60
  );
76
61
  }
77
62
  if (components) {
@@ -109,7 +94,7 @@ describe('integrationPackCheck', () => {
109
94
  );
110
95
  });
111
96
 
112
- it('fails when a theme entry omits its catalog export', async () => {
97
+ it('fails when a theme entry omits its inferred runtime export', async () => {
113
98
  writePackage({files: ['astryx.integration.mjs', 'themes']});
114
99
  fs.writeFileSync(
115
100
  path.join(tmpDir, 'themes', 'ocean', 'oceanTheme.ts'),
@@ -129,19 +114,12 @@ describe('integrationPackCheck', () => {
129
114
  );
130
115
  });
131
116
 
132
- it('fails when a theme imports a file omitted from its catalog', async () => {
117
+ it('fails when a theme imports a missing local file', async () => {
133
118
  writePackage({files: ['astryx.integration.mjs', 'themes']});
134
- fs.mkdirSync(path.join(tmpDir, 'themes', 'ocean', 'tokens'), {
135
- recursive: true,
136
- });
137
119
  fs.writeFileSync(
138
120
  path.join(tmpDir, 'themes', 'ocean', 'oceanTheme.ts'),
139
121
  "import {oceanPalette} from './tokens/ocean.palette';\nexport const oceanTheme = {oceanPalette};\n",
140
122
  );
141
- fs.writeFileSync(
142
- path.join(tmpDir, 'themes', 'ocean', 'tokens', 'ocean.palette.ts'),
143
- 'export const oceanPalette = {};\n',
144
- );
145
123
 
146
124
  const result = await integrationPackCheck({cwd: tmpDir});
147
125
 
@@ -150,7 +128,7 @@ describe('integrationPackCheck', () => {
150
128
  expect.objectContaining({
151
129
  code: 'invalid_theme',
152
130
  message: expect.stringContaining(
153
- 'must resolve to a listed file inside the theme directory',
131
+ 'must resolve to a file inside the theme directory',
154
132
  ),
155
133
  }),
156
134
  );
@@ -231,7 +209,7 @@ describe('integrationPackCheck', () => {
231
209
  );
232
210
  fs.mkdirSync(path.join(tmpDir, 'templates'));
233
211
  fs.writeFileSync(
234
- path.join(tmpDir, 'templates', 'account-page.template.mjs'),
212
+ path.join(tmpDir, 'templates', 'account-page.doc.mjs'),
235
213
  "export default {type: 'page', name: 'Account page', description: 'Account page.'};\n",
236
214
  );
237
215
  fs.writeFileSync(
@@ -302,6 +280,93 @@ describe('integrationPackCheck', () => {
302
280
  expect(fileErrors.length).toBeGreaterThan(0);
303
281
  });
304
282
 
283
+ it('fails a package that ships a namespace doc on a CLI range that cannot read it', async () => {
284
+ writePackage({manifest: "export default {docs: './docs'};\n", themes: false});
285
+ fs.mkdirSync(path.join(tmpDir, 'docs'), {recursive: true});
286
+ fs.writeFileSync(
287
+ path.join(tmpDir, 'docs', 'acme.doc.mjs'),
288
+ "export default {type: 'namespace', name: 'acme', title: 'Acme', summary: 'Acme guides.', slots: {guides: {title: 'Guides', accepts: {kinds: ['generic']}}}};\n",
289
+ );
290
+ fs.writeFileSync(
291
+ path.join(tmpDir, 'docs', 'deploying.doc.mjs'),
292
+ "export default {type: 'generic', name: 'deploying', title: 'Deploying', description: 'Ship it.', placement: {parent: 'namespace:acme', slot: 'guides'}, sections: [{title: 'Overview', content: [{type: 'prose', text: 'Ship it.'}]}]};\n",
293
+ );
294
+ const file = path.join(tmpDir, 'package.json');
295
+ const peer = (/** @type {string | undefined} */ range) => {
296
+ const pkg = JSON.parse(fs.readFileSync(file, 'utf-8'));
297
+ if (range == null) delete pkg.peerDependencies;
298
+ else pkg.peerDependencies = {'@astryxdesign/cli': range};
299
+ fs.writeFileSync(file, `${JSON.stringify(pkg, null, 2)}\n`);
300
+ };
301
+ const codes = async () =>
302
+ (await integrationPackCheck({cwd: tmpDir})).data.issues.map(
303
+ (/** @type {{code: string}} */ issue) => issue.code,
304
+ );
305
+
306
+ peer(undefined);
307
+ expect(await codes()).toContain('docs_tree_needs_cli');
308
+ peer('^0.6.0 || >=0.7.0');
309
+ expect(await codes()).toContain('docs_tree_needs_cli');
310
+ peer('>=0.7.0');
311
+ expect(await codes()).not.toContain('docs_tree_needs_cli');
312
+ }, 120_000);
313
+
314
+ it('fails a package with only a placed guide on a CLI range that cannot read the docs tree, and passes flat topics', async () => {
315
+ writePackage({manifest: "export default {docs: './docs'};\n", themes: false});
316
+ fs.mkdirSync(path.join(tmpDir, 'docs'), {recursive: true});
317
+ fs.writeFileSync(
318
+ path.join(tmpDir, 'docs', 'notes.doc.mjs'),
319
+ "export default {type: 'generic', name: 'notes', title: 'Notes', description: 'Notes.', sections: [{title: 'Overview', content: [{type: 'prose', text: 'Notes.'}]}]};\n",
320
+ );
321
+ const codes = async () =>
322
+ (await integrationPackCheck({cwd: tmpDir})).data.issues.map(
323
+ (/** @type {{code: string}} */ issue) => issue.code,
324
+ );
325
+ // Flat topics alone need no CLI peer.
326
+ expect(await codes()).not.toContain('docs_tree_needs_cli');
327
+ fs.writeFileSync(
328
+ path.join(tmpDir, 'docs', 'setup.doc.mjs'),
329
+ "export default {type: 'generic', name: 'setup', title: 'Setup', description: 'Set up.', placement: {parent: 'namespace:acme', slot: 'guides'}, sections: [{title: 'Overview', content: [{type: 'prose', text: 'Set up.'}]}]};\n",
330
+ );
331
+ expect(await codes()).toContain('docs_tree_needs_cli');
332
+ const file = path.join(tmpDir, 'package.json');
333
+ const pkg = JSON.parse(fs.readFileSync(file, 'utf-8'));
334
+ pkg.peerDependencies = {'@astryxdesign/cli': '>=0.7.0'};
335
+ fs.writeFileSync(file, `${JSON.stringify(pkg, null, 2)}\n`);
336
+ expect(await codes()).not.toContain('docs_tree_needs_cli');
337
+ }, 120_000);
338
+
339
+ it('fails a package with a template that sets replaces on a CLI range that rejects the field', async () => {
340
+ writePackage({manifest: "export default {templates: './templates'};\n", themes: false});
341
+ fs.mkdirSync(path.join(tmpDir, 'templates'), {recursive: true});
342
+ fs.writeFileSync(
343
+ path.join(tmpDir, 'templates', 'acme-shell.doc.mjs'),
344
+ "export default {type: 'page', name: 'acme-shell', description: 'Acme shell.', replaces: 'shell-side-nav'};\n",
345
+ );
346
+ fs.writeFileSync(
347
+ path.join(tmpDir, 'templates', 'acme-shell.tsx'),
348
+ 'export default function AcmeShell() { return null; }\n',
349
+ );
350
+ const file = path.join(tmpDir, 'package.json');
351
+ const peer = (/** @type {string | undefined} */ range) => {
352
+ const pkg = JSON.parse(fs.readFileSync(file, 'utf-8'));
353
+ if (range == null) delete pkg.peerDependencies;
354
+ else pkg.peerDependencies = {'@astryxdesign/cli': range};
355
+ fs.writeFileSync(file, `${JSON.stringify(pkg, null, 2)}\n`);
356
+ };
357
+ const codes = async () =>
358
+ (await integrationPackCheck({cwd: tmpDir})).data.issues.map(
359
+ (/** @type {{code: string}} */ issue) => issue.code,
360
+ );
361
+
362
+ peer(undefined);
363
+ expect(await codes()).toContain('replaces_needs_cli');
364
+ peer('^0.6.0');
365
+ expect(await codes()).toContain('replaces_needs_cli');
366
+ peer('>=0.7.0');
367
+ expect(await codes()).not.toContain('replaces_needs_cli');
368
+ }, 120_000);
369
+
305
370
  it('passes when package.json has no files field', async () => {
306
371
  writePackage({files: undefined});
307
372
  const result = await integrationPackCheck({cwd: tmpDir});
@@ -310,14 +375,48 @@ describe('integrationPackCheck', () => {
310
375
  expect(result.data.packable).toBe(true);
311
376
  });
312
377
 
378
+ it('detects a lifecycle script that changes packed template replacements', async () => {
379
+ const script = [
380
+ "const fs=require('fs')",
381
+ "const p='templates/acme-shell.template.mjs'",
382
+ "const s=fs.readFileSync(p,'utf8')",
383
+ "fs.writeFileSync(p,s.replace('shell-side-nav','shell-top-nav'))",
384
+ ].join(';');
385
+ writePackage({
386
+ manifest: "export default {templates: './templates'};\n",
387
+ files: ['astryx.integration.mjs', 'templates'],
388
+ themes: false,
389
+ scripts: {prepack: `node -e "${script}"`},
390
+ });
391
+ fs.mkdirSync(path.join(tmpDir, 'templates'));
392
+ fs.writeFileSync(
393
+ path.join(tmpDir, 'templates', 'acme-shell.template.mjs'),
394
+ "export default {type: 'page', name: 'Acme shell', description: 'Fixture.', replaces: 'shell-side-nav'};\n",
395
+ );
396
+ fs.writeFileSync(
397
+ path.join(tmpDir, 'templates', 'acme-shell.tsx'),
398
+ 'export default function AcmeShell() { return null; }\n',
399
+ );
400
+
401
+ const result = await integrationPackCheck({cwd: tmpDir});
402
+
403
+ expect(result.data.packable).toBe(false);
404
+ expect(result.data.issues).toContainEqual(
405
+ expect.objectContaining({
406
+ code: 'identity_mismatch',
407
+ message: expect.stringContaining('acme-shell'),
408
+ }),
409
+ );
410
+ });
411
+
313
412
  it('detects a lifecycle script that changes the packed identity', async () => {
314
413
  const script = [
315
414
  "const fs=require('fs')",
316
415
  "fs.renameSync('themes/ocean','themes/storm')",
317
- "const p='themes/manifest.json'",
318
- 'const x=JSON.parse(fs.readFileSync(p))',
319
- "x.themes[0].slug='storm'",
320
- 'fs.writeFileSync(p,JSON.stringify(x))',
416
+ "const p='themes/storm/oceanTheme.doc.mjs'",
417
+ "let x=fs.readFileSync(p,'utf8')",
418
+ "x=x.replace(/name: 'ocean'/, 'name: '+String.fromCharCode(39)+'storm'+String.fromCharCode(39))",
419
+ 'fs.writeFileSync(p,x)',
321
420
  ].join(';');
322
421
  writePackage({
323
422
  files: ['astryx.integration.mjs', 'themes'],
@@ -513,23 +612,15 @@ describe('integrationPackCheck', () => {
513
612
  });
514
613
 
515
614
  describe('pack-check mutation tests', () => {
516
- it('detects when a theme file is deleted after initial add', async () => {
615
+ it('detects when a theme source is deleted after initial authoring', async () => {
517
616
  writePackage({files: ['astryx.integration.mjs', 'themes']});
518
-
519
- // Write a second theme file then delete it — catalog still references it
520
- const catalog = JSON.parse(
521
- fs.readFileSync(path.join(tmpDir, 'themes', 'manifest.json'), 'utf-8'),
522
- );
523
- catalog.themes[0].files.push('tokens.ts');
524
- fs.writeFileSync(
525
- path.join(tmpDir, 'themes', 'manifest.json'),
526
- JSON.stringify(catalog, null, 2) + '\n',
527
- );
528
- // tokens.ts doesn't exist on disk → will be in inventory but not on disk
529
- // (Phase 1 catches this; the file won't be in the pack list either)
617
+ fs.rmSync(path.join(tmpDir, 'themes', 'ocean', 'oceanTheme.ts'));
530
618
 
531
619
  const result = await integrationPackCheck({cwd: tmpDir});
532
620
  expect(result.data.packable).toBe(false);
621
+ expect(result.data.issues).toContainEqual(
622
+ expect.objectContaining({code: 'invalid_theme'}),
623
+ );
533
624
  });
534
625
 
535
626
  it('detects when files[] is narrowed after add removes themes', async () => {
@@ -567,3 +658,252 @@ describe('pack-check mutation tests', () => {
567
658
  }
568
659
  });
569
660
  });
661
+
662
+ describe('extensionless subpath resolution', () => {
663
+ it('rejects .tsx public specifiers before publishing', async () => {
664
+ // Manually construct a package with OLD-style .tsx exports keys
665
+ writePackage({
666
+ manifest: "export default {components: './components'};\n",
667
+ files: ['astryx.integration.mjs', 'components', 'index.mjs'],
668
+ themes: false,
669
+ });
670
+ const pkgFile = path.join(tmpDir, 'package.json');
671
+ const pkg = JSON.parse(fs.readFileSync(pkgFile, 'utf-8'));
672
+ pkg.exports = {
673
+ '.': './index.mjs',
674
+ './components/AcmeWidget.tsx': './components/AcmeWidget.tsx',
675
+ };
676
+ fs.writeFileSync(pkgFile, `${JSON.stringify(pkg, null, 2)}\n`);
677
+ fs.writeFileSync(
678
+ path.join(tmpDir, 'index.mjs'),
679
+ 'export const existing = 1;\n',
680
+ );
681
+ fs.mkdirSync(path.join(tmpDir, 'components'));
682
+ fs.writeFileSync(
683
+ path.join(tmpDir, 'components', 'AcmeWidget.doc.mjs'),
684
+ `export default {type: 'component', name: 'AcmeWidget', import: '@acme/widgets/components/AcmeWidget.tsx', description: 'Widget.', props: []};\n`,
685
+ );
686
+ fs.writeFileSync(
687
+ path.join(tmpDir, 'components', 'AcmeWidget.tsx'),
688
+ 'export function AcmeWidget() { return null; }\n',
689
+ );
690
+
691
+ const result = await integrationPackCheck({cwd: tmpDir});
692
+
693
+ // The .tsx extension in the specifier must be caught
694
+ expect(result.data.packable).toBe(false);
695
+ expect(result.data.issues).toContainEqual(
696
+ expect.objectContaining({
697
+ code: 'typescript_extension_in_specifier',
698
+ message: expect.stringContaining('.tsx'),
699
+ }),
700
+ );
701
+ });
702
+
703
+ it('generated extensionless component specifier resolves through exports map', async () => {
704
+ fs.writeFileSync(
705
+ path.join(tmpDir, 'package.json'),
706
+ `${JSON.stringify({
707
+ name: '@acme/widgets',
708
+ version: '1.0.0',
709
+ files: ['index.mjs'],
710
+ exports: {'.': './index.mjs'},
711
+ })}\n`,
712
+ );
713
+ fs.writeFileSync(
714
+ path.join(tmpDir, 'index.mjs'),
715
+ 'export const existing = 1;\n',
716
+ );
717
+ await integrationAddComponent('AcmeWidget', {cwd: tmpDir});
718
+
719
+ // Verify the exports map has extensionless key → .tsx target
720
+ const pkg = JSON.parse(
721
+ fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8'),
722
+ );
723
+ expect(pkg.exports['./components/AcmeWidget']).toBe(
724
+ './components/AcmeWidget.tsx',
725
+ );
726
+ expect(pkg.exports['./components/AcmeWidget.tsx']).toBeUndefined();
727
+
728
+ const result = await integrationPackCheck({cwd: tmpDir});
729
+
730
+ expect(result.data.packable).toBe(true);
731
+ expect(result.data.issues).not.toContainEqual(
732
+ expect.objectContaining({code: 'typescript_extension_in_specifier'}),
733
+ );
734
+ expect(result.data.issues).not.toContainEqual(
735
+ expect.objectContaining({code: 'component_import_unresolvable'}),
736
+ );
737
+ });
738
+
739
+ it('validates generated imports without project-local TypeScript', async () => {
740
+ fs.rmSync(tmpDir, {recursive: true, force: true});
741
+ tmpDir = fs.mkdtempSync(
742
+ path.join(os.tmpdir(), 'astryx-pack-check-no-typescript-'),
743
+ );
744
+ fs.writeFileSync(
745
+ path.join(tmpDir, 'package.json'),
746
+ `${JSON.stringify({
747
+ name: '@acme/widgets',
748
+ version: '1.0.0',
749
+ files: ['index.mjs'],
750
+ exports: {'.': './index.mjs'},
751
+ })}\n`,
752
+ );
753
+ fs.writeFileSync(
754
+ path.join(tmpDir, 'index.mjs'),
755
+ 'export const existing = 1;\n',
756
+ );
757
+ await integrationAddComponent('AcmeWidget', {cwd: tmpDir});
758
+
759
+ const result = await integrationPackCheck({cwd: tmpDir});
760
+
761
+ expect(result.data.packable).toBe(true);
762
+ expect(result.data.issues).not.toContainEqual(
763
+ expect.objectContaining({code: 'component_import_unresolvable'}),
764
+ );
765
+ });
766
+
767
+ it('generated extensionless template specifiers resolve for page and block types', async () => {
768
+ fs.writeFileSync(
769
+ path.join(tmpDir, 'package.json'),
770
+ `${JSON.stringify({
771
+ name: '@acme/widgets',
772
+ version: '1.0.0',
773
+ files: ['index.mjs'],
774
+ exports: {'.': './index.mjs'},
775
+ })}\n`,
776
+ );
777
+ fs.writeFileSync(
778
+ path.join(tmpDir, 'index.mjs'),
779
+ 'export const existing = 1;\n',
780
+ );
781
+ await integrationAddTemplate('account-page', {cwd: tmpDir, type: 'page'});
782
+ await integrationAddTemplate('info-card', {cwd: tmpDir, type: 'block'});
783
+
784
+ const pkg = JSON.parse(
785
+ fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8'),
786
+ );
787
+ expect(pkg.exports['./templates/account-page']).toBe(
788
+ './templates/account-page.tsx',
789
+ );
790
+ expect(pkg.exports['./templates/info-card']).toBe(
791
+ './templates/info-card.tsx',
792
+ );
793
+
794
+ const result = await integrationPackCheck({cwd: tmpDir});
795
+
796
+ expect(result.data.packable).toBe(true);
797
+ expect(result.data.issues).not.toContainEqual(
798
+ expect.objectContaining({code: 'template_import_unresolvable'}),
799
+ );
800
+ expect(result.data.issues).not.toContainEqual(
801
+ expect.objectContaining({code: 'typescript_extension_in_specifier'}),
802
+ );
803
+ });
804
+
805
+ it('preserves condition-style exports sugar without creating a map', async () => {
806
+ // Package with condition-only exports (sugar, no subpaths)
807
+ fs.writeFileSync(
808
+ path.join(tmpDir, 'package.json'),
809
+ `${JSON.stringify({
810
+ name: '@acme/widgets',
811
+ version: '1.0.0',
812
+ files: ['index.mjs'],
813
+ exports: {import: './index.mjs', require: './index.cjs'},
814
+ })}\n`,
815
+ );
816
+ fs.writeFileSync(
817
+ path.join(tmpDir, 'index.mjs'),
818
+ 'export const existing = 1;\n',
819
+ );
820
+ fs.writeFileSync(path.join(tmpDir, 'index.cjs'), 'exports.existing = 1;\n');
821
+ fs.writeFileSync(
822
+ path.join(tmpDir, 'astryx.integration.mjs'),
823
+ 'export default {};\n',
824
+ );
825
+
826
+ await integrationAddComponent('AcmeWidget', {cwd: tmpDir});
827
+
828
+ const pkg = JSON.parse(
829
+ fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8'),
830
+ );
831
+ // Condition sugar wrapped into subpath map with the component added
832
+ expect(pkg.exports['.']).toEqual({
833
+ import: './index.mjs',
834
+ require: './index.cjs',
835
+ });
836
+ expect(pkg.exports['./components/AcmeWidget']).toBe(
837
+ './components/AcmeWidget.tsx',
838
+ );
839
+ });
840
+
841
+ it('no-map: pack-check fails when generated component has no exports map', async () => {
842
+ fs.writeFileSync(
843
+ path.join(tmpDir, 'package.json'),
844
+ `${JSON.stringify({
845
+ name: '@acme/widgets',
846
+ version: '1.0.0',
847
+ files: ['dist'],
848
+ })}\n`,
849
+ );
850
+ fs.writeFileSync(
851
+ path.join(tmpDir, 'astryx.integration.mjs'),
852
+ 'export default {};\n',
853
+ );
854
+
855
+ await integrationAddComponent('AcmeWidget', {cwd: tmpDir});
856
+ await integrationAddTemplate('hero-page', {cwd: tmpDir, type: 'page'});
857
+
858
+ const pkg = JSON.parse(
859
+ fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8'),
860
+ );
861
+ // No exports map created
862
+ expect(pkg.exports).toBeUndefined();
863
+
864
+ const result = await integrationPackCheck({cwd: tmpDir});
865
+
866
+ // The extensionless import cannot resolve without an exports map —
867
+ // pack-check must fail closed, not false-green.
868
+ expect(result.data.packable).toBe(false);
869
+ expect(result.data.issues).toContainEqual(
870
+ expect.objectContaining({
871
+ severity: 'error',
872
+ message: expect.stringContaining('AcmeWidget'),
873
+ }),
874
+ );
875
+ });
876
+
877
+ it('idempotent when extensionless export already exists', async () => {
878
+ fs.writeFileSync(
879
+ path.join(tmpDir, 'package.json'),
880
+ `${JSON.stringify({
881
+ name: '@acme/widgets',
882
+ version: '1.0.0',
883
+ files: ['index.mjs'],
884
+ exports: {
885
+ '.': './index.mjs',
886
+ './components/AcmeWidget': './components/AcmeWidget.tsx',
887
+ },
888
+ })}\n`,
889
+ );
890
+ fs.writeFileSync(
891
+ path.join(tmpDir, 'index.mjs'),
892
+ 'export const existing = 1;\n',
893
+ );
894
+ fs.writeFileSync(
895
+ path.join(tmpDir, 'astryx.integration.mjs'),
896
+ 'export default {};\n',
897
+ );
898
+
899
+ await integrationAddComponent('AcmeWidget', {cwd: tmpDir});
900
+
901
+ const pkg = JSON.parse(
902
+ fs.readFileSync(path.join(tmpDir, 'package.json'), 'utf-8'),
903
+ );
904
+ // Export preserved, no duplicate
905
+ expect(
906
+ Object.keys(pkg.exports).filter(k => k.includes('AcmeWidget')),
907
+ ).toEqual(['./components/AcmeWidget']);
908
+ });
909
+ });
@@ -9,6 +9,30 @@ export type IntegrationPackCheckResponse = {
9
9
  data: PackCheckData;
10
10
  };
11
11
  export type PackCheckResponse = IntegrationPackCheckResponse;
12
+ /**
13
+ * Public contribution inventory returned by pack-check. Kept here rather than
14
+ * importing the runtime inventory module so the type-only `/json` surface does
15
+ * not pull implementation dependencies into downstream type checking.
16
+ */
17
+ export type PackCheckContributionIdentities = {
18
+ themes: {
19
+ slug: string;
20
+ exportName: string;
21
+ }[];
22
+ components: string[];
23
+ templates: {
24
+ id: string;
25
+ type: string;
26
+ name: string;
27
+ replaces?: string;
28
+ }[];
29
+ codemods: {
30
+ version: string;
31
+ id: string;
32
+ }[];
33
+ docs: string[];
34
+ agentDocsAppend: string[];
35
+ };
12
36
  export type PackCheckData = {
13
37
  name: string | null;
14
38
  version: string | null;
@@ -19,8 +43,8 @@ export type PackCheckData = {
19
43
  tarball: PackCheckTarball | null;
20
44
  inventory: PackCheckInventory;
21
45
  contributions: {
22
- local: import("../../foundation/integrations/contribution-inventory.mjs").ContributionIdentities | null;
23
- packed: import("../../foundation/integrations/contribution-inventory.mjs").ContributionIdentities | null;
46
+ local: PackCheckContributionIdentities | null;
47
+ packed: PackCheckContributionIdentities | null;
24
48
  };
25
49
  issues: import("../../foundation/integrations/issue").AstryxIntegrationIssue[];
26
50
  };