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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (670) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/README.md +121 -85
  3. package/api/blog/blog.doc.mjs +1 -0
  4. package/api/build/_adapter.d.mts +50 -0
  5. package/api/build/_adapter.mjs +60 -0
  6. package/api/build/build.doc.mjs +16 -9
  7. package/api/build/build.test.mjs +197 -8
  8. package/api/build/build.type.d.mts +91 -2
  9. package/api/build/build.type.mjs +52 -8
  10. package/api/build/help/help.d.mts +12 -5
  11. package/api/build/help/help.mjs +69 -6
  12. package/api/build/kit/kit.d.mts +4 -1
  13. package/api/build/kit/kit.mjs +165 -49
  14. package/api/build/kit/rank.d.mts +44 -0
  15. package/api/build/kit/rank.mjs +432 -0
  16. package/api/build/kit/rank.test.mjs +196 -0
  17. package/api/component/_adapter.d.mts +31 -12
  18. package/api/component/_adapter.mjs +79 -15
  19. package/api/component/component.d.mts +6 -3
  20. package/api/component/component.doc.mjs +36 -13
  21. package/api/component/component.mjs +339 -22
  22. package/api/component/component.test.mjs +38 -0
  23. package/api/component/component.type.d.mts +47 -11
  24. package/api/component/component.type.mjs +76 -24
  25. package/api/component/detail/blocks/blocks.d.mts +2 -1
  26. package/api/component/detail/blocks/blocks.mjs +4 -3
  27. package/api/component/list/list.d.mts +0 -5
  28. package/api/component/list/list.mjs +40 -11
  29. package/api/discover/_adapter.d.mts +114 -6
  30. package/api/discover/_adapter.mjs +372 -17
  31. package/api/discover/_adapter.test.mjs +215 -0
  32. package/api/discover/_catalog-view.d.mts +115 -0
  33. package/api/discover/_catalog-view.mjs +203 -0
  34. package/api/discover/_catalog-view.test.mjs +128 -0
  35. package/api/discover/detail/detail.d.mts +18 -6
  36. package/api/discover/detail/detail.mjs +67 -13
  37. package/api/discover/detail/detail.test.mjs +85 -0
  38. package/api/discover/detail/item/item.d.mts +26 -0
  39. package/api/discover/detail/item/item.mjs +78 -0
  40. package/api/discover/detail/item/item.test.mjs +73 -0
  41. package/api/discover/discover.d.mts +3 -9
  42. package/api/discover/discover.doc.mjs +62 -18
  43. package/api/discover/discover.mjs +220 -36
  44. package/api/discover/discover.test.mjs +11 -2
  45. package/api/discover/discover.type.d.mts +150 -11
  46. package/api/discover/discover.type.mjs +107 -17
  47. package/api/discover/list/list.d.mts +20 -6
  48. package/api/discover/list/list.mjs +45 -12
  49. package/api/discover/list/list.test.mjs +46 -0
  50. package/api/discover/search/search.d.mts +18 -16
  51. package/api/discover/search/search.mjs +102 -56
  52. package/api/discover/search/search.test.mjs +144 -10
  53. package/api/docs/_adapter.d.mts +272 -41
  54. package/api/docs/_adapter.mjs +985 -108
  55. package/api/docs/compiled-topics.test.mjs +78 -0
  56. package/api/docs/detail/detail.mjs +22 -63
  57. package/api/docs/detail/section/section.d.mts +1 -1
  58. package/api/docs/detail/section/section.mjs +54 -19
  59. package/api/docs/detail/section/section.test.mjs +50 -0
  60. package/api/docs/docs.d.mts +10 -3
  61. package/api/docs/docs.doc.mjs +55 -16
  62. package/api/docs/docs.mjs +53 -10
  63. package/api/docs/docs.test.mjs +166 -4
  64. package/api/docs/docs.type.d.mts +221 -5
  65. package/api/docs/docs.type.mjs +153 -11
  66. package/api/docs/index/index.d.mts +18 -0
  67. package/api/docs/index/index.mjs +40 -0
  68. package/api/docs/index/index.test.mjs +62 -0
  69. package/api/docs/integration-tree.test.mjs +555 -0
  70. package/api/docs/integrationDocs.test.mjs +114 -8
  71. package/api/docs/list/list.mjs +28 -12
  72. package/api/docs/node/node.d.mts +43 -0
  73. package/api/docs/node/node.mjs +192 -0
  74. package/api/docs/reference-blocks.test.mjs +406 -0
  75. package/api/doctor/doctor.d.mts +104 -1
  76. package/api/doctor/doctor.doc.mjs +1 -0
  77. package/api/doctor/doctor.mjs +635 -7
  78. package/api/doctor/doctor.test.mjs +732 -11
  79. package/api/gap-report/gap-report.doc.mjs +8 -4
  80. package/api/hook/_adapter.mjs +19 -5
  81. package/api/hook/hook.doc.mjs +1 -0
  82. package/api/hook/hook.type.d.mts +3 -3
  83. package/api/hook/hook.type.mjs +11 -11
  84. package/api/hook/list/list.d.mts +2 -2
  85. package/api/hook/list/list.mjs +69 -17
  86. package/api/index.d.mts +2 -3
  87. package/api/index.mjs +5 -4
  88. package/api/init/init.doc.mjs +6 -1
  89. package/api/init/init.test.mjs +41 -1
  90. package/api/init/remove/remove.mjs +1 -1
  91. package/api/init/run/run.mjs +20 -10
  92. package/api/integration/add-contribution.component-names.test.mjs +120 -0
  93. package/api/integration/add-contribution.d.mts +2 -1
  94. package/api/integration/add-contribution.mjs +130 -15
  95. package/api/integration/add-contribution.test.mjs +258 -7
  96. package/api/integration/add-helpers.d.mts +5 -2
  97. package/api/integration/add-helpers.mjs +36 -9
  98. package/api/integration/add-theme.mjs +34 -64
  99. package/api/integration/add-theme.test.mjs +105 -21
  100. package/api/integration/authoring-checks.mjs +138 -28
  101. package/api/integration/authoring-checks.test.mjs +179 -7
  102. package/api/integration/authoring-checks.type.mjs +6 -1
  103. package/api/integration/integration-authoring.type.d.mts +3 -1
  104. package/api/integration/integration-authoring.type.mjs +2 -0
  105. package/api/integration/integration-block-exports.test.mjs +10 -6
  106. package/api/integration/integrationAdd.doc.mjs +14 -4
  107. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  108. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  109. package/api/integration/integrationAddComponent.doc.mjs +2 -1
  110. package/api/integration/integrationAddDoc.doc.mjs +8 -1
  111. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  112. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  113. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  114. package/api/integration/integrationDocConflicts.doc.mjs +2 -1
  115. package/api/integration/integrationPackCheck.doc.mjs +2 -1
  116. package/api/integration/integrationTemplateConflicts.doc.d.mts +3 -0
  117. package/api/integration/integrationTemplateConflicts.doc.mjs +4 -0
  118. package/api/integration/pack-check.lifecycle-output.test.mjs +105 -0
  119. package/api/integration/pack-check.mjs +111 -10
  120. package/api/integration/pack-check.test.mjs +387 -47
  121. package/api/integration/pack-check.type.d.mts +26 -2
  122. package/api/integration/pack-check.type.mjs +14 -1
  123. package/api/integration/summarizeIssues.doc.mjs +1 -0
  124. package/api/integration/template-conflict-compatibility.test.mjs +73 -0
  125. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  126. package/api/integration/validate-integration.mjs +52 -102
  127. package/api/integration/validate-integration.test.mjs +179 -26
  128. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  129. package/api/integration/validateIntegration.doc.mjs +3 -2
  130. package/api/json/assertResponse.doc.mjs +1 -0
  131. package/api/json/envelope-types.test.mjs +76 -0
  132. package/api/json/index.ts +2 -1
  133. package/api/json/isError.doc.mjs +1 -0
  134. package/api/json/parseResponse.doc.mjs +3 -2
  135. package/api/search/search-return-type.test.mjs +54 -0
  136. package/api/search/search.d.mts +62 -11
  137. package/api/search/search.doc.mjs +8 -2
  138. package/api/search/search.mjs +471 -83
  139. package/api/search/search.test.mjs +142 -1
  140. package/api/search/search.type.d.mts +15 -3
  141. package/api/search/search.type.mjs +5 -2
  142. package/api/swizzle/copy/copy.mjs +28 -11
  143. package/api/swizzle/swizzle.doc.mjs +2 -1
  144. package/api/swizzle/swizzle.type.d.mts +2 -2
  145. package/api/swizzle/swizzle.type.mjs +2 -2
  146. package/api/template/copy/copy.mjs +17 -23
  147. package/api/template/copy/copy.test.mjs +17 -0
  148. package/api/template/list/list.mjs +1 -0
  149. package/api/template/table-floating-bulk-actions.test.mjs +66 -0
  150. package/api/template/template-integration.test.mjs +1008 -3
  151. package/api/template/template-suffix.test.mjs +41 -21
  152. package/api/template/template.d.mts +1 -1
  153. package/api/template/template.doc.mjs +30 -8
  154. package/api/template/template.mjs +46 -9
  155. package/api/template/template.type.d.mts +12 -14
  156. package/api/template/template.type.mjs +15 -14
  157. package/api/theme/_adapter.d.mts +2 -3
  158. package/api/theme/_adapter.mjs +4 -5
  159. package/api/theme/add/add.binary.test.mjs +84 -0
  160. package/api/theme/add/add.mjs +31 -22
  161. package/api/theme/add/add.rollback.test.mjs +158 -0
  162. package/api/theme/add/add.staging.test.mjs +83 -0
  163. package/api/theme/add/add.test.mjs +14 -1
  164. package/api/theme/build/build.family.test.mjs +7 -12
  165. package/api/theme/build/build.mjs +140 -59
  166. package/api/theme/build/build.public-component-vars.test.mjs +1 -1
  167. package/api/theme/build/build.receipt-doc.test.mjs +111 -0
  168. package/api/theme/build/build.rollback.test.mjs +148 -0
  169. package/api/theme/build/build.test.mjs +127 -0
  170. package/api/theme/build/font-warning.mjs +3 -3
  171. package/api/theme/build/font-warning.test.mjs +5 -2
  172. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  173. package/api/theme/integration-themes.test.mjs +39 -28
  174. package/api/theme/list/list.test.mjs +19 -20
  175. package/api/theme/listThemes.doc.mjs +6 -5
  176. package/api/theme/palette/generate/generate.mjs +8 -3
  177. package/api/theme/palette/generate/generate.test.mjs +96 -0
  178. package/api/theme/palette/generate/generator.d.mts +10 -13
  179. package/api/theme/palette/generate/generator.mjs +15 -4
  180. package/api/theme/palette/generate/generator.test.mjs +10 -0
  181. package/api/theme/template/template.mjs +11 -2
  182. package/api/theme/template/template.test.mjs +20 -0
  183. package/api/theme/theme.type.d.mts +170 -11
  184. package/api/theme/theme.type.mjs +94 -27
  185. package/api/theme/themeAdd.doc.mjs +4 -3
  186. package/api/theme/themeBuild.doc.mjs +8 -4
  187. package/api/theme/themeList.doc.mjs +6 -3
  188. package/api/theme/themeListAvailable.doc.mjs +5 -3
  189. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  190. package/api/theme/themeTargets.doc.mjs +1 -0
  191. package/api/theme/themeTemplate.doc.mjs +6 -2
  192. package/api/upgrade/_adapter.d.mts +32 -5
  193. package/api/upgrade/_adapter.mjs +139 -22
  194. package/api/upgrade/list/list.mjs +2 -1
  195. package/api/upgrade/list/list.test.mjs +73 -0
  196. package/api/upgrade/project-context.test.mjs +272 -0
  197. package/api/upgrade/provider-agreement.test.mjs +152 -0
  198. package/api/upgrade/run/files-changed.test.mjs +111 -0
  199. package/api/upgrade/run/run.mjs +359 -60
  200. package/api/upgrade/status/status.mjs +2 -2
  201. package/api/upgrade/upgrade.doc.mjs +12 -5
  202. package/api/upgrade/upgrade.type.d.mts +43 -5
  203. package/api/upgrade/upgrade.type.mjs +29 -13
  204. package/assets/codemods/__tests__/registry.test.mjs +1 -0
  205. package/assets/codemods/__tests__/runner.test.mjs +332 -8
  206. package/assets/codemods/file-count.test.mjs +163 -0
  207. package/assets/codemods/integration-discovery.mjs +48 -4
  208. package/assets/codemods/integration-discovery.test.mjs +73 -0
  209. package/assets/codemods/integration-runner.mjs +59 -7
  210. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  211. package/assets/codemods/registry.mjs +1 -0
  212. package/assets/codemods/run-codemod.mjs +177 -34
  213. package/assets/codemods/runner.mjs +353 -104
  214. package/assets/codemods/term-log.mjs +32 -8
  215. package/assets/codemods/term-log.test.mjs +19 -1
  216. package/assets/codemods/transform-prop.mjs +109 -0
  217. package/assets/codemods/transform-prop.test.mjs +95 -0
  218. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  219. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  220. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  221. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  222. package/assets/codemods/transforms/v0.3.0/__tests__/unwrap-authoring-factories.test.mjs +27 -5
  223. package/assets/codemods/transforms/v0.3.0/unwrap-authoring-factories.mjs +20 -5
  224. package/assets/codemods/transforms/v0.6.0/__tests__/next-codemods.test.mjs +47 -0
  225. package/assets/codemods/transforms/v0.6.0/rename-resizable-pixel-bounds.mjs +57 -10
  226. package/assets/codemods/transforms/v0.6.4/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  227. package/assets/codemods/transforms/v0.6.4/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  228. package/assets/codemods/transforms/v0.6.4/index.mjs +31 -0
  229. package/assets/codemods/transforms/v0.6.4/migrate-native-picker-to-presentation.mjs +148 -0
  230. package/assets/codemods/transforms/v0.6.4/migrate-theme-catalog-to-descriptors.mjs +141 -0
  231. package/assets/docs/README.md +9 -0
  232. package/assets/docs/authoring.doc.mjs +14 -0
  233. package/assets/docs/getting-started.doc.mjs +2 -2
  234. package/assets/docs/internationalization.doc.mjs +7 -5
  235. package/assets/docs/layout.doc.dense.mjs +2 -2
  236. package/assets/docs/layout.doc.mjs +1 -1
  237. package/assets/docs/principles.doc.mjs +6 -6
  238. package/assets/docs/styling-libraries.doc.mjs +4 -4
  239. package/assets/docs/styling.doc.mjs +4 -4
  240. package/assets/docs/theme.doc.mjs +5 -5
  241. package/assets/docs/tokens.doc.mjs +1 -1
  242. package/assets/docs/tree/api.doc.mjs +30 -0
  243. package/assets/docs/tree/cli.doc.mjs +23 -0
  244. package/assets/docs/tree/commands.doc.mjs +25 -0
  245. package/assets/docs/tree/component-lookups.doc.mjs +149 -0
  246. package/assets/docs/{cli-integrations.doc.mjs → tree/integrations.doc.mjs} +144 -26
  247. package/assets/docs/tree/integrations.test.mjs +62 -0
  248. package/assets/docs/tree/writing-docs.doc.mjs +286 -0
  249. package/assets/docs/working-with-ai.doc.mjs +4 -4
  250. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.doc.mjs +1 -1
  251. package/assets/templates/blocks/components/CheckboxList/CheckboxListSelectAllPattern.tsx +1 -3
  252. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  253. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  254. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  255. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  256. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  257. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  258. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  259. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  260. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  261. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  262. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  263. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  264. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  265. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  266. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  267. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  268. package/assets/templates/blocks/components/Table/TableBulkActionsTable.doc.mjs +14 -0
  269. package/assets/templates/blocks/components/Table/TableBulkActionsTable.tsx +71 -0
  270. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.doc.mjs +19 -0
  271. package/assets/templates/blocks/components/Table/TableFloatingBulkActionsTable.tsx +139 -0
  272. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  273. package/assets/templates/blocks/components/Timer/TimerFormats.doc.mjs +14 -0
  274. package/assets/templates/blocks/components/Timer/TimerFormats.tsx +34 -0
  275. package/assets/templates/blocks/components/Timer/TimerInline.doc.mjs +14 -0
  276. package/assets/templates/blocks/components/Timer/TimerInline.tsx +14 -0
  277. package/assets/templates/blocks/components/Timer/TimerShowcase.doc.mjs +13 -0
  278. package/assets/templates/blocks/components/Timer/TimerShowcase.tsx +47 -0
  279. package/assets/templates/blocks/components/Timer/TimerTypography.doc.mjs +14 -0
  280. package/assets/templates/blocks/components/Timer/TimerTypography.tsx +31 -0
  281. package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.doc.mjs +19 -3
  282. package/assets/templates/blocks/components/Toolbar/ToolbarTableFilter.tsx +383 -65
  283. package/assets/templates/pages/table-tree/page.tsx +1704 -0
  284. package/assets/templates/pages/table-tree/template.doc.mjs +12 -0
  285. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  286. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  287. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  288. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  289. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  290. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  291. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  292. package/authoring/_shared/contract.ts +22 -0
  293. package/authoring/codemod/codemod.doc.mjs +7 -2
  294. package/authoring/codemod/parse.d.mts +8 -8
  295. package/authoring/codemod/parse.mjs +8 -6
  296. package/authoring/codemod/type.ts +12 -0
  297. package/authoring/config/config.doc.mjs +11 -3
  298. package/authoring/config/debug-composition.test.mjs +92 -0
  299. package/authoring/config/parse.d.mts +15 -13
  300. package/authoring/config/parse.mjs +27 -8
  301. package/authoring/config/parse.test.mjs +8 -0
  302. package/authoring/config/type.ts +31 -8
  303. package/authoring/debug/debug.doc.d.mts +11 -0
  304. package/authoring/debug/debug.doc.mjs +182 -0
  305. package/authoring/debug/parse.d.mts +8 -8
  306. package/authoring/debug/parse.mjs +3 -3
  307. package/authoring/discover/discover.doc.d.mts +13 -0
  308. package/authoring/discover/discover.doc.mjs +138 -0
  309. package/authoring/discover/parse.d.mts +24 -0
  310. package/authoring/discover/parse.mjs +128 -0
  311. package/authoring/discover/parse.test.mjs +124 -0
  312. package/authoring/discover/type.ts +87 -0
  313. package/authoring/doctypes/_schema.d.mts +790 -23
  314. package/authoring/doctypes/_schema.mjs +543 -39
  315. package/authoring/doctypes/base/graph-fields.doc.d.mts +9 -0
  316. package/authoring/doctypes/base/graph-fields.doc.mjs +64 -0
  317. package/authoring/doctypes/base/type.ts +41 -0
  318. package/authoring/doctypes/command/command.doc.mjs +5 -4
  319. package/authoring/doctypes/command/parse.d.mts +2 -2
  320. package/authoring/doctypes/command/parse.mjs +1 -1
  321. package/authoring/doctypes/command/type.ts +6 -5
  322. package/authoring/doctypes/component/component.doc.mjs +6 -3
  323. package/authoring/doctypes/component/parse.d.mts +2 -2
  324. package/authoring/doctypes/component/parse.mjs +1 -1
  325. package/authoring/doctypes/component/type.ts +6 -5
  326. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  327. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  328. package/authoring/doctypes/enum/parse.d.mts +2 -2
  329. package/authoring/doctypes/enum/parse.mjs +1 -1
  330. package/authoring/doctypes/enum/type.ts +4 -2
  331. package/authoring/doctypes/function/function.doc.mjs +7 -2
  332. package/authoring/doctypes/function/parse.d.mts +2 -2
  333. package/authoring/doctypes/function/parse.mjs +1 -1
  334. package/authoring/doctypes/function/type.ts +9 -4
  335. package/authoring/doctypes/hook/hook.doc.mjs +4 -0
  336. package/authoring/doctypes/hook/parse.d.mts +2 -2
  337. package/authoring/doctypes/hook/parse.mjs +1 -1
  338. package/authoring/doctypes/hook/type.ts +5 -4
  339. package/authoring/doctypes/legacy.d.mts +8 -6
  340. package/authoring/doctypes/legacy.mjs +5 -4
  341. package/authoring/doctypes/load-contract.test.mjs +233 -0
  342. package/authoring/doctypes/namespace/namespace.doc.d.mts +9 -0
  343. package/authoring/doctypes/namespace/namespace.doc.mjs +128 -0
  344. package/authoring/doctypes/namespace/parse.d.mts +12 -0
  345. package/authoring/doctypes/namespace/parse.mjs +25 -0
  346. package/authoring/doctypes/namespace/parse.test.mjs +163 -0
  347. package/authoring/doctypes/namespace/type.ts +74 -0
  348. package/authoring/doctypes/parse.d.mts +22 -18
  349. package/authoring/doctypes/parse.mjs +22 -11
  350. package/authoring/doctypes/parse.test.mjs +77 -3
  351. package/authoring/doctypes/reference/parse.d.mts +2 -2
  352. package/authoring/doctypes/reference/parse.mjs +8 -5
  353. package/authoring/doctypes/reference/reference.doc.mjs +48 -6
  354. package/authoring/doctypes/reference/type.ts +70 -7
  355. package/authoring/doctypes/schema/parse.d.mts +2 -2
  356. package/authoring/doctypes/schema/parse.mjs +1 -1
  357. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  358. package/authoring/doctypes/schema/type.ts +4 -4
  359. package/authoring/doctypes/template/parse.d.mts +94 -1
  360. package/authoring/doctypes/template/parse.mjs +40 -2
  361. package/authoring/doctypes/template/parse.test.mjs +26 -2
  362. package/authoring/doctypes/template/template.doc.mjs +13 -3
  363. package/authoring/doctypes/template/type.ts +13 -2
  364. package/authoring/doctypes/theme/parse.d.mts +35 -0
  365. package/authoring/doctypes/theme/parse.mjs +76 -0
  366. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  367. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  368. package/authoring/doctypes/theme/type.ts +42 -0
  369. package/authoring/doctypes/types.ts +12 -10
  370. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  371. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  372. package/authoring/gap-report/parse.d.mts +10 -10
  373. package/authoring/gap-report/parse.mjs +6 -6
  374. package/authoring/gap-report/type.ts +1 -1
  375. package/authoring/identity/identity.doc.d.mts +9 -0
  376. package/authoring/identity/identity.doc.mjs +61 -0
  377. package/authoring/identity/type.ts +132 -0
  378. package/authoring/index.d.mts +3 -0
  379. package/authoring/index.d.ts +62 -17
  380. package/authoring/index.mjs +4 -1
  381. package/authoring/integration/integration.doc.mjs +15 -8
  382. package/authoring/integration/parse.d.mts +2 -2
  383. package/authoring/integration/parse.mjs +1 -1
  384. package/authoring/integration/parse.test.mjs +10 -1
  385. package/authoring/integration/schema.d.mts +6 -4
  386. package/authoring/integration/schema.mjs +9 -3
  387. package/authoring/integration/type.ts +19 -8
  388. package/authoring/shadcn/receipt.d.mts +6 -6
  389. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  390. package/clients/cli/command-load-failure.test.mjs +83 -0
  391. package/clients/cli/command-result-coverage.test.mjs +7 -7
  392. package/clients/cli/commands/blog.doc.mjs +1 -1
  393. package/clients/cli/commands/blog.mjs +23 -8
  394. package/clients/cli/commands/blog.test.mjs +42 -1
  395. package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
  396. package/clients/cli/commands/build-theme.ascii-output.test.mjs +161 -0
  397. package/clients/cli/commands/build-theme.flag-docs.test.mjs +110 -0
  398. package/clients/cli/commands/build-theme.mjs +16 -50
  399. package/clients/cli/commands/build-theme.path-safety.test.mjs +86 -1
  400. package/clients/cli/commands/build-theme.variants.test.mjs +76 -0
  401. package/clients/cli/commands/build.doc.mjs +16 -8
  402. package/clients/cli/commands/build.exit-codes-doc.test.mjs +50 -0
  403. package/clients/cli/commands/build.mjs +137 -114
  404. package/clients/cli/commands/build.playbook.test.mjs +75 -0
  405. package/clients/cli/commands/build.text-fields.test.mjs +81 -0
  406. package/clients/cli/commands/component/index.mjs +153 -61
  407. package/clients/cli/commands/component-batch.test.mjs +341 -0
  408. package/clients/cli/commands/component-ownership.test.mjs +92 -3
  409. package/clients/cli/commands/component-package.test.mjs +46 -0
  410. package/clients/cli/commands/component-resolution.test.mjs +21 -0
  411. package/clients/cli/commands/component.doc.mjs +24 -7
  412. package/clients/cli/commands/component.test.mjs +19 -0
  413. package/clients/cli/commands/debug-result-summary.test.mjs +2 -2
  414. package/clients/cli/commands/detail-levels.test.mjs +2 -2
  415. package/clients/cli/commands/discover.broken-integration.test.mjs +52 -5
  416. package/clients/cli/commands/discover.components-flag.test.mjs +97 -0
  417. package/clients/cli/commands/discover.doc.mjs +55 -9
  418. package/clients/cli/commands/discover.mjs +393 -118
  419. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  420. package/clients/cli/commands/discover.text-projection.test.mjs +103 -0
  421. package/clients/cli/commands/docs.doc.mjs +28 -6
  422. package/clients/cli/commands/docs.mjs +240 -26
  423. package/clients/cli/commands/docs.test.mjs +222 -1
  424. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  425. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -3
  426. package/clients/cli/commands/doctor-integration-templates.doc.mjs +15 -8
  427. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  428. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  429. package/clients/cli/commands/doctor-integration.package-json.test.mjs +53 -0
  430. package/clients/cli/commands/doctor-integration.test.mjs +90 -8
  431. package/clients/cli/commands/doctor.doc.mjs +1 -1
  432. package/clients/cli/commands/doctor.mjs +59 -32
  433. package/clients/cli/commands/doctor.test.mjs +42 -0
  434. package/clients/cli/commands/gap-report.doc.mjs +17 -6
  435. package/clients/cli/commands/gap-report.test.mjs +72 -0
  436. package/clients/cli/commands/hook/index.mjs +7 -17
  437. package/clients/cli/commands/hook.doc.mjs +1 -1
  438. package/clients/cli/commands/hook.text-projection.test.mjs +45 -0
  439. package/clients/cli/commands/init.doc.mjs +20 -9
  440. package/clients/cli/commands/init.flag-help.test.mjs +153 -0
  441. package/clients/cli/commands/integration-add.controls.test.mjs +132 -0
  442. package/clients/cli/commands/integration-add.doc.mjs +32 -6
  443. package/clients/cli/commands/integration-authoring.test.mjs +13 -9
  444. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  445. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  446. package/clients/cli/commands/integration.doc.mjs +1 -1
  447. package/clients/cli/commands/integration.mjs +1 -0
  448. package/clients/cli/commands/interactive-guard.test.mjs +101 -24
  449. package/clients/cli/commands/json-contract.test.mjs +33 -0
  450. package/clients/cli/commands/manifest.doc.mjs +1 -1
  451. package/clients/cli/commands/no-prompt-wording.test.mjs +94 -0
  452. package/clients/cli/commands/search.doc.mjs +7 -4
  453. package/clients/cli/commands/search.mjs +28 -9
  454. package/clients/cli/commands/search.test.mjs +75 -0
  455. package/clients/cli/commands/setup-nudge.test.mjs +6 -0
  456. package/clients/cli/commands/swizzle.doc.mjs +3 -2
  457. package/clients/cli/commands/swizzle.path-safety.test.mjs +42 -0
  458. package/clients/cli/commands/template.doc.mjs +52 -13
  459. package/clients/cli/commands/template.flag-help.test.mjs +117 -0
  460. package/clients/cli/commands/template.mjs +4 -91
  461. package/clients/cli/commands/template.path-help.test.mjs +40 -0
  462. package/clients/cli/commands/text-json-parity.test.mjs +702 -0
  463. package/clients/cli/commands/theme-add.doc.mjs +4 -3
  464. package/clients/cli/commands/theme-build.doc.mjs +8 -7
  465. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  466. package/clients/cli/commands/theme-palette-generate.doc.mjs +9 -5
  467. package/clients/cli/commands/theme-palette-generate.test.mjs +19 -0
  468. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  469. package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
  470. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  471. package/clients/cli/commands/theme-template.behavior.test.mjs +12 -0
  472. package/clients/cli/commands/theme-template.doc.mjs +2 -2
  473. package/clients/cli/commands/theme.doc.mjs +1 -1
  474. package/clients/cli/commands/upgrade.ascii-output.test.mjs +87 -0
  475. package/clients/cli/commands/upgrade.doc.mjs +22 -10
  476. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  477. package/clients/cli/commands/upgrade.flag-help.test.mjs +188 -0
  478. package/clients/cli/commands/upgrade.hook-output.test.mjs +88 -0
  479. package/clients/cli/commands/upgrade.mjs +29 -7
  480. package/clients/cli/formatters/index.mjs +164 -1
  481. package/clients/cli/formatters/index.test.mjs +97 -0
  482. package/clients/cli/index.mjs +21 -34
  483. package/clients/cli/latest-version-env.test.mjs +50 -0
  484. package/clients/cli/lib/cli-error.test.mjs +7 -0
  485. package/clients/cli/lib/component-format.mjs +9 -9
  486. package/clients/cli/lib/component-format.test.mjs +1 -1
  487. package/clients/cli/lib/define-command.mjs +32 -6
  488. package/clients/cli/lib/doc-text-ascii.test.mjs +82 -0
  489. package/clients/cli/lib/exit-codes.test.mjs +90 -0
  490. package/clients/cli/lib/hook-format.mjs +19 -10
  491. package/clients/cli/lib/json-shim.mjs +62 -16
  492. package/clients/cli/lib/json-shim.test.mjs +69 -0
  493. package/clients/cli/lib/manifest.d.ts +2 -0
  494. package/clients/cli/lib/manifest.mjs +39 -10
  495. package/clients/cli/lib/manifest.test.mjs +22 -2
  496. package/clients/cli/lib/parse-error-format.test.mjs +81 -0
  497. package/foundation/agent-docs/agent-docs.d.mts +7 -2
  498. package/foundation/agent-docs/agent-docs.mjs +82 -12
  499. package/foundation/agent-docs/agent-docs.path-safety.test.mjs +266 -4
  500. package/foundation/agent-docs/agent-docs.test.mjs +19 -1
  501. package/foundation/config/integration-debug.test.mjs +28 -3
  502. package/foundation/config/project-themes.test.mjs +11 -19
  503. package/foundation/config/project.d.mts +20 -11
  504. package/foundation/config/project.mjs +263 -91
  505. package/foundation/config/project.test.mjs +270 -21
  506. package/foundation/discovery/authoring-self-docs.d.mts +87 -0
  507. package/foundation/discovery/authoring-self-docs.mjs +237 -0
  508. package/foundation/discovery/authoring-self-docs.test.mjs +170 -0
  509. package/foundation/discovery/authoring-surface.d.mts +74 -0
  510. package/foundation/discovery/authoring-surface.mjs +525 -0
  511. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  512. package/foundation/discovery/cli-self-docs.d.mts +119 -0
  513. package/foundation/discovery/cli-self-docs.mjs +490 -0
  514. package/foundation/discovery/cli-self-docs.test.mjs +375 -0
  515. package/foundation/discovery/component-discovery.d.mts +39 -1
  516. package/foundation/discovery/component-discovery.mjs +50 -1
  517. package/foundation/discovery/component-loader.d.mts +35 -38
  518. package/foundation/discovery/component-loader.mjs +53 -222
  519. package/foundation/discovery/docs-discovery.d.mts +119 -11
  520. package/foundation/discovery/docs-discovery.mjs +423 -108
  521. package/foundation/discovery/docs-discovery.test.mjs +365 -20
  522. package/foundation/discovery/docs-output-budget.d.mts +28 -0
  523. package/foundation/discovery/docs-output-budget.mjs +50 -0
  524. package/foundation/discovery/docs-section-key.d.mts +116 -0
  525. package/foundation/discovery/docs-section-key.mjs +322 -0
  526. package/foundation/discovery/docs-section-key.test.mjs +246 -0
  527. package/foundation/discovery/template-adapter.d.mts +113 -11
  528. package/foundation/discovery/template-adapter.fixture-refs.test.mjs +248 -0
  529. package/foundation/discovery/template-adapter.integration-isolation.test.mjs +94 -0
  530. package/foundation/discovery/template-adapter.mjs +775 -84
  531. package/foundation/discovery/template-adapter.test.mjs +57 -0
  532. package/foundation/discovery/template-conflict-release.d.mts +13 -0
  533. package/foundation/discovery/template-conflict-release.mjs +40 -0
  534. package/foundation/discovery/template-conflict-release.test.mjs +40 -0
  535. package/foundation/discovery/theme-discovery.d.mts +67 -7
  536. package/foundation/discovery/theme-discovery.mjs +916 -186
  537. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  538. package/foundation/discovery/theming-targets.test.mjs +4 -0
  539. package/foundation/doc-compiler/bundle.d.mts +47 -0
  540. package/foundation/doc-compiler/bundle.mjs +278 -0
  541. package/foundation/doc-compiler/bundle.test.mjs +266 -0
  542. package/foundation/doc-compiler/compile.d.mts +343 -0
  543. package/foundation/doc-compiler/compile.mjs +558 -0
  544. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  545. package/foundation/doc-compiler/diagnostics.mjs +305 -0
  546. package/foundation/doc-compiler/doc-compiler.test.mjs +714 -0
  547. package/foundation/doc-compiler/doc-loads.test.mjs +1630 -0
  548. package/foundation/doc-compiler/import.d.mts +24 -0
  549. package/foundation/doc-compiler/import.mjs +59 -0
  550. package/foundation/doc-compiler/inputs.d.mts +102 -0
  551. package/foundation/doc-compiler/inputs.mjs +291 -0
  552. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  553. package/foundation/doc-compiler/ir.d.mts +22 -0
  554. package/foundation/doc-compiler/ir.mjs +471 -0
  555. package/foundation/doc-compiler/lenses.d.mts +36 -0
  556. package/foundation/doc-compiler/lenses.mjs +173 -0
  557. package/foundation/doc-compiler/links.d.mts +162 -0
  558. package/foundation/doc-compiler/links.mjs +294 -0
  559. package/foundation/doc-compiler/links.test.mjs +192 -0
  560. package/foundation/doc-compiler/lower-doc.test.mjs +495 -0
  561. package/foundation/doc-compiler/overlays.d.mts +37 -0
  562. package/foundation/doc-compiler/overlays.mjs +206 -0
  563. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  564. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  565. package/foundation/doc-compiler/read.d.mts +127 -0
  566. package/foundation/doc-compiler/read.mjs +325 -0
  567. package/foundation/doc-compiler/read.test.mjs +313 -0
  568. package/foundation/doc-compiler/source.d.mts +33 -0
  569. package/foundation/doc-compiler/source.mjs +128 -0
  570. package/foundation/doc-compiler/tree.d.mts +288 -0
  571. package/foundation/doc-compiler/tree.mjs +876 -0
  572. package/foundation/doc-compiler/tree.test.mjs +606 -0
  573. package/foundation/fs/file-protection.d.mts +33 -0
  574. package/foundation/fs/file-protection.mjs +825 -0
  575. package/foundation/fs/file-protection.test.mjs +250 -0
  576. package/foundation/fs/module-loader.d.mts +1 -0
  577. package/foundation/fs/module-loader.mjs +50 -1
  578. package/foundation/fs/module-loader.stdout.test.mjs +332 -0
  579. package/foundation/fs/path-safety.d.mts +3 -2
  580. package/foundation/fs/path-safety.mjs +49 -19
  581. package/foundation/fs/path-safety.test.mjs +50 -0
  582. package/foundation/fs/publish-file-hardlink-unavailable.test.mjs +129 -94
  583. package/foundation/identity/provider-identity.d.mts +90 -0
  584. package/foundation/identity/provider-identity.mjs +320 -0
  585. package/foundation/identity/provider-identity.test.mjs +254 -0
  586. package/foundation/identity/providers.d.mts +7 -0
  587. package/foundation/identity/providers.mjs +16 -0
  588. package/foundation/integrations/autolink.d.mts +58 -1
  589. package/foundation/integrations/autolink.mjs +143 -45
  590. package/foundation/integrations/autolink.test.mjs +1 -1
  591. package/foundation/integrations/cli-requirement.d.mts +45 -0
  592. package/foundation/integrations/cli-requirement.mjs +154 -0
  593. package/foundation/integrations/cli-requirement.test.mjs +84 -0
  594. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  595. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  596. package/foundation/integrations/contribution-inventory.d.mts +3 -2
  597. package/foundation/integrations/contribution-inventory.mjs +27 -24
  598. package/foundation/integrations/contribution-inventory.test.mjs +86 -27
  599. package/foundation/integrations/integration-warnings.d.mts +9 -2
  600. package/foundation/integrations/integration-warnings.mjs +52 -21
  601. package/foundation/integrations/integration-warnings.test.mjs +74 -1
  602. package/foundation/integrations/integrations.d.mts +63 -3
  603. package/foundation/integrations/integrations.mjs +122 -9
  604. package/foundation/integrations/integrations.test.mjs +415 -1
  605. package/foundation/integrations/provider-conflicts.test.mjs +125 -0
  606. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  607. package/foundation/integrations/provider-resolution.d.mts +152 -0
  608. package/foundation/integrations/provider-resolution.mjs +576 -0
  609. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  610. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  611. package/foundation/integrations/theme-descriptor.mjs +44 -0
  612. package/foundation/integrations/validate-contributions.d.mts +2 -0
  613. package/foundation/integrations/validate-contributions.mjs +131 -29
  614. package/foundation/response/base.d.ts +8 -4
  615. package/foundation/response/batch.type.d.mts +33 -0
  616. package/foundation/response/batch.type.mjs +34 -0
  617. package/foundation/response/error-codes.d.mts +3 -1
  618. package/foundation/response/error-codes.d.ts +2 -0
  619. package/foundation/response/error-codes.doc.mjs +13 -4
  620. package/foundation/response/error-codes.mjs +8 -2
  621. package/foundation/response/error-codes.test.mjs +137 -10
  622. package/foundation/response/json-contract.test.mjs +57 -17
  623. package/foundation/response/json.d.mts +4 -2
  624. package/foundation/response/json.mjs +8 -10
  625. package/foundation/response/response-types.doc.d.mts +5 -1
  626. package/foundation/response/response-types.doc.mjs +46 -38
  627. package/foundation/response/response-types.doc.test.mjs +181 -0
  628. package/foundation/response/response.doc.mjs +1 -1
  629. package/foundation/text/string-utils.d.mts +8 -0
  630. package/foundation/text/string-utils.mjs +40 -10
  631. package/foundation/xle/browser.d.mts +3 -3
  632. package/foundation/xle/browser.mjs +3 -3
  633. package/foundation/xle/expand.d.mts +2 -0
  634. package/foundation/xle/expand.mjs +6 -5
  635. package/foundation/xle/expand.test.mjs +54 -0
  636. package/foundation/xle/parse.mjs +1 -1
  637. package/foundation/xle/print.mjs +2 -2
  638. package/foundation/xle/splice.mjs +1 -1
  639. package/foundation/xle/xle.test.mjs +13 -0
  640. package/package.json +10 -11
  641. package/api/layout/_adapter.d.mts +0 -34
  642. package/api/layout/_adapter.mjs +0 -133
  643. package/api/layout/check/check.d.mts +0 -16
  644. package/api/layout/check/check.mjs +0 -40
  645. package/api/layout/expand/expand.d.mts +0 -22
  646. package/api/layout/expand/expand.mjs +0 -153
  647. package/api/layout/grammar/grammar.d.mts +0 -13
  648. package/api/layout/grammar/grammar.mjs +0 -86
  649. package/api/layout/layout.d.mts +0 -6
  650. package/api/layout/layout.mjs +0 -17
  651. package/api/layout/layout.test.mjs +0 -297
  652. package/api/layout/layout.type.d.mts +0 -89
  653. package/api/layout/layout.type.mjs +0 -103
  654. package/api/layout/layoutCheck.doc.d.mts +0 -11
  655. package/api/layout/layoutCheck.doc.mjs +0 -84
  656. package/api/layout/layoutExpand.doc.d.mts +0 -11
  657. package/api/layout/layoutExpand.doc.mjs +0 -106
  658. package/api/layout/layoutGrammar.doc.d.mts +0 -11
  659. package/api/layout/layoutGrammar.doc.mjs +0 -56
  660. package/assets/templates/themes/manifest.json +0 -95
  661. package/clients/cli/commands/layout-check.doc.mjs +0 -54
  662. package/clients/cli/commands/layout-expand.doc.mjs +0 -66
  663. package/clients/cli/commands/layout-grammar.doc.mjs +0 -30
  664. package/clients/cli/commands/layout.doc.mjs +0 -34
  665. package/clients/cli/commands/layout.error-codes.test.mjs +0 -66
  666. package/clients/cli/commands/layout.exit-parity.test.mjs +0 -41
  667. package/clients/cli/commands/layout.mjs +0 -263
  668. package/clients/cli/lib/update-check.mjs +0 -83
  669. package/clients/cli/lib/update-check.test.mjs +0 -137
  670. package/clients/cli/update-hint-commands.test.mjs +0 -54
