@astryxdesign/cli 0.7.2-canary.fe2c655 → 0.7.2

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 (509) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/README.md +175 -154
  3. package/api/build/_adapter.d.mts +8 -0
  4. package/api/build/_adapter.mjs +12 -1
  5. package/api/build/build.doc.mjs +4 -0
  6. package/api/build/help/help.mjs +1 -1
  7. package/api/build/kit/kit.mjs +3 -11
  8. package/api/component/_adapter.d.mts +72 -1
  9. package/api/component/_adapter.mjs +212 -18
  10. package/api/component/component.doc.mjs +6 -1
  11. package/api/component/component.mjs +82 -15
  12. package/api/component/component.test.mjs +80 -0
  13. package/api/component/doc-links.test.mjs +386 -0
  14. package/api/component/integration-export-name.test.mjs +644 -0
  15. package/api/component/list/list.mjs +42 -4
  16. package/api/discover/_adapter.d.mts +132 -12
  17. package/api/discover/_adapter.mjs +488 -27
  18. package/api/discover/_adapter.test.mjs +599 -17
  19. package/api/discover/_catalog-view.d.mts +16 -5
  20. package/api/discover/_catalog-view.mjs +32 -8
  21. package/api/discover/detail/doc/doc.mjs +9 -1
  22. package/api/discover/discover.d.mts +11 -0
  23. package/api/discover/discover.doc.mjs +9 -7
  24. package/api/discover/discover.mjs +121 -19
  25. package/api/discover/discover.type.d.mts +20 -7
  26. package/api/discover/discover.type.mjs +17 -7
  27. package/api/discover/list/list.d.mts +4 -3
  28. package/api/discover/list/list.mjs +17 -10
  29. package/api/docs/_adapter.d.mts +74 -0
  30. package/api/docs/_adapter.mjs +553 -16
  31. package/api/docs/docs.doc.mjs +2 -1
  32. package/api/docs/docs.mjs +2 -1
  33. package/api/docs/docs.test.mjs +5 -2
  34. package/api/docs/integration-tree.test.mjs +22 -0
  35. package/api/docs/integrationDocs.test.mjs +124 -0
  36. package/api/docs/list/list.mjs +12 -2
  37. package/api/docs/reference-blocks.test.mjs +1 -3
  38. package/api/doctor/_adapter.d.mts +108 -0
  39. package/api/doctor/_adapter.mjs +223 -4
  40. package/api/doctor/doctor.d.mts +199 -0
  41. package/api/doctor/doctor.doc.mjs +3 -2
  42. package/api/doctor/doctor.mjs +530 -34
  43. package/api/doctor/doctor.test.mjs +180 -14
  44. package/api/doctor/release-checks.test.mjs +156 -0
  45. package/api/doctor/theme-checks.mjs +17 -4
  46. package/api/doctor/theme-checks.test.mjs +223 -7
  47. package/api/error.d.mts +10 -0
  48. package/api/error.mjs +25 -0
  49. package/api/gap-report/gap-report.d.mts +3 -0
  50. package/api/gap-report/gap-report.doc.mjs +11 -3
  51. package/api/gap-report/gap-report.mjs +219 -52
  52. package/api/gap-report/gap-report.test.mjs +233 -0
  53. package/api/gap-report/gap-report.type.d.mts +41 -0
  54. package/api/gap-report/gap-report.type.mjs +18 -0
  55. package/api/hook/_adapter.mjs +3 -11
  56. package/api/hook/hook.doc.mjs +4 -0
  57. package/api/hook/list/list.d.mts +1 -1
  58. package/api/index.d.mts +2 -0
  59. package/api/index.mjs +2 -0
  60. package/api/init/_adapter.d.mts +22 -0
  61. package/api/init/_adapter.mjs +59 -0
  62. package/api/init/init.d.mts +7 -5
  63. package/api/init/init.doc.mjs +28 -7
  64. package/api/init/init.mjs +28 -4
  65. package/api/init/init.type.d.mts +48 -3
  66. package/api/init/init.type.mjs +37 -3
  67. package/api/init/run/run.d.mts +1 -1
  68. package/api/init/run/run.mjs +17 -6
  69. package/api/init/user/user.d.mts +14 -0
  70. package/api/init/user/user.mjs +87 -0
  71. package/api/init/user/user.test.mjs +232 -0
  72. package/api/integration/_adapter.d.mts +45 -0
  73. package/api/integration/_adapter.mjs +112 -0
  74. package/api/integration/add-contribution.component-names.test.mjs +66 -0
  75. package/api/integration/add-contribution.mjs +8 -4
  76. package/api/integration/add-contribution.test.mjs +4 -2
  77. package/api/integration/authoring-checks.mjs +110 -6
  78. package/api/integration/authoring-checks.test.mjs +808 -0
  79. package/api/integration/authoring-checks.type.d.mts +143 -0
  80. package/api/integration/authoring-checks.type.mjs +74 -2
  81. package/api/integration/check/check.d.mts +96 -0
  82. package/api/integration/check/check.mjs +357 -0
  83. package/api/integration/check/check.test.mjs +489 -0
  84. package/api/integration/integration-check.type.d.mts +118 -0
  85. package/api/integration/integration-check.type.mjs +84 -0
  86. package/api/integration/integrationCheck.doc.d.mts +10 -0
  87. package/api/integration/integrationCheck.doc.mjs +73 -0
  88. package/api/integration/integrationComponentConflicts.doc.mjs +45 -6
  89. package/api/integration/integrationDocConflicts.doc.mjs +22 -5
  90. package/api/integration/pack-check.mjs +364 -120
  91. package/api/integration/pack-check.test.mjs +730 -10
  92. package/api/integration/validate-integration-fixes.test.mjs +67 -0
  93. package/api/integration/validate-integration.d.mts +8 -0
  94. package/api/integration/validate-integration.mjs +63 -9
  95. package/api/integration/validate-integration.test.mjs +88 -8
  96. package/api/integration/validate-integration.type.d.mts +16 -0
  97. package/api/integration/validate-integration.type.mjs +14 -1
  98. package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
  99. package/api/integration/validateIntegration.doc.mjs +19 -3
  100. package/api/search/_adapter.d.mts +11 -0
  101. package/api/search/_adapter.mjs +25 -0
  102. package/api/search/search.d.mts +82 -13
  103. package/api/search/search.doc.mjs +8 -3
  104. package/api/search/search.domain-priority.test.mjs +108 -18
  105. package/api/search/search.integration-check.test.mjs +24 -0
  106. package/api/search/search.mjs +645 -64
  107. package/api/search/search.test.mjs +179 -1
  108. package/api/search/search.type.d.mts +14 -1
  109. package/api/search/search.type.mjs +6 -1
  110. package/api/swizzle/_adapter.mjs +2 -2
  111. package/api/swizzle/copy/copy.mjs +29 -15
  112. package/api/template/template-integration.test.mjs +1 -1
  113. package/api/template/template.test.mjs +120 -3
  114. package/api/theme/_adapter.d.mts +16 -0
  115. package/api/theme/_adapter.mjs +32 -5
  116. package/api/theme/build/build.d.mts +2 -1
  117. package/api/theme/build/build.family.test.mjs +64 -0
  118. package/api/theme/build/build.mjs +250 -38
  119. package/api/theme/build/build.packed-old-core.test.mjs +20 -3
  120. package/api/theme/build/font-warning.mjs +5 -3
  121. package/api/theme/build/font-warning.test.mjs +2 -1
  122. package/api/theme/remove/remove.test.mjs +2 -2
  123. package/api/theme/targets/targets.mjs +3 -10
  124. package/api/theme/themeBuild.doc.mjs +4 -4
  125. package/api/theme/themeTargets.doc.mjs +4 -0
  126. package/api/theme/use/use.test.mjs +1 -1
  127. package/api/upgrade/_adapter.d.mts +40 -2
  128. package/api/upgrade/_adapter.mjs +118 -5
  129. package/api/upgrade/run/cli-behind-core.test.mjs +438 -0
  130. package/api/upgrade/run/run.mjs +35 -2
  131. package/api/upgrade/status/status.d.mts +21 -5
  132. package/api/upgrade/status/status.mjs +45 -8
  133. package/api/upgrade/upgrade.doc.mjs +6 -3
  134. package/api/upgrade/upgrade.mjs +5 -1
  135. package/api/upgrade/upgrade.type.d.mts +23 -0
  136. package/api/upgrade/upgrade.type.mjs +16 -1
  137. package/assets/codemods/__tests__/registry.test.mjs +1 -0
  138. package/assets/codemods/registry.mjs +1 -0
  139. package/assets/codemods/runner.mjs +7 -1
  140. package/assets/codemods/transforms/v0.7.2/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +120 -0
  141. package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
  142. package/assets/codemods/transforms/v0.7.2/migrate-list-edge-compensation-to-edge.mjs +198 -0
  143. package/assets/discover/official-packages.json +367 -0
  144. package/assets/docs/README.md +10 -0
  145. package/assets/docs/author-a-theme.doc.mjs +3 -3
  146. package/assets/docs/browser-support.doc.mjs +1 -1
  147. package/assets/docs/getting-started.doc.mjs +26 -6
  148. package/assets/docs/styling-overview.doc.mjs +1 -1
  149. package/assets/docs/theme.doc.dense.mjs +1 -1
  150. package/assets/docs/theme.doc.mjs +2 -2
  151. package/assets/docs/theme.doc.zh.mjs +1 -1
  152. package/assets/docs/tree/add-a-component.doc.mjs +22 -2
  153. package/assets/docs/tree/add-a-theme.doc.mjs +13 -3
  154. package/assets/docs/tree/add-a-topic.doc.mjs +54 -9
  155. package/assets/docs/tree/agent-guidance.doc.mjs +19 -5
  156. package/assets/docs/tree/block-template.doc.mjs +8 -20
  157. package/assets/docs/tree/build-the-template.doc.mjs +1 -1
  158. package/assets/docs/tree/building-blocks.doc.mjs +4 -0
  159. package/assets/docs/tree/check-the-props.doc.mjs +201 -0
  160. package/assets/docs/tree/check-your-docs.doc.mjs +69 -11
  161. package/assets/docs/tree/checks.doc.mjs +32 -24
  162. package/assets/docs/tree/ci-and-containers.doc.mjs +88 -0
  163. package/assets/docs/tree/cli-command.doc.mjs +142 -0
  164. package/assets/docs/tree/cli.doc.mjs +6 -0
  165. package/assets/docs/tree/codemods.doc.mjs +17 -7
  166. package/assets/docs/tree/commands.doc.mjs +7 -1
  167. package/assets/docs/tree/component-family.doc.mjs +8 -6
  168. package/assets/docs/tree/component-imports.doc.mjs +21 -3
  169. package/assets/docs/tree/components.doc.mjs +7 -1
  170. package/assets/docs/tree/computer-agent-guide.doc.mjs +160 -0
  171. package/assets/docs/tree/computer-integrations.doc.mjs +93 -0
  172. package/assets/docs/tree/configuration.doc.mjs +7 -3
  173. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +41 -22
  174. package/assets/docs/tree/define-the-theme.doc.mjs +6 -5
  175. package/assets/docs/tree/describe-the-component.doc.mjs +3 -3
  176. package/assets/docs/tree/docs.doc.mjs +9 -3
  177. package/assets/docs/tree/document-the-template.doc.mjs +1 -1
  178. package/assets/docs/tree/document-the-theme.doc.mjs +3 -3
  179. package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
  180. package/assets/docs/tree/extend-or-replace.doc.mjs +19 -9
  181. package/assets/docs/tree/fonts-and-assets.doc.mjs +2 -2
  182. package/assets/docs/tree/generate-a-palette.doc.mjs +7 -5
  183. package/assets/docs/tree/global-integrations.doc.mjs +124 -0
  184. package/assets/docs/tree/global.doc.mjs +131 -0
  185. package/assets/docs/tree/grade-template-with-agent.doc.mjs +5 -5
  186. package/assets/docs/tree/install-once.doc.mjs +105 -0
  187. package/assets/docs/tree/integrations.doc.mjs +13 -1
  188. package/assets/docs/tree/layout-spacing.doc.mjs +2 -3
  189. package/assets/docs/tree/layout.doc.mjs +6 -6
  190. package/assets/docs/tree/links.doc.mjs +7 -6
  191. package/assets/docs/tree/migration-setup.doc.mjs +3 -2
  192. package/assets/docs/tree/migration-verification.doc.mjs +0 -1
  193. package/assets/docs/tree/migration.doc.mjs +0 -1
  194. package/assets/docs/tree/monorepos.doc.mjs +84 -0
  195. package/assets/docs/tree/package-and-test.doc.mjs +1 -1
  196. package/assets/docs/tree/page-template.doc.mjs +4 -8
  197. package/assets/docs/tree/problems.doc.mjs +205 -0
  198. package/assets/docs/tree/project-global-or-both.doc.mjs +131 -0
  199. package/assets/docs/tree/publishing.doc.mjs +6 -6
  200. package/assets/docs/tree/quick-start.doc.mjs +53 -27
  201. package/assets/docs/tree/reference.doc.mjs +192 -0
  202. package/assets/docs/tree/replace-a-core-component.doc.mjs +15 -7
  203. package/assets/docs/tree/replace-a-core-template.doc.mjs +10 -12
  204. package/assets/docs/tree/scaffold.doc.mjs +1 -1
  205. package/assets/docs/tree/sections-and-placement.doc.mjs +9 -11
  206. package/assets/docs/tree/see-it-in-an-app.doc.mjs +17 -5
  207. package/assets/docs/tree/short-and-findable.doc.mjs +9 -8
  208. package/assets/docs/tree/single-component.doc.mjs +15 -6
  209. package/assets/docs/tree/start-a-template.doc.mjs +18 -8
  210. package/assets/docs/tree/subcomponent.doc.mjs +6 -6
  211. package/assets/docs/tree/template-assets.doc.mjs +2 -2
  212. package/assets/docs/tree/template-doc-overview.doc.mjs +6 -17
  213. package/assets/docs/tree/template-fonts.doc.mjs +1 -1
  214. package/assets/docs/tree/template-icons.doc.mjs +1 -1
  215. package/assets/docs/tree/template-images-media.doc.mjs +1 -1
  216. package/assets/docs/tree/template-styles.doc.mjs +2 -2
  217. package/assets/docs/tree/templates.doc.mjs +7 -1
  218. package/assets/docs/tree/test-in-an-app.doc.mjs +7 -7
  219. package/assets/docs/tree/test-template-in-app.doc.mjs +5 -5
  220. package/assets/docs/tree/themes.doc.mjs +4 -0
  221. package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
  222. package/assets/docs/tree/troubleshooting.doc.mjs +29 -13
  223. package/assets/docs/tree/type-scale.doc.mjs +3 -3
  224. package/assets/docs/tree/uninstall.doc.mjs +109 -0
  225. package/assets/docs/tree/updates.doc.mjs +92 -0
  226. package/assets/docs/tree/upgrading.doc.mjs +6 -6
  227. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +14 -2
  228. package/assets/docs/tree/verify-packed-template.doc.mjs +3 -3
  229. package/assets/docs/tree/versioning.doc.mjs +10 -9
  230. package/assets/docs/tree/who-answers.doc.mjs +119 -0
  231. package/assets/docs/tree/write-the-template-file.doc.mjs +7 -6
  232. package/assets/docs/use-a-theme.doc.mjs +2 -2
  233. package/assets/docs/working-with-ai.doc.mjs +66 -13
  234. package/assets/theme.template.ts +1 -1
  235. package/authoring/codemod/codemod.doc.mjs +7 -3
  236. package/authoring/config/config.doc.mjs +9 -6
  237. package/authoring/config/type.ts +4 -2
  238. package/authoring/debug/parse.d.mts +5 -5
  239. package/authoring/discover/discover.doc.mjs +7 -1
  240. package/authoring/doctypes/_schema.d.mts +8 -3
  241. package/authoring/doctypes/_schema.mjs +1 -0
  242. package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
  243. package/authoring/doctypes/command/command.doc.mjs +20 -12
  244. package/authoring/doctypes/command/type.ts +14 -0
  245. package/authoring/doctypes/component/component.doc.mjs +30 -27
  246. package/authoring/doctypes/component/type.ts +21 -8
  247. package/authoring/doctypes/enum/enum.doc.mjs +7 -4
  248. package/authoring/doctypes/function/function.doc.mjs +9 -8
  249. package/authoring/doctypes/hook/hook.doc.mjs +5 -4
  250. package/authoring/doctypes/hook/type.ts +4 -0
  251. package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
  252. package/authoring/doctypes/reference/reference.doc.mjs +12 -11
  253. package/authoring/doctypes/schema/schema.doc.mjs +9 -9
  254. package/authoring/doctypes/template/integration-template.doc.d.mts +11 -0
  255. package/authoring/doctypes/template/integration-template.doc.mjs +49 -0
  256. package/authoring/doctypes/template/parse.d.mts +6 -2
  257. package/authoring/doctypes/template/parse.mjs +3 -1
  258. package/authoring/doctypes/template/template.doc.mjs +3 -3
  259. package/authoring/doctypes/template/type.ts +22 -0
  260. package/authoring/doctypes/theme/theme.doc.mjs +2 -2
  261. package/authoring/gap-report/gap-report.doc.mjs +2 -2
  262. package/authoring/identity/identity.doc.mjs +3 -3
  263. package/authoring/index.d.ts +2 -0
  264. package/authoring/integration/integration.doc.mjs +30 -6
  265. package/authoring/integration/parse.test.mjs +21 -0
  266. package/authoring/integration/schema.d.mts +16 -3
  267. package/authoring/integration/schema.mjs +34 -2
  268. package/authoring/integration/type.ts +12 -0
  269. package/clients/cli/bin/astryx.mjs +20 -3
  270. package/clients/cli/cli-command.test.mjs +166 -0
  271. package/clients/cli/commands/blog.doc.mjs +1 -0
  272. package/clients/cli/commands/build-theme.batch-report.test.mjs +17 -3
  273. package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
  274. package/clients/cli/commands/build-theme.mjs +26 -13
  275. package/clients/cli/commands/build-theme.path-safety.test.mjs +224 -6
  276. package/clients/cli/commands/build-theme.registry.test.mjs +5 -2
  277. package/clients/cli/commands/build.doc.mjs +1 -0
  278. package/clients/cli/commands/build.exit-codes-doc.test.mjs +4 -0
  279. package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
  280. package/clients/cli/commands/component.doc.mjs +1 -0
  281. package/clients/cli/commands/discover.broken-integration.test.mjs +11 -7
  282. package/clients/cli/commands/discover.doc.mjs +9 -1
  283. package/clients/cli/commands/discover.mjs +144 -93
  284. package/clients/cli/commands/discover.no-source.test.mjs +448 -33
  285. package/clients/cli/commands/discover.sources.test.mjs +20 -1
  286. package/clients/cli/commands/docs.doc.mjs +1 -0
  287. package/clients/cli/commands/docs.mjs +49 -19
  288. package/clients/cli/commands/docs.test.mjs +2 -2
  289. package/clients/cli/commands/doctor-integration-components.doc.mjs +19 -4
  290. package/clients/cli/commands/doctor-integration-docs.doc.mjs +20 -5
  291. package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -0
  292. package/clients/cli/commands/doctor-integration-validate.doc.mjs +22 -2
  293. package/clients/cli/commands/doctor-integration.test.mjs +888 -3
  294. package/clients/cli/commands/doctor.doc.mjs +12 -2
  295. package/clients/cli/commands/doctor.mjs +292 -7
  296. package/clients/cli/commands/doctor.test.mjs +10 -4
  297. package/clients/cli/commands/gap-report.doc.mjs +15 -2
  298. package/clients/cli/commands/gap-report.mjs +24 -2
  299. package/clients/cli/commands/gap-report.test.mjs +79 -0
  300. package/clients/cli/commands/hook.doc.mjs +1 -0
  301. package/clients/cli/commands/init.behavior.test.mjs +5 -0
  302. package/clients/cli/commands/init.doc.mjs +29 -3
  303. package/clients/cli/commands/integration-add.doc.mjs +7 -0
  304. package/clients/cli/commands/integration-authoring.test.mjs +49 -3
  305. package/clients/cli/commands/integration-check.doc.mjs +93 -0
  306. package/clients/cli/commands/integration-check.test.mjs +441 -0
  307. package/clients/cli/commands/integration-pack.doc.mjs +8 -1
  308. package/clients/cli/commands/integration-verify.doc.mjs +8 -1
  309. package/clients/cli/commands/integration.doc.mjs +6 -2
  310. package/clients/cli/commands/integration.mjs +119 -7
  311. package/clients/cli/commands/json-contract.test.mjs +11 -2
  312. package/clients/cli/commands/manifest.doc.mjs +1 -0
  313. package/clients/cli/commands/outside-project.test.mjs +774 -0
  314. package/clients/cli/commands/search.doc.mjs +1 -0
  315. package/clients/cli/commands/search.mjs +16 -11
  316. package/clients/cli/commands/search.test.mjs +429 -296
  317. package/clients/cli/commands/setup-nudge.test.mjs +102 -2
  318. package/clients/cli/commands/swizzle.doc.mjs +7 -0
  319. package/clients/cli/commands/swizzle.mjs +5 -3
  320. package/clients/cli/commands/swizzle.routing.test.mjs +19 -2
  321. package/clients/cli/commands/template.doc.mjs +1 -0
  322. package/clients/cli/commands/text-json-parity.test.mjs +5 -0
  323. package/clients/cli/commands/theme-add-lifecycle.test.mjs +3 -3
  324. package/clients/cli/commands/theme-add.doc.mjs +8 -1
  325. package/clients/cli/commands/theme-build.doc.mjs +3 -2
  326. package/clients/cli/commands/theme-eject.doc.mjs +1 -0
  327. package/clients/cli/commands/theme-list.behavior.test.mjs +6 -0
  328. package/clients/cli/commands/theme-list.doc.mjs +1 -0
  329. package/clients/cli/commands/theme-palette-generate.doc.mjs +1 -0
  330. package/clients/cli/commands/theme-remove.doc.mjs +7 -0
  331. package/clients/cli/commands/theme-targets.doc.mjs +1 -0
  332. package/clients/cli/commands/theme-template.doc.mjs +1 -0
  333. package/clients/cli/commands/theme-use.doc.mjs +7 -0
  334. package/clients/cli/commands/upgrade.config-ordering.test.mjs +2 -1
  335. package/clients/cli/commands/upgrade.doc.mjs +22 -1
  336. package/clients/cli/commands/upgrade.file-protection.test.mjs +3 -2
  337. package/clients/cli/commands/upgrade.hook-output.test.mjs +2 -1
  338. package/clients/cli/commands/upgrade.older-cli.test.mjs +160 -0
  339. package/clients/cli/index.mjs +112 -16
  340. package/clients/cli/lib/cli-error.mjs +4 -1
  341. package/clients/cli/lib/component-format.test.mjs +1 -1
  342. package/clients/cli/lib/define-command.mjs +2 -2
  343. package/clients/cli/lib/json-shim.mjs +3 -1
  344. package/clients/cli/lib/manifest.d.ts +9 -0
  345. package/clients/cli/lib/manifest.mjs +17 -1
  346. package/clients/cli/lib/manifest.test.mjs +25 -0
  347. package/foundation/agent-docs/agent-doc-state.d.mts +35 -6
  348. package/foundation/agent-docs/agent-doc-state.mjs +66 -6
  349. package/foundation/agent-docs/agent-docs.d.mts +4 -3
  350. package/foundation/agent-docs/agent-docs.mjs +11 -9
  351. package/foundation/agent-docs/computer-agent-text.d.mts +133 -0
  352. package/foundation/agent-docs/computer-agent-text.mjs +623 -0
  353. package/foundation/agent-docs/computer-agent-text.test.mjs +602 -0
  354. package/foundation/config/project.d.mts +35 -3
  355. package/foundation/config/project.mjs +226 -7
  356. package/foundation/config/project.test.mjs +66 -0
  357. package/foundation/config/theme-state.mjs +5 -4
  358. package/foundation/discovery/authoring-self-docs.mjs +2 -1
  359. package/foundation/discovery/cli-self-docs.mjs +20 -3
  360. package/foundation/discovery/cli-self-docs.test.mjs +3 -2
  361. package/foundation/discovery/component-discovery.d.mts +190 -10
  362. package/foundation/discovery/component-discovery.export-names.test.mjs +760 -0
  363. package/foundation/discovery/component-discovery.mjs +864 -56
  364. package/foundation/discovery/component-discovery.test.mjs +96 -0
  365. package/foundation/discovery/component-replacement.mjs +20 -1
  366. package/foundation/discovery/component-replacement.test.mjs +40 -0
  367. package/foundation/discovery/copied-passages.d.mts +216 -0
  368. package/foundation/discovery/copied-passages.mjs +720 -0
  369. package/foundation/discovery/copied-passages.test.mjs +124 -0
  370. package/foundation/discovery/doc-consistency.d.mts +34 -0
  371. package/foundation/discovery/doc-consistency.mjs +513 -0
  372. package/foundation/discovery/doc-consistency.test.mjs +347 -0
  373. package/foundation/discovery/doc-fluff.d.mts +112 -0
  374. package/foundation/discovery/doc-fluff.mjs +328 -0
  375. package/foundation/discovery/doc-fluff.test.mjs +142 -0
  376. package/foundation/discovery/doc-types.d.mts +157 -0
  377. package/foundation/discovery/doc-types.mjs +1231 -0
  378. package/foundation/discovery/doc-types.test.mjs +744 -0
  379. package/foundation/discovery/docs-discovery.d.mts +88 -0
  380. package/foundation/discovery/docs-discovery.mjs +83 -2
  381. package/foundation/discovery/integration-doc-files.d.mts +22 -0
  382. package/foundation/discovery/integration-doc-files.mjs +231 -0
  383. package/foundation/discovery/integration-doc-files.test.mjs +246 -0
  384. package/foundation/discovery/module-exports.d.mts +27 -0
  385. package/foundation/discovery/module-exports.mjs +356 -31
  386. package/foundation/discovery/module-exports.test.mjs +172 -0
  387. package/foundation/discovery/package-tsconfig.d.mts +14 -0
  388. package/foundation/discovery/package-tsconfig.mjs +228 -0
  389. package/foundation/discovery/package-tsconfig.test.mjs +210 -0
  390. package/foundation/discovery/project-typescript.d.mts +32 -0
  391. package/foundation/discovery/project-typescript.mjs +89 -0
  392. package/foundation/discovery/prop-drift.d.mts +297 -0
  393. package/foundation/discovery/prop-drift.mjs +2428 -0
  394. package/foundation/discovery/prop-drift.test.mjs +2337 -0
  395. package/foundation/discovery/runner-allowlist.d.mts +40 -0
  396. package/foundation/discovery/runner-allowlist.mjs +53 -0
  397. package/foundation/discovery/stray-pointers.d.mts +52 -0
  398. package/foundation/discovery/stray-pointers.mjs +293 -0
  399. package/foundation/discovery/stray-pointers.test.mjs +86 -0
  400. package/foundation/discovery/template-adapter.mjs +74 -5
  401. package/foundation/discovery/template-needs.mjs +5 -2
  402. package/foundation/discovery/theme-imports.mjs +8 -4
  403. package/foundation/discovery/theme-imports.test.mjs +1 -1
  404. package/foundation/discovery/type-match.d.mts +53 -0
  405. package/foundation/discovery/type-match.mjs +660 -0
  406. package/foundation/discovery/type-match.test.mjs +169 -0
  407. package/foundation/discovery/type-text.d.mts +68 -0
  408. package/foundation/discovery/type-text.mjs +658 -0
  409. package/foundation/discovery/type-text.test.mjs +196 -0
  410. package/foundation/discovery/unresolved-references.d.mts +62 -0
  411. package/foundation/discovery/unresolved-references.mjs +790 -0
  412. package/foundation/discovery/unresolved-references.test.mjs +567 -0
  413. package/foundation/doc-compiler/doc-loads.test.mjs +51 -1
  414. package/foundation/doc-compiler/inputs.mjs +27 -1
  415. package/foundation/doc-compiler/inputs.test.mjs +0 -1
  416. package/foundation/doc-compiler/links.d.mts +41 -5
  417. package/foundation/doc-compiler/links.mjs +167 -28
  418. package/foundation/doc-compiler/links.test.mjs +97 -4
  419. package/foundation/doc-compiler/read.d.mts +1 -1
  420. package/foundation/doc-compiler/tree.mjs +30 -1
  421. package/foundation/doc-compiler/tree.test.mjs +8 -1
  422. package/foundation/env/cli-command.d.mts +83 -0
  423. package/foundation/env/cli-command.mjs +152 -0
  424. package/foundation/env/cli-command.test.mjs +129 -0
  425. package/foundation/env/node-version.test.mjs +15 -3
  426. package/foundation/env/package-manager.d.mts +93 -9
  427. package/foundation/env/package-manager.global.test.mjs +66 -0
  428. package/foundation/env/package-manager.mjs +184 -13
  429. package/foundation/env/package-manager.test.mjs +341 -15
  430. package/foundation/env/project-scope.d.mts +9 -0
  431. package/foundation/env/project-scope.mjs +33 -0
  432. package/foundation/env/search-path.d.mts +42 -0
  433. package/foundation/env/search-path.mjs +205 -0
  434. package/foundation/env/search-path.test.mjs +122 -0
  435. package/foundation/env/user-dirs.d.mts +39 -0
  436. package/foundation/env/user-dirs.mjs +93 -0
  437. package/foundation/env/user-dirs.test.mjs +72 -0
  438. package/foundation/env/user-settings.d.mts +46 -0
  439. package/foundation/env/user-settings.mjs +106 -0
  440. package/foundation/env/user-settings.test.mjs +64 -0
  441. package/foundation/fs/file-protection.mjs +15 -1
  442. package/foundation/fs/module-loader.d.mts +2 -1
  443. package/foundation/fs/module-loader.mjs +60 -4
  444. package/foundation/fs/module-loader.stdout.test.mjs +3 -2
  445. package/foundation/fs/module-loader.test.mjs +194 -0
  446. package/foundation/fs/path-compare.d.mts +33 -0
  447. package/foundation/fs/path-compare.mjs +73 -0
  448. package/foundation/fs/paths.d.mts +57 -1
  449. package/foundation/fs/paths.mjs +131 -3
  450. package/foundation/fs/paths.test.mjs +10 -1
  451. package/foundation/integrations/computer-integrations.d.mts +78 -0
  452. package/foundation/integrations/computer-integrations.mjs +316 -0
  453. package/foundation/integrations/computer-integrations.test.mjs +292 -0
  454. package/foundation/integrations/contribution-inventory.d.mts +11 -0
  455. package/foundation/integrations/contribution-inventory.mjs +56 -3
  456. package/foundation/integrations/integration-warnings.mjs +3 -2
  457. package/foundation/integrations/integration-warnings.test.mjs +8 -9
  458. package/foundation/integrations/integrations.d.mts +25 -1
  459. package/foundation/integrations/integrations.mjs +46 -3
  460. package/foundation/integrations/issue.ts +6 -0
  461. package/foundation/integrations/validate-contributions.d.mts +2 -0
  462. package/foundation/integrations/validate-contributions.mjs +41 -1
  463. package/foundation/release/agent-text-worker.d.mts +4 -0
  464. package/foundation/release/agent-text-worker.mjs +52 -0
  465. package/foundation/release/cache.d.mts +310 -0
  466. package/foundation/release/cache.mjs +1216 -0
  467. package/foundation/release/cache.test.mjs +920 -0
  468. package/foundation/release/choose.d.mts +207 -0
  469. package/foundation/release/choose.mjs +677 -0
  470. package/foundation/release/choose.test.mjs +427 -0
  471. package/foundation/release/core-worker.d.mts +4 -0
  472. package/foundation/release/core-worker.mjs +38 -0
  473. package/foundation/release/global-state.d.mts +259 -0
  474. package/foundation/release/global-state.mjs +472 -0
  475. package/foundation/release/global-state.test.mjs +381 -0
  476. package/foundation/release/handoff.d.mts +60 -0
  477. package/foundation/release/handoff.e2e.test.mjs +278 -0
  478. package/foundation/release/handoff.mjs +357 -0
  479. package/foundation/release/lock-lease.d.mts +23 -0
  480. package/foundation/release/lock-lease.mjs +80 -0
  481. package/foundation/release/notices.d.mts +253 -0
  482. package/foundation/release/notices.mjs +596 -0
  483. package/foundation/release/notices.test.mjs +565 -0
  484. package/foundation/release/npm-guard.d.mts +4 -0
  485. package/foundation/release/npm-guard.mjs +126 -0
  486. package/foundation/release/project.d.mts +141 -0
  487. package/foundation/release/project.mjs +466 -0
  488. package/foundation/release/project.test.mjs +288 -0
  489. package/foundation/release/refresh-worker.d.mts +4 -0
  490. package/foundation/release/refresh-worker.mjs +27 -0
  491. package/foundation/release/run-context.d.mts +47 -0
  492. package/foundation/release/run-context.mjs +149 -0
  493. package/foundation/release/update-notice-env.d.mts +28 -0
  494. package/foundation/release/update-notice-env.mjs +39 -0
  495. package/foundation/response/base.d.ts +26 -3
  496. package/foundation/response/error-codes.d.mts +3 -1
  497. package/foundation/response/error-codes.doc.mjs +12 -0
  498. package/foundation/response/error-codes.mjs +17 -0
  499. package/foundation/response/error-codes.test.mjs +2 -0
  500. package/foundation/response/json-contract.test.mjs +7 -2
  501. package/foundation/response/json.mjs +4 -1
  502. package/foundation/response/response-types.doc.mjs +22 -11
  503. package/foundation/response/response-types.doc.test.mjs +46 -0
  504. package/foundation/response/response.doc.mjs +3 -3
  505. package/foundation/xle/browser-imports.test.mjs +74 -0
  506. package/foundation/xle/registry.mjs +4 -0
  507. package/foundation/xle/registry.test.mjs +28 -0
  508. package/package.json +11 -11
  509. package/scripts/postinstall.mjs +24 -5