@@ -33,8 +33,19 @@
33
33
 
34
34
  import * as fs from 'node:fs';
35
35
  import * as path from 'node:path';
36
- import jscodeshift from 'jscodeshift';
37
36
  import {assertWithin} from '../../foundation/fs/path-safety.mjs';
37
+ import {
38
+ THEME_SLUG_RE,
39
+ unreadThemeFolders,
40
+ } from '../../foundation/discovery/theme-discovery.mjs';
41
+ import {
42
+ createFixContext,
43
+ DOC_CANDIDATE_RE,
44
+ pathIsInside,
45
+ stampOf,
46
+ TEMPLATE_CANDIDATE_RE,
47
+ unreachableFix,
48
+ } from '../../foundation/integrations/contribution-fixes.mjs';
38
49
  import {
39
50
  findManifestPaths,
40
51
  loadManifest,
@@ -90,106 +101,35 @@ const UNREACHABLE_SKIP_DIRS = new Set([
90
101
  '.next',
91
102
  'out',
92
103
  ]);
93
- const DOC_CANDIDATE_RE = /\.doc\.(?:ts|mjs|js)$/u;
94
- const TEMPLATE_CANDIDATE_RE = /\.template\.(?:ts|mjs|js)$/u;
95
- const STATIC_DOC_TYPES = new Set(['component', 'generic', 'page', 'block']);
96
- const STATIC_TEMPLATE_TYPES = new Set(['page', 'block']);
97
- const j = jscodeshift.withParser('tsx');
98
-
99
- /** @param {any} node @returns {any} */
100
- function unwrapStaticExpression(node) {
101
- let current = node;
102
- while (
103
- current &&
104
- [
105
- 'TSSatisfiesExpression',
106
- 'TSAsExpression',
107
- 'TypeCastExpression',
108
- 'ParenthesizedExpression',
109
- ].includes(current.type)
110
- ) {
111
- current = current.expression;
112
- }
113
- if (current?.type === 'CallExpression' && current.arguments.length > 0) {
114
- current = unwrapStaticExpression(current.arguments[0]);
115
- }
116
- return current;
117
- }
118
-
119
- /** @param {any} property @param {string} name */
120
- function staticPropertyNamed(property, name) {
121
- if (
122
- !property ||
123
- !['ObjectProperty', 'Property'].includes(property.type) ||
124
- property.computed
125
- ) {
126
- return false;
127
- }
128
- return (
129
- (property.key?.type === 'Identifier' && property.key.name === name) ||
130
- (['Literal', 'StringLiteral'].includes(property.key?.type) &&
131
- property.key.value === name)
132
- );
133
- }
134
-
135
104
  /**
136
- * Identify contribution metadata without importing it. Doctor scans files that
137
- * the manifest does not declare, so executing those files would run code the
138
- * package never asked Astryx to load.
139
- *
140
- * @param {string} file
141
- * @param {boolean} templateOnly
105
+ * A warning for each folder under the themes root that holds modules but is
106
+ * not read as a theme. Either branch of its fix leaves nothing to warn about:
107
+ * the folder becomes a theme, or a dot-folder discovery skips.
108
+ * @param {string} packageDir
109
+ * @param {import('../../foundation/integrations/integrations.mjs').LoadedIntegration} loaded
110
+ * @returns {Issue[]}
142
111
  */
143
- function isStaticContributionMetadata(file, templateOnly) {
144
- let ast;
145
- try {
146
- ast = j(fs.readFileSync(file, 'utf-8'));
147
- } catch {
148
- return false;
149
- }
150
- /** @type {any[]} */
151
- const candidates = [];
152
- ast
153
- .find(j.ExportDefaultDeclaration)
154
- .forEach((/** @type {any} */ exportPath) => {
155
- candidates.push(exportPath.value.declaration);
156
- });
157
- ast
158
- .find(j.ExportNamedDeclaration)
159
- .forEach((/** @type {any} */ exportPath) => {
160
- const declaration = exportPath.value.declaration;
161
- if (declaration?.type !== 'VariableDeclaration') return;
162
- for (const declarator of declaration.declarations) {
163
- if (
164
- declarator.id?.type === 'Identifier' &&
165
- declarator.id.name === 'docs'
166
- ) {
167
- candidates.push(declarator.init);
168
- }
169
- }
170
- });
171
-
172
- const allowedTypes = templateOnly ? STATIC_TEMPLATE_TYPES : STATIC_DOC_TYPES;
173
- for (const candidate of candidates) {
174
- const object = unwrapStaticExpression(candidate);
175
- if (object?.type !== 'ObjectExpression') continue;
176
- const typeProperty = object.properties.find((/** @type {any} */ property) =>
177
- staticPropertyNamed(property, 'type'),
178
- );
179
- const value = unwrapStaticExpression(typeProperty?.value);
180
- if (
181
- ['Literal', 'StringLiteral'].includes(value?.type) &&
182
- allowedTypes.has(value.value)
183
- ) {
184
- return true;
112
+ function unreadThemeFolderIssues(packageDir, loaded) {
113
+ const themes = /** @type {string} */ (loaded.themes);
114
+ return unreadThemeFolders(themes, {
115
+ packageDir,
116
+ packageName: loaded.name,
117
+ }).map(folder => {
118
+ const name = path.basename(folder);
119
+ const shown = `${path.relative(packageDir, folder).split(path.sep).join('/')}/`;
120
+ const hide = `rename it to .${name} so Astryx skips it`;
121
+ let fix;
122
+ if (THEME_SLUG_RE.test(name)) {
123
+ const stem = `${name.replace(/-([a-z0-9])/gu, (_, character) => character.toUpperCase())}Theme`;
124
+ fix = `if it is a theme, add ${stem}.ts and ${stem}.doc.mjs to it (\`astryx integration add theme ${name}\` writes both) and move its code into ${stem}.ts; if not, ${hide}.`;
125
+ } else {
126
+ fix = `${hide}; a theme folder needs a lower-kebab name.`;
185
127
  }
186
- }
187
- return false;
188
- }
189
-
190
- /** @param {string} candidate @param {string} root */
191
- function pathIsInside(candidate, root) {
192
- return candidate === root || candidate.startsWith(`${root}${path.sep}`);
128
+ return warning(
129
+ 'unread_theme_folder',
130
+ `Folder "${shown}" holds modules but no <name>Theme source or .doc.mjs descriptor, so Astryx does not read it as a theme. Fix: ${fix}`,
131
+ );
132
+ });
193
133
  }
194
134
 
195
135
  /**
@@ -214,6 +154,7 @@ async function findUnreachableContributionIssues(packageDir, loaded) {
214
154
  );
215
155
  /** @type {Issue[]} */
216
156
  const issues = [];
157
+ const context = createFixContext(packageDir, loaded);
217
158
  let scanned = 0;
218
159
  let truncated = false;
219
160
 
@@ -237,13 +178,18 @@ async function findUnreachableContributionIssues(packageDir, loaded) {
237
178
  truncated = true;
238
179
  return;
239
180
  }
240
- const isTemplate = TEMPLATE_CANDIDATE_RE.test(entry.name);
241
- if (!isTemplate && !DOC_CANDIDATE_RE.test(entry.name)) continue;
242
- if (!isStaticContributionMetadata(full, isTemplate)) continue;
181
+ if (
182
+ !TEMPLATE_CANDIDATE_RE.test(entry.name) &&
183
+ !DOC_CANDIDATE_RE.test(entry.name)
184
+ ) {
185
+ continue;
186
+ }
187
+ const stamp = stampOf(context, full);
188
+ if (stamp == null) continue;
243
189
  issues.push(
244
190
  warning(
245
191
  'unreachable_contribution',
246
- `Found contribution metadata "${path.relative(packageDir, full)}" outside every declared integration root, so it contributes nothing. Move it under the matching root or update the manifest root.`,
192
+ `Found contribution metadata "${path.relative(packageDir, full)}" outside every declared integration root, so it contributes nothing. ${unreachableFix(context, full, stamp)}`,
247
193
  ),
248
194
  );
249
195
  }
@@ -366,6 +312,8 @@ async function validateAtPackageDir(
366
312
  // Roots + contribution checks are shared with validateLoadedIntegration so
367
313
  // the everyday-command nudge runs the exact same validators.
368
314
  issues.push(...(await validateLoadedIntegration(loaded)));
315
+ if (loaded.themes)
316
+ issues.push(...unreadThemeFolderIssues(packageDir, loaded));
369
317
  if (scanUnreachable) {
370
318
  issues.push(
371
319
  ...(await findUnreachableContributionIssues(packageDir, loaded)),
@@ -400,8 +348,10 @@ export async function validateLocalIntegration(cwd = process.cwd()) {
400
348
  try {
401
349
  pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
402
350
  } catch (err) {
351
+ // A null name means "no manifest here"; this package has one.
403
352
  return {
404
353
  found: true,
354
+ name: '(local package)',
405
355
  manifestFile: manifests[0],
406
356
  issues: [
407
357
  error(
@@ -13,10 +13,16 @@ import {afterEach, beforeEach, describe, expect, it} from 'vitest';
13
13
  import * as fs from 'node:fs';
14
14
  import * as path from 'node:path';
15
15
  import {
16
+ validateIntegration,
16
17
  validateLocalIntegration,
17
18
  validateInstalledIntegration,
18
19
  summarizeIssues,
19
20
  } from './validate-integration.mjs';
21
+ import {
22
+ integrationComponentConflicts,
23
+ integrationDocConflicts,
24
+ integrationTemplateConflicts,
25
+ } from './authoring-checks.mjs';
20
26
 
21
27
  let tmpDir;
22
28
 
@@ -154,7 +160,7 @@ describe('validate-integration API', () => {
154
160
  fs.mkdirSync(componentsDir);
155
161
  fs.writeFileSync(
156
162
  path.join(componentsDir, 'Widget.doc.mjs'),
157
- `export default {name: 'Widget'};\n`,
163
+ `export default {name: 'Widget', props: []};\n`,
158
164
  );
159
165
  fs.writeFileSync(
160
166
  path.join(componentsDir, 'Widget.tsx'),
@@ -187,6 +193,39 @@ describe('validate-integration API', () => {
187
193
  expect(byCode(result.issues, 'invalid_codemod')).toHaveLength(1);
188
194
  });
189
195
 
196
+ it('names a broken codemod of an installed package by its path inside the package', async () => {
197
+ const consumer = path.join(tmpDir, 'consumer');
198
+ fs.mkdirSync(consumer, {recursive: true});
199
+ fs.writeFileSync(
200
+ path.join(consumer, 'package.json'),
201
+ JSON.stringify({name: 'consumer'}),
202
+ );
203
+ const pkgDir = path.join(consumer, 'node_modules', '@acme', 'kit');
204
+ writePackage(pkgDir, {
205
+ name: '@acme/kit',
206
+ manifest: `export default { codemods: './codemods' };\n`,
207
+ });
208
+ fs.mkdirSync(path.join(pkgDir, 'codemods', '1.1.0'), {recursive: true});
209
+ fs.writeFileSync(
210
+ path.join(pkgDir, 'codemods', '1.1.0', 'no-default.mjs'),
211
+ 'export const nope = 1;\n',
212
+ );
213
+ fs.writeFileSync(
214
+ path.join(pkgDir, 'codemods', 'stray.mjs'),
215
+ `export default {type: 'code', title: 'Stray', transform: file => file.source};\n`,
216
+ );
217
+
218
+ const result = await validateInstalledIntegration('@acme/kit', consumer);
219
+
220
+ const [broken] = byCode(result.issues, 'invalid_codemod');
221
+ expect(broken.message).toContain('(codemods/1.1.0/no-default.mjs)');
222
+ const [stray] = byCode(result.issues, 'codemod_outside_version');
223
+ expect(stray.message).toContain('"codemods/stray.mjs"');
224
+ for (const issue of result.issues) {
225
+ expect(issue.message).not.toContain(tmpDir);
226
+ }
227
+ });
228
+
190
229
  it('flags a broken template as invalid_template error', async () => {
191
230
  const pkgDir = path.join(tmpDir, 'pkg');
192
231
  writePackage(pkgDir, {
@@ -204,33 +243,24 @@ describe('validate-integration API', () => {
204
243
  expect(byCode(result.issues, 'invalid_template')).toHaveLength(1);
205
244
  });
206
245
 
207
- it('reports no errors for a valid source-theme catalog', async () => {
246
+ it('reports no errors for a valid source-theme descriptor', async () => {
208
247
  const pkgDir = path.join(tmpDir, 'pkg');
209
248
  writePackage(pkgDir, {
210
- manifest: `export default { themes: './themes' };\n`,
249
+ manifest: `export default { themes: './themes' };
250
+ `,
211
251
  });
212
252
  const themeDir = path.join(pkgDir, 'themes', 'ocean');
213
253
  fs.mkdirSync(themeDir, {recursive: true});
214
254
  fs.writeFileSync(
215
- path.join(pkgDir, 'themes', 'manifest.json'),
216
- JSON.stringify({
217
- version: 1,
218
- themes: [
219
- {
220
- slug: 'ocean',
221
- displayName: 'Ocean',
222
- description: 'Blue and calm.',
223
- maintained: true,
224
- entry: 'oceanTheme.ts',
225
- exportName: 'oceanTheme',
226
- files: ['oceanTheme.ts'],
227
- },
228
- ],
229
- }),
255
+ path.join(themeDir, 'oceanTheme.doc.mjs'),
256
+ `/** @type {import('@astryxdesign/cli/authoring').ThemeDoc} */
257
+ export default {type: 'theme', name: 'ocean', displayName: 'Ocean', description: 'Blue and calm.', maintained: true};
258
+ `,
230
259
  );
231
260
  fs.writeFileSync(
232
261
  path.join(themeDir, 'oceanTheme.ts'),
233
- `export const oceanTheme = {};\n`,
262
+ `export const oceanTheme = {};
263
+ `,
234
264
  );
235
265
 
236
266
  const result = await validateLocalIntegration(pkgDir);
@@ -238,13 +268,17 @@ describe('validate-integration API', () => {
238
268
  expect(summarizeIssues(result.issues).errors).toBe(0);
239
269
  });
240
270
 
241
- it('flags an unreadable source-theme catalog as invalid_theme', async () => {
271
+ it('flags an obsolete source-theme catalog as invalid_theme', async () => {
242
272
  const pkgDir = path.join(tmpDir, 'pkg');
243
273
  writePackage(pkgDir, {
244
- manifest: `export default { themes: './themes' };\n`,
274
+ manifest: `export default { themes: './themes' };
275
+ `,
245
276
  });
246
277
  fs.mkdirSync(path.join(pkgDir, 'themes'), {recursive: true});
247
- fs.writeFileSync(path.join(pkgDir, 'themes', 'manifest.json'), '{not-json');
278
+ fs.writeFileSync(
279
+ path.join(pkgDir, 'themes', 'manifest.json'),
280
+ '{"version":1}',
281
+ );
248
282
 
249
283
  const result = await validateLocalIntegration(pkgDir);
250
284
  expect(byCode(result.issues, 'invalid_theme')).toHaveLength(1);
@@ -269,6 +303,11 @@ describe('validate-integration API', () => {
269
303
  message: expect.stringContaining('InvisibleWidget.doc.mjs'),
270
304
  }),
271
305
  ]);
306
+ expect(
307
+ byCode(result.issues, 'source_without_component_doc')[0].message,
308
+ ).toContain(
309
+ "Fix: add InvisibleWidget.doc.mjs beside it with type: 'component'",
310
+ );
272
311
  });
273
312
 
274
313
  it('reports codemods outside semver folders and invalid folder names', async () => {
@@ -284,8 +323,12 @@ describe('validate-integration API', () => {
284
323
 
285
324
  const result = await validateLocalIntegration(pkgDir);
286
325
 
287
- expect(byCode(result.issues, 'codemod_outside_version')).toHaveLength(1);
288
- expect(byCode(result.issues, 'invalid_codemod_version')).toHaveLength(1);
326
+ const [stray] = byCode(result.issues, 'codemod_outside_version');
327
+ expect(stray.message).toContain('"codemods/forgotten.mjs"');
328
+ expect(stray.message).toContain('codemods/1.2.0/forgotten.mjs');
329
+ expect(stray.message).not.toContain(tmpDir);
330
+ const [folder] = byCode(result.issues, 'invalid_codemod_version');
331
+ expect(folder.message).toContain('Fix: rename it');
289
332
  });
290
333
 
291
334
  it('warns about valid contribution metadata outside every declared root', async () => {
@@ -327,6 +370,31 @@ describe('validate-integration API', () => {
327
370
  const unreachable = byCode(result.issues, 'unreachable_contribution');
328
371
  expect(unreachable).toHaveLength(1);
329
372
  expect(unreachable[0].message).toContain('src/orphan.doc.mjs');
373
+ // No docs root is declared, but src/ also holds a .doc.mjs that is not a
374
+ // topic, which a docs root at src/ would read too; so the fix moves it.
375
+ expect(unreachable[0].message).toContain(
376
+ "Fix: move it into docs/ and set `docs: './docs'` in astryx.integration.mjs.",
377
+ );
378
+ });
379
+
380
+ it('names the root that reads misplaced metadata when one is declared', async () => {
381
+ const pkgDir = path.join(tmpDir, 'pkg');
382
+ writePackage(pkgDir, {
383
+ manifest: `export default { templates: './templates' };\n`,
384
+ });
385
+ fs.mkdirSync(path.join(pkgDir, 'templates'));
386
+ fs.mkdirSync(path.join(pkgDir, 'src', 'blocks'), {recursive: true});
387
+ fs.writeFileSync(
388
+ path.join(pkgDir, 'src', 'blocks', 'Carousel.doc.mjs'),
389
+ `export default {type: 'block', name: 'Carousel', displayName: 'Carousel', aspectRatio: 1};\n`,
390
+ );
391
+
392
+ const result = await validateLocalIntegration(pkgDir);
393
+
394
+ const [issue] = byCode(result.issues, 'unreachable_contribution');
395
+ expect(issue.message).toContain(
396
+ "Fix: move it under templates/ (the templates root), or set `templates: './src/blocks'` in astryx.integration.mjs.",
397
+ );
330
398
  });
331
399
 
332
400
  it('never executes unreachable metadata while diagnosing it', async () => {
@@ -417,7 +485,7 @@ describe('validate-integration API', () => {
417
485
  fs.mkdirSync(cDir, {recursive: true});
418
486
  fs.writeFileSync(
419
487
  path.join(cDir, 'Widget.doc.mjs'),
420
- `export default { name: 'Widget' };\n`,
488
+ `export default { type: 'component', name: 'Widget', props: [] };\n`,
421
489
  );
422
490
  fs.writeFileSync(
423
491
  path.join(cDir, 'Widget.tsx'),
@@ -439,7 +507,7 @@ describe('validate-integration API', () => {
439
507
  // Doc with no sibling Widget.tsx.
440
508
  fs.writeFileSync(
441
509
  path.join(cDir, 'Widget.doc.mjs'),
442
- `export default { name: 'Widget' };\n`,
510
+ `export default { type: 'component', name: 'Widget', props: [] };\n`,
443
511
  );
444
512
 
445
513
  const result = await validateLocalIntegration(pkgDir);
@@ -472,3 +540,88 @@ describe('validate-integration API', () => {
472
540
  expect(byCode(result.issues, 'invalid_package_spec')).toHaveLength(1);
473
541
  });
474
542
  });
543
+
544
+ describe('integration diagnostics are read-only', () => {
545
+ /** Every directory and file under `dir`, with file bytes. */
546
+ function snapshot(dir) {
547
+ /** @type {Record<string, string>} */
548
+ const entries = {};
549
+ /** @param {string} current */
550
+ const walk = current => {
551
+ for (const entry of fs.readdirSync(current, {withFileTypes: true})) {
552
+ const full = path.join(current, entry.name);
553
+ const key = path.relative(dir, full);
554
+ if (entry.isDirectory()) {
555
+ entries[`${key}/`] = '';
556
+ walk(full);
557
+ } else {
558
+ entries[key] = fs.readFileSync(full, 'base64');
559
+ }
560
+ }
561
+ };
562
+ walk(dir);
563
+ return entries;
564
+ }
565
+
566
+ /** A package with valid, broken, conflicting, and unreachable contributions. */
567
+ function writeDiagnosedPackage(dir) {
568
+ writePackage(dir, {
569
+ manifest:
570
+ "export default {\n components: './components',\n templates: './templates',\n docs: './docs',\n codemods: './gone',\n themes: './themes',\n};\n",
571
+ });
572
+ const write = (relative, contents) => {
573
+ fs.mkdirSync(path.dirname(path.join(dir, relative)), {recursive: true});
574
+ fs.writeFileSync(path.join(dir, relative), contents);
575
+ };
576
+ write(
577
+ 'components/Card.doc.mjs',
578
+ "export default {type: 'component', name: 'Card', props: []};\n",
579
+ );
580
+ write('components/Card.tsx', 'export function Card() { return null; }\n');
581
+ write(
582
+ 'components/Orphan.doc.mjs',
583
+ "export default {type: 'component', name: 'Orphan', props: []};\n",
584
+ );
585
+ write('templates/dash.doc.mjs', "export default {type: 'page', name: 'Dash'};\n");
586
+ write(
587
+ 'docs/theme.doc.mjs',
588
+ "export default {type: 'generic', name: 'theme', title: 'Theme', description: 'x', sections: [{title: 'A', content: [{type: 'prose', text: 'x'}]}]};\n",
589
+ );
590
+ write('themes/manifest.json', '{"version": 1, "themes": [{"slug": 7}]}\n');
591
+ write(
592
+ 'stray/Stray.doc.mjs',
593
+ "export default {type: 'component', name: 'Stray', props: []};\n",
594
+ );
595
+ }
596
+
597
+ it('leaves local and installed packages byte-for-byte unchanged', async () => {
598
+ const pkgDir = path.join(tmpDir, 'pkg');
599
+ writeDiagnosedPackage(pkgDir);
600
+ const consumer = path.join(tmpDir, 'consumer');
601
+ fs.mkdirSync(consumer, {recursive: true});
602
+ fs.writeFileSync(
603
+ path.join(consumer, 'package.json'),
604
+ JSON.stringify({name: 'consumer'}),
605
+ );
606
+ writeDiagnosedPackage(path.join(consumer, 'node_modules', '@acme', 'widgets'));
607
+ const before = {pkg: snapshot(pkgDir), consumer: snapshot(consumer)};
608
+
609
+ const local = await validateIntegration(undefined, {cwd: pkgDir});
610
+ const installed = await validateIntegration('@acme/widgets', {
611
+ cwd: consumer,
612
+ });
613
+ for (const [pkg, cwd] of [
614
+ [undefined, pkgDir],
615
+ ['@acme/widgets', consumer],
616
+ ]) {
617
+ await integrationTemplateConflicts(pkg, {cwd});
618
+ await integrationComponentConflicts(pkg, {cwd});
619
+ await integrationDocConflicts(pkg, {cwd});
620
+ }
621
+
622
+ expect(summarizeIssues(local.data.issues).errors).toBeGreaterThan(0);
623
+ expect(byCode(local.data.issues, 'unreachable_contribution')).toHaveLength(1);
624
+ expect(summarizeIssues(installed.data.issues).errors).toBeGreaterThan(0);
625
+ expect({pkg: snapshot(pkgDir), consumer: snapshot(consumer)}).toEqual(before);
626
+ });
627
+ });
@@ -0,0 +1,110 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file `doctor integration validate` warns about a folder under the themes
5
+ * root that holds modules but is not read as a theme, and both branches of
6
+ * its fix leave nothing to warn about.
7
+ *
8
+ * @input a local integration package with a themes root
9
+ * @output the unread_theme_folder warnings validation reports
10
+ * @position packages/cli/api/integration — validation regression tests
11
+ */
12
+
13
+ import {afterEach, beforeEach, describe, expect, it} from 'vitest';
14
+ import * as fs from 'node:fs';
15
+ import * as path from 'node:path';
16
+ import {validateLocalIntegration} from './validate-integration.mjs';
17
+ import {integrationAddTheme} from './add-theme.mjs';
18
+
19
+ let tmpDir;
20
+
21
+ beforeEach(() => {
22
+ tmpDir = fs.mkdtempSync(path.join(process.cwd(), '.astryx-unread-theme-'));
23
+ fs.writeFileSync(
24
+ path.join(tmpDir, 'package.json'),
25
+ JSON.stringify({name: '@acme/kit', version: '1.0.0'}),
26
+ );
27
+ fs.writeFileSync(
28
+ path.join(tmpDir, 'astryx.integration.mjs'),
29
+ "export default {themes: './themes'};\n",
30
+ );
31
+ });
32
+
33
+ afterEach(() => {
34
+ fs.rmSync(tmpDir, {recursive: true, force: true});
35
+ });
36
+
37
+ /** @param {Record<string, string>} files paths under themes/ */
38
+ function writeThemes(files) {
39
+ for (const [file, contents] of Object.entries(files)) {
40
+ const target = path.join(tmpDir, 'themes', file);
41
+ fs.mkdirSync(path.dirname(target), {recursive: true});
42
+ fs.writeFileSync(target, contents);
43
+ }
44
+ }
45
+
46
+ const OCEAN = {
47
+ 'ocean/oceanTheme.doc.mjs':
48
+ "/** @type {import('@astryxdesign/cli/authoring').ThemeDoc} */\nexport default {type: 'theme', name: 'ocean', displayName: 'Ocean', description: 'Blue.', maintained: true};\n",
49
+ 'ocean/oceanTheme.ts':
50
+ "import {blue} from '@acme/kit/themes/shared/palette';\nexport const oceanTheme = {blue};\n",
51
+ 'shared/palette.ts': 'export const blue = 1;\n',
52
+ };
53
+
54
+ async function unread() {
55
+ const {issues} = await validateLocalIntegration(tmpDir);
56
+ return issues.filter(issue => issue.code === 'unread_theme_folder');
57
+ }
58
+
59
+ describe('unread theme folders', () => {
60
+ it('warns about each folder that looks like a theme but is not read as one', async () => {
61
+ writeThemes({
62
+ ...OCEAN,
63
+ 'sand/sand.ts': 'export const sand = {};\n',
64
+ 'sand/sand.doc.ts': "export default {type: 'theme', name: 'sand'};\n",
65
+ 'reef/index.ts': 'export const reefTheme = {};\n',
66
+ 'Tide_Pool/index.ts': 'export const tide = {};\n',
67
+ 'fonts/inter.woff2': 'x',
68
+ 'utils/format.ts': 'export const format = String;\n',
69
+ '.cache/index.ts': 'export {};\n',
70
+ });
71
+ const issues = await unread();
72
+ expect(issues.map(issue => issue.severity)).toEqual([
73
+ 'warning',
74
+ 'warning',
75
+ 'warning',
76
+ ]);
77
+ expect(issues.map(issue => issue.message)).toEqual([
78
+ 'Folder "themes/Tide_Pool/" holds modules but no <name>Theme source or .doc.mjs descriptor, so Astryx does not read it as a theme. Fix: rename it to .Tide_Pool so Astryx skips it; a theme folder needs a lower-kebab name.',
79
+ 'Folder "themes/reef/" holds modules but no <name>Theme source or .doc.mjs descriptor, so Astryx does not read it as a theme. Fix: if it is a theme, add reefTheme.ts and reefTheme.doc.mjs to it (`astryx integration add theme reef` writes both) and move its code into reefTheme.ts; if not, rename it to .reef so Astryx skips it.',
80
+ 'Folder "themes/sand/" holds modules but no <name>Theme source or .doc.mjs descriptor, so Astryx does not read it as a theme. Fix: if it is a theme, add sandTheme.ts and sandTheme.doc.mjs to it (`astryx integration add theme sand` writes both) and move its code into sandTheme.ts; if not, rename it to .sand so Astryx skips it.',
81
+ ]);
82
+ });
83
+
84
+ it('does not warn about a helper folder a module imports by a relative path', async () => {
85
+ writeThemes({
86
+ ...OCEAN,
87
+ 'index.ts':
88
+ "export * from './ocean/oceanTheme';\nexport * from './util';\n",
89
+ 'util/index.ts': 'export const util = 1;\n',
90
+ });
91
+ expect(await unread()).toEqual([]);
92
+ });
93
+
94
+ it('holds when either branch of the fix is followed', async () => {
95
+ writeThemes({
96
+ ...OCEAN,
97
+ 'sand/sand.ts': 'export const sand = {};\n',
98
+ 'reef/index.ts': 'export const reefTheme = {};\n',
99
+ 'Tide_Pool/index.ts': 'export const tide = {};\n',
100
+ });
101
+ await integrationAddTheme('sand', {cwd: tmpDir});
102
+ await integrationAddTheme('reef', {cwd: tmpDir});
103
+ fs.renameSync(
104
+ path.join(tmpDir, 'themes', 'Tide_Pool'),
105
+ path.join(tmpDir, 'themes', '.Tide_Pool'),
106
+ );
107
+ const {issues} = await validateLocalIntegration(tmpDir);
108
+ expect(issues).toEqual([]);
109
+ });
110
+ });
@@ -12,6 +12,7 @@ export const doc = {
12
12
  type: 'function',
13
13
  kind: 'api',
14
14
  name: 'validateIntegration',
15
+ namespace: 'cli/api',
15
16
  displayName: 'validateIntegration()',
16
17
  summary:
17
18
  'Validate a single Astryx integration package and report its issues.',
@@ -45,7 +46,7 @@ export const doc = {
45
46
  {
46
47
  type: 'integration.validate',
47
48
  description:
48
- 'The result envelope: `data.name` and `data.version` of the validated package (both null when no local manifest is found), plus `data.issues`, an AstryxIntegrationIssue[] of {code, severity: `warning` | `error`, message}.',
49
+ 'The result envelope: `data.name` and `data.version` of the validated package (both null only when no local manifest is found; `data.name` is `(local package)` when the local package.json has no readable name), plus `data.issues`, an AstryxIntegrationIssue[] of {code, severity: `warning` | `error`, message}.',
49
50
  },
50
51
  ],
51
52
  examples: [
@@ -59,5 +60,5 @@ export const doc = {
59
60
  },
60
61
  ],
61
62
  command: 'doctor integration validate',
62
- related: ['summarizeIssues', 'doctor integration templates', 'upgrade'],
63
+ related: ['summarizeIssues', 'integrationTemplateConflicts', 'upgrade'],
63
64
  };
@@ -11,6 +11,7 @@ export const doc = {
11
11
  type: 'function',
12
12
  kind: 'api',
13
13
  name: 'assertResponse',
14
+ namespace: 'cli/api',
14
15
  displayName: 'assertResponse()',
15
16
  summary:
16
17
  'Parse and assert one expected response type, throwing on an error or a mismatch.',