@@ -37,6 +37,8 @@ const componentDoc = name =>
37
37
  `export default {type: 'component', name: '${name}', displayName: '${name}', usage: {description: '${name}.'}, props: []};\n`;
38
38
  /** @param {string} name */
39
39
  const componentSource = name => `export function ${name}() { return null; }\n`;
40
+ const templateSource = name =>
41
+ `export default function ${name}() { return null; }\n`;
40
42
  /** @param {string} name */
41
43
  const topic = name =>
42
44
  `export default ${JSON.stringify({
@@ -1131,6 +1133,71 @@ describe('source_without_component_doc fixes hold when followed', () => {
1131
1133
  });
1132
1134
  });
1133
1135
 
1136
+ describe('source_without_template_doc fixes hold when followed', () => {
1137
+ it('adds the named doc, which resolves the warning', async () => {
1138
+ const dir = writePackage({
1139
+ [MANIFEST]: manifest({templates: './templates'}),
1140
+ 'templates/hero.tsx': templateSource('Hero'),
1141
+ 'templates/hero.test.tsx': templateSource('HeroTest'),
1142
+ });
1143
+
1144
+ const message = only(await issuesOf(dir), 'source_without_template_doc');
1145
+ expect(message).toBe(
1146
+ "Template source \"hero.tsx\" has no same-stem metadata file hero.doc.mjs, so `astryx template` never lists it. Fix: add hero.doc.mjs beside it with type: 'page' or 'block'; `astryx docs authoring integration-template-doc` lists its fields. If it is not a template, move it out of the templates root.",
1147
+ );
1148
+
1149
+ const fixed = follow(dir, {
1150
+ write: {
1151
+ 'templates/hero.doc.mjs': `export default {type: 'page', name: 'hero', displayName: 'Hero'};\n`,
1152
+ },
1153
+ });
1154
+ expect(await issuesOf(fixed)).toEqual([]);
1155
+ });
1156
+
1157
+ it('checks a dotted template id, but no test, spec or story file', async () => {
1158
+ const dir = writePackage({
1159
+ [MANIFEST]: manifest({templates: './templates'}),
1160
+ 'templates/landing.page.tsx': templateSource('LandingPage'),
1161
+ 'templates/hero.test.tsx': templateSource('HeroTest'),
1162
+ 'templates/hero.spec.tsx': templateSource('HeroSpec'),
1163
+ 'templates/hero.stories.tsx': templateSource('HeroStories'),
1164
+ });
1165
+
1166
+ const message = only(await issuesOf(dir), 'source_without_template_doc');
1167
+ expect(message).toContain(
1168
+ 'Template source "landing.page.tsx" has no same-stem metadata file landing.page.doc.mjs',
1169
+ );
1170
+
1171
+ const fixed = follow(dir, {
1172
+ write: {
1173
+ 'templates/landing.page.doc.mjs': `export default {type: 'page', name: 'landing.page', displayName: 'Landing'};\n`,
1174
+ },
1175
+ });
1176
+ expect(await issuesOf(fixed)).toEqual([]);
1177
+ });
1178
+
1179
+ it('never flags a helper in a subfolder of the templates root', async () => {
1180
+ const dir = writePackage({
1181
+ [MANIFEST]: manifest({templates: './templates'}),
1182
+ 'templates/hero.doc.mjs': `export default {type: 'page', name: 'hero', displayName: 'Hero'};\n`,
1183
+ 'templates/hero.tsx': templateSource('Hero'),
1184
+ 'templates/hero/HeroCard.tsx': templateSource('HeroCard'),
1185
+ });
1186
+
1187
+ expect(await issuesOf(dir)).toEqual([]);
1188
+ });
1189
+
1190
+ it('accepts a released .template.mjs spec as the metadata', async () => {
1191
+ const dir = writePackage({
1192
+ [MANIFEST]: manifest({templates: './templates'}),
1193
+ 'templates/hero.tsx': templateSource('Hero'),
1194
+ 'templates/hero.template.mjs': `export default {type: 'page', name: 'hero', displayName: 'Hero'};\n`,
1195
+ });
1196
+
1197
+ expect(await issuesOf(dir)).toEqual([]);
1198
+ });
1199
+ });
1200
+
1134
1201
  describe('codemod fixes hold when followed', () => {
1135
1202
  it('moves a stray codemod into a version folder, and renames a mis-named one', async () => {
1136
1203
  const dir = writePackage({
@@ -67,6 +67,14 @@ export type ValidateResult = {
67
67
  */
68
68
  reason?: "no_package_json" | undefined;
69
69
  issues: Issue[];
70
+ /**
71
+ * Information that
72
+ * fails nothing, such as `invalid_cli_command` (a malformed `cliCommand`).
73
+ */
74
+ notes?: {
75
+ code: string;
76
+ message: string;
77
+ }[] | undefined;
70
78
  integration?: import("../../foundation/integrations/integrations.mjs").LoadedIntegration | undefined;
71
79
  };
72
80
  import { validateLoadedIntegration } from '../../foundation/integrations/validate-contributions.mjs';
@@ -34,6 +34,8 @@
34
34
  import * as fs from 'node:fs';
35
35
  import * as path from 'node:path';
36
36
  import {assertWithin} from '../../foundation/fs/path-safety.mjs';
37
+ import {integrationDocTypes} from '../docs/_adapter.mjs';
38
+ import {integrationDocConsistency} from '../../foundation/discovery/doc-consistency.mjs';
37
39
  import {
38
40
  THEME_SLUG_RE,
39
41
  unreadThemeFolders,
@@ -54,11 +56,13 @@ import {
54
56
  // The on-disk contribution validators live in foundation: Project and
55
57
  // integration-warnings need them too, and foundation must not depend on api.
56
58
  import {
59
+ INVALID_CLI_COMMAND,
57
60
  validateLoadedIntegration,
58
61
  issueError as error,
59
62
  issueWarning as warning,
60
63
  rootProblem,
61
64
  } from '../../foundation/integrations/validate-contributions.mjs';
65
+ import {formatCliCommand} from '../../foundation/env/package-manager.mjs';
62
66
 
63
67
  export {validateLoadedIntegration};
64
68
 
@@ -74,6 +78,8 @@ export {validateLoadedIntegration};
74
78
  * @property {string} [manifestFile] Absolute path to the loaded manifest.
75
79
  * @property {'no_package_json'} [reason] Why nothing was validated (internal).
76
80
  * @property {Issue[]} issues
81
+ * @property {Array<{code: string, message: string}>} [notes] Information that
82
+ * fails nothing, such as `invalid_cli_command` (a malformed `cliCommand`).
77
83
  * @property {import('../../foundation/integrations/integrations.mjs').LoadedIntegration} [integration]
78
84
  */
79
85
 
@@ -123,7 +129,7 @@ function unreadThemeFolderIssues(packageDir, loaded) {
123
129
  let fix;
124
130
  if (THEME_SLUG_RE.test(name)) {
125
131
  const stem = `${name.replace(/-([a-z0-9])/gu, (_, character) => character.toUpperCase())}Theme`;
126
- 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}.`;
132
+ fix = `if it is a theme, add ${stem}.ts and ${stem}.doc.mjs to it (\`${formatCliCommand(`integration add theme ${name}`, packageDir)}\` writes both) and move its code into ${stem}.ts; if not, ${hide}.`;
127
133
  } else {
128
134
  fix = `${hide}; a theme folder needs a lower-kebab name.`;
129
135
  }
@@ -282,11 +288,14 @@ async function validateAtPackageDir(
282
288
  let unknownKeys;
283
289
  /** @type {string | undefined} */
284
290
  let agentDocsError;
291
+ /** @type {string | undefined} */
292
+ let cliCommandError;
285
293
  try {
286
- ({manifest, unknownKeys, agentDocsError} = await loadManifest(
287
- manifestFile,
288
- `Integration manifest (${path.basename(manifestFile)})`,
289
- ));
294
+ ({manifest, unknownKeys, agentDocsError, cliCommandError} =
295
+ await loadManifest(
296
+ manifestFile,
297
+ `Integration manifest (${path.basename(manifestFile)})`,
298
+ ));
290
299
  } catch (err) {
291
300
  issues.push(error('invalid_manifest', /** @type {any} */ (err).message));
292
301
  return result;
@@ -318,6 +327,8 @@ async function validateAtPackageDir(
318
327
  themes: resolveRoot(manifest.themes),
319
328
  issuesUrl: manifest.issuesUrl,
320
329
  agentDocs: manifest.agentDocs,
330
+ cliCommand: manifest.cliCommand,
331
+ __cliCommandError: cliCommandError,
321
332
  __agentDocsError: agentDocsError,
322
333
  __unknownKeys: unknownKeys,
323
334
  __spec: identity.name,
@@ -328,9 +339,35 @@ async function validateAtPackageDir(
328
339
 
329
340
  // Roots + contribution checks are shared with validateLoadedIntegration so
330
341
  // the everyday-command nudge runs the exact same validators.
331
- issues.push(...(await validateLoadedIntegration(loaded)));
342
+ // A malformed `cliCommand` is an info note beside the issues, not an issue:
343
+ // `integration check --strict` fails on any warning, and a new failure code
344
+ // joins only in a minor release (architecture:cli-surface INV35). Doctor's
345
+ // project check still warns about it.
346
+ for (const issue of await validateLoadedIntegration(loaded)) {
347
+ if (issue.code === INVALID_CLI_COMMAND) {
348
+ (result.notes ??= []).push({code: issue.code, message: issue.message});
349
+ } else {
350
+ issues.push(issue);
351
+ }
352
+ }
332
353
  if (loaded.themes && !rootProblem(loaded.themes))
333
354
  issues.push(...unreadThemeFolderIssues(packageDir, loaded));
355
+ // What the docs say that no reader serves: a prop listed twice, an
356
+ // overlay's text for a prop the doc lacks, an empty or unreachable section,
357
+ // and an overlay of no topic.
358
+ issues.push(
359
+ ...(await integrationDocConsistency(
360
+ {
361
+ components:
362
+ loaded.components && !rootProblem(loaded.components)
363
+ ? loaded.components
364
+ : undefined,
365
+ docs:
366
+ loaded.docs && !rootProblem(loaded.docs) ? loaded.docs : undefined,
367
+ },
368
+ packageDir,
369
+ )),
370
+ );
334
371
  if (scanUnreachable) {
335
372
  issues.push(
336
373
  ...(await findUnreachableContributionIssues(packageDir, loaded)),
@@ -461,6 +498,13 @@ export async function validateIntegration(pkg, options = {}) {
461
498
  const result = pkg
462
499
  ? await validateInstalledIntegration(pkg, cwd)
463
500
  : await validateLocalIntegration(cwd);
501
+ // Each doc the package ships, against the published authoring type for its
502
+ // kind, read with the project's own compiler. Findings are warnings only.
503
+ const integration = result.found ? result.integration : undefined;
504
+ const docTypes = integration
505
+ ? await integrationDocTypes(integration, cwd)
506
+ : undefined;
507
+ const notes = result.found ? (result.notes ?? []) : [];
464
508
  return {
465
509
  type: 'integration.validate',
466
510
  data: {
@@ -469,9 +513,19 @@ export async function validateIntegration(pkg, options = {}) {
469
513
  validated: result.found,
470
514
  name: result.found ? (result.name ?? null) : null,
471
515
  version: result.found ? (result.version ?? null) : null,
472
- issues: result.reason === 'no_package_json'
473
- ? [{code: 'no_package', severity: 'error', message: 'No package.json found. Run this command inside a package directory.'}]
474
- : result.issues,
516
+ issues:
517
+ result.reason === 'no_package_json'
518
+ ? [
519
+ {
520
+ code: 'no_package',
521
+ severity: 'error',
522
+ message:
523
+ 'No package.json found. Run this command inside a package directory.',
524
+ },
525
+ ]
526
+ : result.issues,
527
+ ...(notes.length > 0 ? {notes} : {}),
528
+ ...(docTypes ? {docTypes} : {}),
475
529
  },
476
530
  };
477
531
  }
@@ -80,6 +80,28 @@ describe('validate-integration API', () => {
80
80
  expect(errors).toBe(0);
81
81
  });
82
82
 
83
+ it('warns, with a fix and the file, on docs no reader can serve', async () => {
84
+ const pkgDir = path.join(tmpDir, 'pkg');
85
+ writePackage(pkgDir, {
86
+ manifest: `export default { docs: './docs' };\n`,
87
+ });
88
+ fs.mkdirSync(path.join(pkgDir, 'docs'), {recursive: true});
89
+ fs.writeFileSync(
90
+ path.join(pkgDir, 'docs', 'ghost.doc.zh.mjs'),
91
+ "export default {title: 'ghost'};\n",
92
+ );
93
+
94
+ const result = await validateLocalIntegration(pkgDir);
95
+
96
+ expect(byCode(result.issues, 'orphan_doc_overlay')).toEqual([
97
+ expect.objectContaining({
98
+ severity: 'warning',
99
+ file: 'docs/ghost.doc.zh.mjs',
100
+ fix: expect.stringContaining('Delete docs/ghost.doc.zh.mjs'),
101
+ }),
102
+ ]);
103
+ });
104
+
83
105
  it('reports an unknown manifest key as a warning, and still loads the rest', async () => {
84
106
  // The manifest used to be parsed with a strict schema, so a single unknown
85
107
  // key failed the parse — and an integration whose manifest fails to parse
@@ -176,6 +198,17 @@ describe('validate-integration API', () => {
176
198
  expect(agentDocsIssues[0].severity).toBe('error');
177
199
  });
178
200
 
201
+ it('reports nothing for a docsiteUrl', async () => {
202
+ const pkgDir = path.join(tmpDir, 'pkg');
203
+ writePackage(pkgDir, {
204
+ manifest: `export default {docsiteUrl: 'https://widgets.example.com'};\n`,
205
+ });
206
+
207
+ const result = await validateLocalIntegration(pkgDir);
208
+
209
+ expect(result.issues).toEqual([]);
210
+ });
211
+
179
212
  it('flags a broken codemod as invalid_codemod error', async () => {
180
213
  const pkgDir = path.join(tmpDir, 'pkg');
181
214
  writePackage(pkgDir, {
@@ -310,6 +343,36 @@ export default {type: 'theme', name: 'ocean', displayName: 'Ocean', description:
310
343
  );
311
344
  });
312
345
 
346
+ it('warns when a template source has no same-stem metadata, skipping test files', async () => {
347
+ const pkgDir = path.join(tmpDir, 'pkg');
348
+ writePackage(pkgDir, {
349
+ manifest: `export default { templates: './templates' };\n`,
350
+ });
351
+ fs.mkdirSync(path.join(pkgDir, 'templates'));
352
+ fs.writeFileSync(
353
+ path.join(pkgDir, 'templates', 'stray.tsx'),
354
+ 'export default function Stray() { return null; }\n',
355
+ );
356
+ fs.writeFileSync(
357
+ path.join(pkgDir, 'templates', 'stray.test.tsx'),
358
+ "import {it} from 'vitest';\nit('renders', () => {});\n",
359
+ );
360
+
361
+ const result = await validateLocalIntegration(pkgDir);
362
+
363
+ const warnings = byCode(result.issues, 'source_without_template_doc');
364
+ expect(warnings).toEqual([
365
+ expect.objectContaining({
366
+ severity: 'warning',
367
+ message: expect.stringContaining('"stray.tsx"'),
368
+ }),
369
+ ]);
370
+ expect(warnings[0].message).not.toContain('stray.test.tsx');
371
+ expect(warnings[0].message).toContain(
372
+ "Fix: add stray.doc.mjs beside it with type: 'page' or 'block'",
373
+ );
374
+ });
375
+
313
376
  it('reports codemods outside semver folders and invalid folder names', async () => {
314
377
  const pkgDir = path.join(tmpDir, 'pkg');
315
378
  writePackage(pkgDir, {
@@ -582,7 +645,10 @@ describe('integration diagnostics are read-only', () => {
582
645
  'components/Orphan.doc.mjs',
583
646
  "export default {type: 'component', name: 'Orphan', props: []};\n",
584
647
  );
585
- write('templates/dash.doc.mjs', "export default {type: 'page', name: 'Dash'};\n");
648
+ write(
649
+ 'templates/dash.doc.mjs',
650
+ "export default {type: 'page', name: 'Dash'};\n",
651
+ );
586
652
  write(
587
653
  'docs/theme.doc.mjs',
588
654
  "export default {type: 'generic', name: 'theme', title: 'Theme', description: 'x', sections: [{title: 'A', content: [{type: 'prose', text: 'x'}]}]};\n",
@@ -603,7 +669,9 @@ describe('integration diagnostics are read-only', () => {
603
669
  path.join(consumer, 'package.json'),
604
670
  JSON.stringify({name: 'consumer'}),
605
671
  );
606
- writeDiagnosedPackage(path.join(consumer, 'node_modules', '@acme', 'widgets'));
672
+ writeDiagnosedPackage(
673
+ path.join(consumer, 'node_modules', '@acme', 'widgets'),
674
+ );
607
675
  const before = {pkg: snapshot(pkgDir), consumer: snapshot(consumer)};
608
676
 
609
677
  const local = await validateIntegration(undefined, {cwd: pkgDir});
@@ -620,9 +688,13 @@ describe('integration diagnostics are read-only', () => {
620
688
  }
621
689
 
622
690
  expect(summarizeIssues(local.data.issues).errors).toBeGreaterThan(0);
623
- expect(byCode(local.data.issues, 'unreachable_contribution')).toHaveLength(1);
691
+ expect(byCode(local.data.issues, 'unreachable_contribution')).toHaveLength(
692
+ 1,
693
+ );
624
694
  expect(summarizeIssues(installed.data.issues).errors).toBeGreaterThan(0);
625
- expect({pkg: snapshot(pkgDir), consumer: snapshot(consumer)}).toEqual(before);
695
+ expect({pkg: snapshot(pkgDir), consumer: snapshot(consumer)}).toEqual(
696
+ before,
697
+ );
626
698
  });
627
699
  });
628
700
 
@@ -644,7 +716,9 @@ describe('validated separates "checked and clean" from "never checked"', () => {
644
716
  expect(validate.data.issues).toEqual([]);
645
717
 
646
718
  const templates = await integrationTemplateConflicts(undefined, {cwd: dir});
647
- const components = await integrationComponentConflicts(undefined, {cwd: dir});
719
+ const components = await integrationComponentConflicts(undefined, {
720
+ cwd: dir,
721
+ });
648
722
  const docs = await integrationDocConflicts(undefined, {cwd: dir});
649
723
  expect(templates.data.validated).toBe(false);
650
724
  expect(components.data.validated).toBe(false);
@@ -660,7 +734,9 @@ describe('validated separates "checked and clean" from "never checked"', () => {
660
734
  expect(validate.data.name).toBe('@acme/widgets');
661
735
 
662
736
  const templates = await integrationTemplateConflicts(undefined, {cwd: dir});
663
- const components = await integrationComponentConflicts(undefined, {cwd: dir});
737
+ const components = await integrationComponentConflicts(undefined, {
738
+ cwd: dir,
739
+ });
664
740
  const docs = await integrationDocConflicts(undefined, {cwd: dir});
665
741
  expect(templates.data.validated).toBe(true);
666
742
  expect(components.data.validated).toBe(true);
@@ -732,8 +808,12 @@ describe('unreadable folders are reported, never fatal', () => {
732
808
  expect(
733
809
  byCode(result.issues, 'unreadable_root').map(issue => issue.message),
734
810
  ).toEqual([
735
- expect.stringMatching(/^Declared codemods root cannot be read \(EACCES\)/),
736
- expect.stringMatching(/^Declared themes root cannot be read \(EACCES\)/),
811
+ expect.stringMatching(
812
+ /^Declared codemods root cannot be read \(EACCES\)/,
813
+ ),
814
+ expect.stringMatching(
815
+ /^Declared themes root cannot be read \(EACCES\)/,
816
+ ),
737
817
  ]);
738
818
  },
739
819
  );
@@ -34,10 +34,26 @@ export type ValidateIntegrationOptions = {
34
34
  */
35
35
  export type ValidateIntegrationResponse = {
36
36
  type: "integration.validate";
37
+ /**
38
+ * `notes`: information beside the issues that fails nothing, such as
39
+ * `invalid_cli_command`, a `cliCommand` that was ignored as malformed
40
+ */
37
41
  data: {
38
42
  validated: boolean;
39
43
  name: string | null;
40
44
  version: string | null;
41
45
  issues: import("../../foundation/integrations/issue").AstryxIntegrationIssue[];
46
+ notes?: Array<{
47
+ code: string;
48
+ message: string;
49
+ }>;
50
+ docTypes?: DocTypesReport;
42
51
  };
43
52
  };
53
+ /**
54
+ * `fixtures`: how many test fixture docs (under `__tests__` in the
55
+ * components or docs root, which those readers skip) were not checked
56
+ */
57
+ export type DocTypesReport = import("../../foundation/discovery/doc-types.mjs").DocTypesReport & {
58
+ fixtures?: number;
59
+ };
@@ -38,7 +38,20 @@
38
38
  * "healthy" — the two are otherwise byte-identical.
39
39
  * @typedef {object} ValidateIntegrationResponse
40
40
  * @property {'integration.validate'} type
41
- * @property {{validated: boolean, name: string | null, version: string | null, issues: import('../../foundation/integrations/issue').AstryxIntegrationIssue[]}} data
41
+ * @property {{validated: boolean, name: string | null, version: string | null, issues: import('../../foundation/integrations/issue').AstryxIntegrationIssue[], notes?: Array<{code: string, message: string}>, docTypes?: DocTypesReport}} data
42
+ * `notes`: information beside the issues that fails nothing, such as
43
+ * `invalid_cli_command`, a `cliCommand` that was ignored as malformed
44
+ */
45
+
46
+ /**
47
+ * Each doc the package ships, checked against the published authoring type
48
+ * for its kind. Present when the manifest loads. `status: 'skipped'`
49
+ * means nothing was checked (no TypeScript in the project) and `reason` says
50
+ * why. Every finding is a warning.
51
+ *
52
+ * @typedef {import('../../foundation/discovery/doc-types.mjs').DocTypesReport & {fixtures?: number}} DocTypesReport
53
+ * `fixtures`: how many test fixture docs (under `__tests__` in the
54
+ * components or docs root, which those readers skip) were not checked
42
55
  */
43
56
 
44
57
  export {};
@@ -15,6 +15,7 @@ import * as fs from 'node:fs';
15
15
  import * as path from 'node:path';
16
16
  import {validateLocalIntegration} from './validate-integration.mjs';
17
17
  import {integrationAddTheme} from './add-theme.mjs';
18
+ import {formatCliCommand} from '../../foundation/env/package-manager.mjs';
18
19
 
19
20
  let tmpDir;
20
21
 
@@ -76,8 +77,8 @@ describe('unread theme folders', () => {
76
77
  ]);
77
78
  expect(issues.map(issue => issue.message)).toEqual([
78
79
  '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.',
80
+ `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 (\`${formatCliCommand('integration add theme reef', tmpDir)}\` writes both) and move its code into reefTheme.ts; if not, rename it to .reef so Astryx skips it.`,
81
+ `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 (\`${formatCliCommand('integration add theme sand', tmpDir)}\` writes both) and move its code into sandTheme.ts; if not, rename it to .sand so Astryx skips it.`,
81
82
  ]);
82
83
  });
83
84
 
@@ -23,11 +23,27 @@ export const doc = {
23
23
  'declared contribution root exists, and runs the codemod/template/component/' +
24
24
  'docs/theme validators, returning every finding as an AstryxIntegrationIssue. A missing ' +
25
25
  'local manifest is guidance (name null, no issues), not an error, so callers ' +
26
- 'can stay exit-0 in a non-integration directory.',
26
+ 'can stay exit-0 in a non-integration directory. It also checks every doc the ' +
27
+ 'package ships under its roots (component, template, docs topic, theme, and translation, served or not) against ' +
28
+ "the published authoring type for its kind, as `tsc` would, with the project's " +
29
+ 'own `typescript` (or, where `typescript` is missing or has no JavaScript compiler ' +
30
+ 'API, as TypeScript 7 does, the `@typescript/typescript6` it installs): an unknown ' +
31
+ 'field, a missing required field, or a value outside ' +
32
+ "a field's type is a warning in `docTypes` naming the field and a fix. A test " +
33
+ 'fixture under `__tests__` in the components or docs root is counted, not checked. ' +
34
+ 'Without TypeScript, `docTypes` is `skipped` with a reason.',
27
35
  importPath: '@astryxdesign/cli/api',
28
36
  signature:
29
37
  'validateIntegration(pkg?: string, options?: ValidateIntegrationOptions): Promise<ValidateIntegrationResponse>',
30
- keywords: ['integration', 'validate', 'manifest', 'lint', 'check'],
38
+ keywords: [
39
+ 'integration',
40
+ 'validate',
41
+ 'manifest',
42
+ 'lint',
43
+ 'check',
44
+ 'types',
45
+ 'typecheck',
46
+ ],
31
47
  params: [
32
48
  {
33
49
  name: 'pkg',
@@ -46,7 +62,7 @@ export const doc = {
46
62
  {
47
63
  type: 'integration.validate',
48
64
  description:
49
- 'The result envelope: `data.validated`, false when nothing was validated — with no `package.json` at all, `data.issues` carries one `no_package` error-severity issue so the command exits 1; with a `package.json` but no integration manifest, `data.issues` is empty, which means "not looked at", not "healthy"; `data.name` and `data.version` of the validated package (both null when `data.validated` is false; `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}.',
65
+ 'The result envelope: `data.validated`, false when nothing was validated — with no `package.json` at all, `data.issues` carries one `no_package` error-severity issue so the command exits 1; with a `package.json` but no integration manifest, `data.issues` is empty, which means "not looked at", not "healthy"; `data.name` and `data.version` of the validated package (both null when `data.validated` is false; `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, fix?, file?, line?}: `fix` is the change that resolves the issue, and `file` and `line` where it is, relative to the package, when the check knows them; and `data.notes` when there are any: {code, message} information that fails nothing, such as `invalid_cli_command` for a `cliCommand` that was ignored as malformed. When the manifest loads, `data.docTypes` holds the doc type check: `status` (`checked` | `skipped`), `reason` when skipped, `typescript`, `docs` (doc values checked), `findings` ({doc, line, export, type, field, problem: `unknown_field` | `missing_field` | `wrong_type`, severity: `warning`, message, fix}), `unchecked` ({doc, reason}: a doc that could not be fully checked, or a root its reader cannot read), and `fixtures` when the components or docs root holds test fixture docs under `__tests__`: how many, none of them checked.',
50
66
  },
51
67
  ],
52
68
  examples: [
@@ -0,0 +1,11 @@
1
+ // @generated by scripts/sync-api-types.mjs from the JSDoc in api/**/*.mjs.
2
+ // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
+
4
+ /**
5
+ * The Core a typed search reads: the project's, else the release's own,
6
+ * installed into the per-user cache first when needed. Throws as
7
+ * requireCoreDir does.
8
+ * @param {string} cwd
9
+ * @returns {string}
10
+ */
11
+ export function requireSearchCoreDir(cwd: string): string;
@@ -0,0 +1,25 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Environment adapter for search: locating the Core a search reads,
5
+ * including the network install and npm subprocess that fetch a release's
6
+ * own Core outside a project (spec AST-081 FR3; architecture:cli-surface
7
+ * INV21).
8
+ *
9
+ * @input the folder a search runs in
10
+ * @output the Core folder a search reads
11
+ * @position packages/cli/api/search — imported by search.mjs only
12
+ */
13
+
14
+ import {requireCoreDir} from '../../foundation/fs/paths.mjs';
15
+
16
+ /**
17
+ * The Core a typed search reads: the project's, else the release's own,
18
+ * installed into the per-user cache first when needed. Throws as
19
+ * requireCoreDir does.
20
+ * @param {string} cwd
21
+ * @returns {string}
22
+ */
23
+ export function requireSearchCoreDir(cwd) {
24
+ return requireCoreDir(cwd);
25
+ }