@astryxdesign/cli 0.7.2-canary.fdd384f → 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 (450) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/README.md +169 -149
  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/kit/kit.mjs +3 -11
  7. package/api/component/_adapter.d.mts +31 -0
  8. package/api/component/_adapter.mjs +119 -11
  9. package/api/component/component.doc.mjs +6 -1
  10. package/api/component/component.mjs +60 -10
  11. package/api/component/doc-links.test.mjs +386 -0
  12. package/api/discover/_adapter.d.mts +132 -12
  13. package/api/discover/_adapter.mjs +488 -27
  14. package/api/discover/_adapter.test.mjs +599 -17
  15. package/api/discover/_catalog-view.d.mts +16 -5
  16. package/api/discover/_catalog-view.mjs +32 -8
  17. package/api/discover/detail/doc/doc.mjs +9 -1
  18. package/api/discover/discover.d.mts +11 -0
  19. package/api/discover/discover.doc.mjs +9 -7
  20. package/api/discover/discover.mjs +121 -19
  21. package/api/discover/discover.type.d.mts +20 -7
  22. package/api/discover/discover.type.mjs +17 -7
  23. package/api/discover/list/list.d.mts +4 -3
  24. package/api/discover/list/list.mjs +17 -10
  25. package/api/docs/_adapter.d.mts +63 -0
  26. package/api/docs/_adapter.mjs +312 -18
  27. package/api/docs/docs.doc.mjs +2 -1
  28. package/api/docs/docs.mjs +2 -1
  29. package/api/docs/docs.test.mjs +5 -2
  30. package/api/docs/integration-tree.test.mjs +22 -0
  31. package/api/docs/list/list.mjs +12 -2
  32. package/api/docs/reference-blocks.test.mjs +1 -3
  33. package/api/doctor/_adapter.d.mts +108 -0
  34. package/api/doctor/_adapter.mjs +223 -4
  35. package/api/doctor/doctor.d.mts +199 -0
  36. package/api/doctor/doctor.doc.mjs +3 -2
  37. package/api/doctor/doctor.mjs +530 -34
  38. package/api/doctor/doctor.test.mjs +180 -14
  39. package/api/doctor/release-checks.test.mjs +156 -0
  40. package/api/doctor/theme-checks.mjs +16 -3
  41. package/api/doctor/theme-checks.test.mjs +223 -7
  42. package/api/error.d.mts +10 -0
  43. package/api/error.mjs +25 -0
  44. package/api/gap-report/gap-report.d.mts +3 -0
  45. package/api/gap-report/gap-report.doc.mjs +11 -3
  46. package/api/gap-report/gap-report.mjs +152 -48
  47. package/api/gap-report/gap-report.test.mjs +233 -0
  48. package/api/gap-report/gap-report.type.d.mts +41 -0
  49. package/api/gap-report/gap-report.type.mjs +18 -0
  50. package/api/hook/_adapter.mjs +3 -11
  51. package/api/hook/hook.doc.mjs +4 -0
  52. package/api/hook/list/list.d.mts +1 -1
  53. package/api/init/_adapter.d.mts +22 -0
  54. package/api/init/_adapter.mjs +59 -0
  55. package/api/init/init.d.mts +7 -5
  56. package/api/init/init.doc.mjs +28 -7
  57. package/api/init/init.mjs +28 -4
  58. package/api/init/init.type.d.mts +48 -3
  59. package/api/init/init.type.mjs +37 -3
  60. package/api/init/run/run.d.mts +1 -1
  61. package/api/init/run/run.mjs +15 -4
  62. package/api/init/user/user.d.mts +14 -0
  63. package/api/init/user/user.mjs +87 -0
  64. package/api/init/user/user.test.mjs +232 -0
  65. package/api/integration/_adapter.d.mts +33 -0
  66. package/api/integration/_adapter.mjs +58 -0
  67. package/api/integration/authoring-checks.mjs +100 -5
  68. package/api/integration/authoring-checks.test.mjs +769 -0
  69. package/api/integration/authoring-checks.type.d.mts +134 -0
  70. package/api/integration/authoring-checks.type.mjs +60 -1
  71. package/api/integration/integrationCheck.doc.mjs +1 -1
  72. package/api/integration/integrationComponentConflicts.doc.mjs +11 -3
  73. package/api/integration/integrationDocConflicts.doc.mjs +22 -5
  74. package/api/integration/pack-check.mjs +303 -13
  75. package/api/integration/pack-check.test.mjs +371 -10
  76. package/api/integration/validate-integration-fixes.test.mjs +67 -0
  77. package/api/integration/validate-integration.d.mts +8 -0
  78. package/api/integration/validate-integration.mjs +55 -9
  79. package/api/integration/validate-integration.test.mjs +77 -8
  80. package/api/integration/validate-integration.type.d.mts +8 -0
  81. package/api/integration/validate-integration.type.mjs +3 -1
  82. package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
  83. package/api/integration/validateIntegration.doc.mjs +4 -2
  84. package/api/search/_adapter.d.mts +11 -0
  85. package/api/search/_adapter.mjs +25 -0
  86. package/api/search/search.d.mts +73 -13
  87. package/api/search/search.doc.mjs +8 -3
  88. package/api/search/search.domain-priority.test.mjs +108 -18
  89. package/api/search/search.mjs +541 -52
  90. package/api/search/search.test.mjs +143 -1
  91. package/api/search/search.type.d.mts +14 -1
  92. package/api/search/search.type.mjs +6 -1
  93. package/api/swizzle/_adapter.mjs +2 -2
  94. package/api/swizzle/copy/copy.mjs +1 -1
  95. package/api/template/template-integration.test.mjs +1 -1
  96. package/api/theme/_adapter.d.mts +16 -0
  97. package/api/theme/_adapter.mjs +32 -5
  98. package/api/theme/build/build.d.mts +2 -1
  99. package/api/theme/build/build.mjs +70 -14
  100. package/api/theme/build/build.packed-old-core.test.mjs +20 -3
  101. package/api/theme/build/font-warning.mjs +5 -3
  102. package/api/theme/build/font-warning.test.mjs +2 -1
  103. package/api/theme/remove/remove.test.mjs +2 -2
  104. package/api/theme/targets/targets.mjs +3 -10
  105. package/api/theme/themeTargets.doc.mjs +4 -0
  106. package/api/theme/use/use.test.mjs +1 -1
  107. package/api/upgrade/_adapter.d.mts +40 -2
  108. package/api/upgrade/_adapter.mjs +118 -5
  109. package/api/upgrade/run/cli-behind-core.test.mjs +438 -0
  110. package/api/upgrade/run/run.mjs +35 -2
  111. package/api/upgrade/status/status.d.mts +21 -5
  112. package/api/upgrade/status/status.mjs +45 -8
  113. package/api/upgrade/upgrade.doc.mjs +6 -3
  114. package/api/upgrade/upgrade.mjs +5 -1
  115. package/api/upgrade/upgrade.type.d.mts +23 -0
  116. package/api/upgrade/upgrade.type.mjs +16 -1
  117. package/assets/codemods/__tests__/registry.test.mjs +1 -0
  118. package/assets/codemods/registry.mjs +1 -0
  119. package/assets/codemods/runner.mjs +7 -1
  120. package/assets/codemods/transforms/next/index.mjs +1 -11
  121. package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
  122. package/assets/discover/official-packages.json +367 -0
  123. package/assets/docs/author-a-theme.doc.mjs +2 -2
  124. package/assets/docs/browser-support.doc.mjs +1 -1
  125. package/assets/docs/getting-started.doc.mjs +23 -3
  126. package/assets/docs/styling-overview.doc.mjs +1 -1
  127. package/assets/docs/theme.doc.mjs +1 -1
  128. package/assets/docs/tree/add-a-component.doc.mjs +12 -2
  129. package/assets/docs/tree/add-a-theme.doc.mjs +13 -3
  130. package/assets/docs/tree/add-a-topic.doc.mjs +54 -9
  131. package/assets/docs/tree/agent-guidance.doc.mjs +19 -5
  132. package/assets/docs/tree/block-template.doc.mjs +6 -18
  133. package/assets/docs/tree/build-the-template.doc.mjs +1 -1
  134. package/assets/docs/tree/building-blocks.doc.mjs +4 -0
  135. package/assets/docs/tree/check-the-props.doc.mjs +8 -3
  136. package/assets/docs/tree/check-your-docs.doc.mjs +30 -13
  137. package/assets/docs/tree/checks.doc.mjs +17 -17
  138. package/assets/docs/tree/ci-and-containers.doc.mjs +88 -0
  139. package/assets/docs/tree/cli-command.doc.mjs +142 -0
  140. package/assets/docs/tree/cli.doc.mjs +6 -0
  141. package/assets/docs/tree/codemods.doc.mjs +17 -7
  142. package/assets/docs/tree/commands.doc.mjs +7 -1
  143. package/assets/docs/tree/component-family.doc.mjs +3 -5
  144. package/assets/docs/tree/component-imports.doc.mjs +13 -3
  145. package/assets/docs/tree/components.doc.mjs +7 -1
  146. package/assets/docs/tree/computer-agent-guide.doc.mjs +160 -0
  147. package/assets/docs/tree/computer-integrations.doc.mjs +93 -0
  148. package/assets/docs/tree/configuration.doc.mjs +7 -3
  149. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +41 -22
  150. package/assets/docs/tree/define-the-theme.doc.mjs +6 -5
  151. package/assets/docs/tree/describe-the-component.doc.mjs +2 -2
  152. package/assets/docs/tree/docs.doc.mjs +9 -3
  153. package/assets/docs/tree/document-the-template.doc.mjs +1 -1
  154. package/assets/docs/tree/document-the-theme.doc.mjs +3 -3
  155. package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
  156. package/assets/docs/tree/extend-or-replace.doc.mjs +19 -9
  157. package/assets/docs/tree/fonts-and-assets.doc.mjs +2 -2
  158. package/assets/docs/tree/generate-a-palette.doc.mjs +7 -5
  159. package/assets/docs/tree/global-integrations.doc.mjs +124 -0
  160. package/assets/docs/tree/global.doc.mjs +131 -0
  161. package/assets/docs/tree/grade-template-with-agent.doc.mjs +5 -5
  162. package/assets/docs/tree/install-once.doc.mjs +105 -0
  163. package/assets/docs/tree/integrations.doc.mjs +13 -1
  164. package/assets/docs/tree/layout-spacing.doc.mjs +2 -3
  165. package/assets/docs/tree/layout.doc.mjs +6 -6
  166. package/assets/docs/tree/links.doc.mjs +6 -5
  167. package/assets/docs/tree/migration-setup.doc.mjs +3 -2
  168. package/assets/docs/tree/migration-verification.doc.mjs +0 -1
  169. package/assets/docs/tree/migration.doc.mjs +0 -1
  170. package/assets/docs/tree/monorepos.doc.mjs +84 -0
  171. package/assets/docs/tree/package-and-test.doc.mjs +1 -1
  172. package/assets/docs/tree/page-template.doc.mjs +3 -7
  173. package/assets/docs/tree/problems.doc.mjs +205 -0
  174. package/assets/docs/tree/project-global-or-both.doc.mjs +131 -0
  175. package/assets/docs/tree/publishing.doc.mjs +6 -6
  176. package/assets/docs/tree/quick-start.doc.mjs +52 -26
  177. package/assets/docs/tree/reference.doc.mjs +192 -0
  178. package/assets/docs/tree/replace-a-core-component.doc.mjs +15 -7
  179. package/assets/docs/tree/replace-a-core-template.doc.mjs +9 -11
  180. package/assets/docs/tree/scaffold.doc.mjs +1 -1
  181. package/assets/docs/tree/sections-and-placement.doc.mjs +9 -11
  182. package/assets/docs/tree/see-it-in-an-app.doc.mjs +17 -5
  183. package/assets/docs/tree/short-and-findable.doc.mjs +9 -8
  184. package/assets/docs/tree/single-component.doc.mjs +14 -6
  185. package/assets/docs/tree/start-a-template.doc.mjs +18 -8
  186. package/assets/docs/tree/subcomponent.doc.mjs +6 -6
  187. package/assets/docs/tree/template-assets.doc.mjs +2 -2
  188. package/assets/docs/tree/template-doc-overview.doc.mjs +6 -17
  189. package/assets/docs/tree/template-fonts.doc.mjs +1 -1
  190. package/assets/docs/tree/template-icons.doc.mjs +1 -1
  191. package/assets/docs/tree/template-images-media.doc.mjs +1 -1
  192. package/assets/docs/tree/template-styles.doc.mjs +2 -2
  193. package/assets/docs/tree/templates.doc.mjs +7 -1
  194. package/assets/docs/tree/test-in-an-app.doc.mjs +7 -7
  195. package/assets/docs/tree/test-template-in-app.doc.mjs +5 -5
  196. package/assets/docs/tree/themes.doc.mjs +4 -0
  197. package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
  198. package/assets/docs/tree/troubleshooting.doc.mjs +22 -14
  199. package/assets/docs/tree/uninstall.doc.mjs +109 -0
  200. package/assets/docs/tree/updates.doc.mjs +92 -0
  201. package/assets/docs/tree/upgrading.doc.mjs +6 -6
  202. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +14 -2
  203. package/assets/docs/tree/verify-packed-template.doc.mjs +3 -3
  204. package/assets/docs/tree/versioning.doc.mjs +9 -9
  205. package/assets/docs/tree/who-answers.doc.mjs +119 -0
  206. package/assets/docs/tree/write-the-template-file.doc.mjs +5 -5
  207. package/assets/docs/working-with-ai.doc.mjs +23 -9
  208. package/authoring/codemod/codemod.doc.mjs +7 -3
  209. package/authoring/config/config.doc.mjs +9 -6
  210. package/authoring/config/type.ts +4 -2
  211. package/authoring/debug/parse.d.mts +5 -5
  212. package/authoring/discover/discover.doc.mjs +7 -1
  213. package/authoring/doctypes/_schema.d.mts +8 -3
  214. package/authoring/doctypes/_schema.mjs +1 -0
  215. package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
  216. package/authoring/doctypes/command/command.doc.mjs +20 -12
  217. package/authoring/doctypes/command/type.ts +14 -0
  218. package/authoring/doctypes/component/component.doc.mjs +29 -26
  219. package/authoring/doctypes/component/type.ts +15 -5
  220. package/authoring/doctypes/enum/enum.doc.mjs +7 -4
  221. package/authoring/doctypes/function/function.doc.mjs +9 -8
  222. package/authoring/doctypes/hook/hook.doc.mjs +5 -4
  223. package/authoring/doctypes/hook/type.ts +4 -0
  224. package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
  225. package/authoring/doctypes/reference/reference.doc.mjs +12 -11
  226. package/authoring/doctypes/schema/schema.doc.mjs +9 -9
  227. package/authoring/doctypes/template/template.doc.mjs +2 -2
  228. package/authoring/doctypes/theme/theme.doc.mjs +2 -2
  229. package/authoring/gap-report/gap-report.doc.mjs +2 -2
  230. package/authoring/identity/identity.doc.mjs +3 -3
  231. package/authoring/index.d.ts +1 -0
  232. package/authoring/integration/integration.doc.mjs +22 -5
  233. package/authoring/integration/parse.test.mjs +11 -0
  234. package/authoring/integration/schema.d.mts +14 -3
  235. package/authoring/integration/schema.mjs +33 -2
  236. package/authoring/integration/type.ts +8 -0
  237. package/clients/cli/bin/astryx.mjs +20 -3
  238. package/clients/cli/cli-command.test.mjs +166 -0
  239. package/clients/cli/commands/blog.doc.mjs +1 -0
  240. package/clients/cli/commands/build-theme.batch-report.test.mjs +14 -2
  241. package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
  242. package/clients/cli/commands/build-theme.mjs +25 -12
  243. package/clients/cli/commands/build.doc.mjs +1 -0
  244. package/clients/cli/commands/build.exit-codes-doc.test.mjs +4 -0
  245. package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
  246. package/clients/cli/commands/component.doc.mjs +1 -0
  247. package/clients/cli/commands/discover.broken-integration.test.mjs +11 -7
  248. package/clients/cli/commands/discover.doc.mjs +9 -1
  249. package/clients/cli/commands/discover.mjs +144 -93
  250. package/clients/cli/commands/discover.no-source.test.mjs +448 -33
  251. package/clients/cli/commands/discover.sources.test.mjs +20 -1
  252. package/clients/cli/commands/docs.doc.mjs +1 -0
  253. package/clients/cli/commands/docs.mjs +49 -19
  254. package/clients/cli/commands/docs.test.mjs +2 -2
  255. package/clients/cli/commands/doctor-integration-components.doc.mjs +7 -3
  256. package/clients/cli/commands/doctor-integration-docs.doc.mjs +20 -5
  257. package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -0
  258. package/clients/cli/commands/doctor-integration-validate.doc.mjs +13 -2
  259. package/clients/cli/commands/doctor-integration.test.mjs +52 -4
  260. package/clients/cli/commands/doctor.doc.mjs +12 -2
  261. package/clients/cli/commands/doctor.mjs +102 -7
  262. package/clients/cli/commands/doctor.test.mjs +10 -4
  263. package/clients/cli/commands/gap-report.doc.mjs +15 -2
  264. package/clients/cli/commands/gap-report.mjs +24 -2
  265. package/clients/cli/commands/gap-report.test.mjs +79 -0
  266. package/clients/cli/commands/hook.doc.mjs +1 -0
  267. package/clients/cli/commands/init.behavior.test.mjs +5 -0
  268. package/clients/cli/commands/init.doc.mjs +29 -3
  269. package/clients/cli/commands/integration-add.doc.mjs +7 -0
  270. package/clients/cli/commands/integration-authoring.test.mjs +49 -3
  271. package/clients/cli/commands/integration-check.doc.mjs +10 -2
  272. package/clients/cli/commands/integration-check.test.mjs +175 -1
  273. package/clients/cli/commands/integration-pack.doc.mjs +8 -1
  274. package/clients/cli/commands/integration-verify.doc.mjs +8 -1
  275. package/clients/cli/commands/integration.mjs +15 -9
  276. package/clients/cli/commands/json-contract.test.mjs +11 -2
  277. package/clients/cli/commands/manifest.doc.mjs +1 -0
  278. package/clients/cli/commands/outside-project.test.mjs +774 -0
  279. package/clients/cli/commands/search.doc.mjs +1 -0
  280. package/clients/cli/commands/search.mjs +16 -11
  281. package/clients/cli/commands/search.test.mjs +429 -296
  282. package/clients/cli/commands/setup-nudge.test.mjs +102 -2
  283. package/clients/cli/commands/swizzle.doc.mjs +7 -0
  284. package/clients/cli/commands/swizzle.mjs +5 -3
  285. package/clients/cli/commands/swizzle.routing.test.mjs +19 -2
  286. package/clients/cli/commands/template.doc.mjs +1 -0
  287. package/clients/cli/commands/theme-add-lifecycle.test.mjs +3 -3
  288. package/clients/cli/commands/theme-add.doc.mjs +8 -1
  289. package/clients/cli/commands/theme-build.doc.mjs +1 -0
  290. package/clients/cli/commands/theme-eject.doc.mjs +1 -0
  291. package/clients/cli/commands/theme-list.behavior.test.mjs +6 -0
  292. package/clients/cli/commands/theme-list.doc.mjs +1 -0
  293. package/clients/cli/commands/theme-palette-generate.doc.mjs +1 -0
  294. package/clients/cli/commands/theme-remove.doc.mjs +7 -0
  295. package/clients/cli/commands/theme-targets.doc.mjs +1 -0
  296. package/clients/cli/commands/theme-template.doc.mjs +1 -0
  297. package/clients/cli/commands/theme-use.doc.mjs +7 -0
  298. package/clients/cli/commands/upgrade.config-ordering.test.mjs +2 -1
  299. package/clients/cli/commands/upgrade.doc.mjs +22 -1
  300. package/clients/cli/commands/upgrade.file-protection.test.mjs +3 -2
  301. package/clients/cli/commands/upgrade.hook-output.test.mjs +2 -1
  302. package/clients/cli/commands/upgrade.older-cli.test.mjs +160 -0
  303. package/clients/cli/index.mjs +111 -16
  304. package/clients/cli/lib/cli-error.mjs +4 -1
  305. package/clients/cli/lib/component-format.test.mjs +1 -1
  306. package/clients/cli/lib/define-command.mjs +2 -2
  307. package/clients/cli/lib/json-shim.mjs +3 -1
  308. package/clients/cli/lib/manifest.d.ts +9 -0
  309. package/clients/cli/lib/manifest.mjs +17 -1
  310. package/clients/cli/lib/manifest.test.mjs +25 -0
  311. package/foundation/agent-docs/agent-doc-state.d.mts +35 -6
  312. package/foundation/agent-docs/agent-doc-state.mjs +66 -6
  313. package/foundation/agent-docs/agent-docs.d.mts +4 -3
  314. package/foundation/agent-docs/agent-docs.mjs +11 -9
  315. package/foundation/agent-docs/computer-agent-text.d.mts +133 -0
  316. package/foundation/agent-docs/computer-agent-text.mjs +623 -0
  317. package/foundation/agent-docs/computer-agent-text.test.mjs +602 -0
  318. package/foundation/config/project.d.mts +35 -3
  319. package/foundation/config/project.mjs +145 -8
  320. package/foundation/config/project.test.mjs +66 -0
  321. package/foundation/config/theme-state.mjs +5 -4
  322. package/foundation/discovery/authoring-self-docs.mjs +1 -1
  323. package/foundation/discovery/cli-self-docs.mjs +20 -3
  324. package/foundation/discovery/cli-self-docs.test.mjs +3 -2
  325. package/foundation/discovery/component-replacement.mjs +2 -1
  326. package/foundation/discovery/copied-passages.d.mts +216 -0
  327. package/foundation/discovery/copied-passages.mjs +720 -0
  328. package/foundation/discovery/copied-passages.test.mjs +124 -0
  329. package/foundation/discovery/doc-consistency.d.mts +34 -0
  330. package/foundation/discovery/doc-consistency.mjs +513 -0
  331. package/foundation/discovery/doc-consistency.test.mjs +347 -0
  332. package/foundation/discovery/doc-fluff.d.mts +112 -0
  333. package/foundation/discovery/doc-fluff.mjs +328 -0
  334. package/foundation/discovery/doc-fluff.test.mjs +142 -0
  335. package/foundation/discovery/doc-types.d.mts +1 -1
  336. package/foundation/discovery/doc-types.mjs +15 -8
  337. package/foundation/discovery/doc-types.test.mjs +94 -2
  338. package/foundation/discovery/docs-discovery.d.mts +7 -0
  339. package/foundation/discovery/docs-discovery.mjs +26 -2
  340. package/foundation/discovery/project-typescript.d.mts +11 -2
  341. package/foundation/discovery/project-typescript.mjs +32 -4
  342. package/foundation/discovery/prop-drift.d.mts +26 -7
  343. package/foundation/discovery/prop-drift.mjs +173 -8
  344. package/foundation/discovery/prop-drift.test.mjs +120 -2
  345. package/foundation/discovery/runner-allowlist.d.mts +40 -0
  346. package/foundation/discovery/runner-allowlist.mjs +53 -0
  347. package/foundation/discovery/stray-pointers.d.mts +52 -0
  348. package/foundation/discovery/stray-pointers.mjs +293 -0
  349. package/foundation/discovery/stray-pointers.test.mjs +86 -0
  350. package/foundation/discovery/template-needs.mjs +5 -2
  351. package/foundation/discovery/theme-imports.mjs +8 -4
  352. package/foundation/discovery/theme-imports.test.mjs +1 -1
  353. package/foundation/discovery/type-text.mjs +1 -1
  354. package/foundation/discovery/type-text.test.mjs +1 -1
  355. package/foundation/doc-compiler/doc-loads.test.mjs +42 -2
  356. package/foundation/doc-compiler/inputs.mjs +4 -1
  357. package/foundation/doc-compiler/links.d.mts +32 -0
  358. package/foundation/doc-compiler/links.mjs +163 -26
  359. package/foundation/doc-compiler/links.test.mjs +97 -4
  360. package/foundation/doc-compiler/read.d.mts +1 -1
  361. package/foundation/doc-compiler/tree.mjs +30 -1
  362. package/foundation/doc-compiler/tree.test.mjs +8 -1
  363. package/foundation/env/cli-command.d.mts +83 -0
  364. package/foundation/env/cli-command.mjs +152 -0
  365. package/foundation/env/cli-command.test.mjs +129 -0
  366. package/foundation/env/node-version.test.mjs +15 -3
  367. package/foundation/env/package-manager.d.mts +93 -9
  368. package/foundation/env/package-manager.global.test.mjs +66 -0
  369. package/foundation/env/package-manager.mjs +184 -13
  370. package/foundation/env/package-manager.test.mjs +341 -15
  371. package/foundation/env/project-scope.d.mts +9 -0
  372. package/foundation/env/project-scope.mjs +33 -0
  373. package/foundation/env/search-path.d.mts +42 -0
  374. package/foundation/env/search-path.mjs +205 -0
  375. package/foundation/env/search-path.test.mjs +122 -0
  376. package/foundation/env/user-dirs.d.mts +39 -0
  377. package/foundation/env/user-dirs.mjs +93 -0
  378. package/foundation/env/user-dirs.test.mjs +72 -0
  379. package/foundation/env/user-settings.d.mts +46 -0
  380. package/foundation/env/user-settings.mjs +106 -0
  381. package/foundation/env/user-settings.test.mjs +64 -0
  382. package/foundation/fs/file-protection.mjs +15 -1
  383. package/foundation/fs/module-loader.d.mts +2 -1
  384. package/foundation/fs/module-loader.mjs +60 -4
  385. package/foundation/fs/module-loader.stdout.test.mjs +3 -2
  386. package/foundation/fs/module-loader.test.mjs +194 -0
  387. package/foundation/fs/path-compare.d.mts +33 -0
  388. package/foundation/fs/path-compare.mjs +73 -0
  389. package/foundation/fs/paths.d.mts +57 -1
  390. package/foundation/fs/paths.mjs +131 -3
  391. package/foundation/fs/paths.test.mjs +10 -1
  392. package/foundation/integrations/computer-integrations.d.mts +78 -0
  393. package/foundation/integrations/computer-integrations.mjs +316 -0
  394. package/foundation/integrations/computer-integrations.test.mjs +292 -0
  395. package/foundation/integrations/contribution-inventory.d.mts +11 -0
  396. package/foundation/integrations/contribution-inventory.mjs +50 -2
  397. package/foundation/integrations/integration-warnings.mjs +3 -2
  398. package/foundation/integrations/integration-warnings.test.mjs +8 -9
  399. package/foundation/integrations/integrations.d.mts +25 -1
  400. package/foundation/integrations/integrations.mjs +46 -3
  401. package/foundation/integrations/issue.ts +6 -0
  402. package/foundation/integrations/validate-contributions.d.mts +2 -0
  403. package/foundation/integrations/validate-contributions.mjs +41 -1
  404. package/foundation/release/agent-text-worker.d.mts +4 -0
  405. package/foundation/release/agent-text-worker.mjs +52 -0
  406. package/foundation/release/cache.d.mts +310 -0
  407. package/foundation/release/cache.mjs +1216 -0
  408. package/foundation/release/cache.test.mjs +920 -0
  409. package/foundation/release/choose.d.mts +207 -0
  410. package/foundation/release/choose.mjs +677 -0
  411. package/foundation/release/choose.test.mjs +427 -0
  412. package/foundation/release/core-worker.d.mts +4 -0
  413. package/foundation/release/core-worker.mjs +38 -0
  414. package/foundation/release/global-state.d.mts +259 -0
  415. package/foundation/release/global-state.mjs +472 -0
  416. package/foundation/release/global-state.test.mjs +381 -0
  417. package/foundation/release/handoff.d.mts +60 -0
  418. package/foundation/release/handoff.e2e.test.mjs +278 -0
  419. package/foundation/release/handoff.mjs +357 -0
  420. package/foundation/release/lock-lease.d.mts +23 -0
  421. package/foundation/release/lock-lease.mjs +80 -0
  422. package/foundation/release/notices.d.mts +253 -0
  423. package/foundation/release/notices.mjs +596 -0
  424. package/foundation/release/notices.test.mjs +565 -0
  425. package/foundation/release/npm-guard.d.mts +4 -0
  426. package/foundation/release/npm-guard.mjs +126 -0
  427. package/foundation/release/project.d.mts +141 -0
  428. package/foundation/release/project.mjs +466 -0
  429. package/foundation/release/project.test.mjs +288 -0
  430. package/foundation/release/refresh-worker.d.mts +4 -0
  431. package/foundation/release/refresh-worker.mjs +27 -0
  432. package/foundation/release/run-context.d.mts +47 -0
  433. package/foundation/release/run-context.mjs +149 -0
  434. package/foundation/release/update-notice-env.d.mts +28 -0
  435. package/foundation/release/update-notice-env.mjs +39 -0
  436. package/foundation/response/base.d.ts +26 -3
  437. package/foundation/response/error-codes.d.mts +3 -1
  438. package/foundation/response/error-codes.doc.mjs +12 -0
  439. package/foundation/response/error-codes.mjs +17 -0
  440. package/foundation/response/error-codes.test.mjs +2 -0
  441. package/foundation/response/json-contract.test.mjs +7 -2
  442. package/foundation/response/json.mjs +4 -1
  443. package/foundation/response/response-types.doc.mjs +17 -11
  444. package/foundation/response/response-types.doc.test.mjs +46 -0
  445. package/foundation/response/response.doc.mjs +3 -3
  446. package/foundation/xle/browser-imports.test.mjs +74 -0
  447. package/package.json +11 -11
  448. package/scripts/postinstall.mjs +24 -5
  449. /package/assets/codemods/transforms/{next → v0.7.2}/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +0 -0
  450. /package/assets/codemods/transforms/{next → v0.7.2}/migrate-list-edge-compensation-to-edge.mjs +0 -0
@@ -117,6 +117,23 @@ export function discoverBuiltinTopics() {
117
117
  return topics;
118
118
  }
119
119
 
120
+ /**
121
+ * The CLI's own guide files: every flat topic and every doc in its docs tree,
122
+ * without the dense, translated, and draft variants.
123
+ *
124
+ * @returns {string[]}
125
+ */
126
+ export function builtinGuideFiles() {
127
+ const files = Object.values(discoverBuiltinTopics());
128
+ const tree = path.join(BUILTIN_DOCS_DIR, 'tree');
129
+ if (fs.existsSync(tree)) {
130
+ for (const file of fs.readdirSync(tree).sort()) {
131
+ if (BUILTIN_TOPIC_FILE_RE.test(file)) files.push(path.join(tree, file));
132
+ }
133
+ }
134
+ return files;
135
+ }
136
+
120
137
  /**
121
138
  * Load a topic doc from disk. A `.ts` doc is loaded through jiti, the rest
122
139
  * natively; both the historical `export const docs` and the stamped
@@ -384,7 +401,11 @@ export function problemsInNamespace(doc) {
384
401
  }
385
402
  }
386
403
  const slots = doc?.slots;
387
- if (slots == null || typeof slots !== 'object' || Object.keys(slots).length === 0) {
404
+ if (
405
+ slots == null ||
406
+ typeof slots !== 'object' ||
407
+ Object.keys(slots).length === 0
408
+ ) {
388
409
  problems.push('slots: expected at least one slot');
389
410
  return problems;
390
411
  }
@@ -392,7 +413,10 @@ export function problemsInNamespace(doc) {
392
413
  if (typeof slot?.title !== 'string' || slot.title === '') {
393
414
  problems.push(`slots.${name}.title: expected a non-empty string`);
394
415
  }
395
- if (!Array.isArray(slot?.accepts?.kinds) || slot.accepts.kinds.length === 0) {
416
+ if (
417
+ !Array.isArray(slot?.accepts?.kinds) ||
418
+ slot.accepts.kinds.length === 0
419
+ ) {
396
420
  problems.push(`slots.${name}.accepts.kinds: expected at least one kind`);
397
421
  }
398
422
  }
@@ -2,7 +2,9 @@
2
2
  // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
3
 
4
4
  /**
5
- * Resolve the project's own `typescript`, trying each directory in order.
5
+ * Resolve the project's own `typescript`, trying each directory in order;
6
+ * where it has no JavaScript compiler API (TypeScript 7), the TypeScript 6
7
+ * API package installed beside it.
6
8
  * @param {Array<string | null | undefined>} dirs
7
9
  * @returns {{ts: any, version: string} | {ts: null, version: string} | null}
8
10
  * `ts: null` when a TypeScript is installed but has no `createProgram`
@@ -16,8 +18,15 @@ export function resolveProjectTypeScript(dirs: Array<string | null | undefined>)
16
18
  } | null;
17
19
  /**
18
20
  * Why a check that needs the compiler did not run, when the TypeScript
19
- * installed has no JavaScript compiler API.
21
+ * installed has no JavaScript compiler API, and what to do.
20
22
  * @param {string} version
21
23
  * @param {string} outcome what was not done, such as `docs were not checked`
22
24
  */
23
25
  export function unusableTypeScriptReason(version: string, outcome: string): string;
26
+ /**
27
+ * What to do when the project's TypeScript is missing or cannot be used:
28
+ * beside TypeScript 7, the TypeScript 6 API package it ships for tools;
29
+ * otherwise a version every check here reads, 5.0 (the oldest that checks a
30
+ * JavaScript doc) through 6.
31
+ */
32
+ export const TYPESCRIPT_FIX: "On TypeScript 7, add its TypeScript 6 API package (`npm install -D @typescript/typescript6`); otherwise install TypeScript 5.0 through 6 (`npm install -D typescript@6`). Then run this check again.";
@@ -15,7 +15,16 @@ import * as path from 'node:path';
15
15
  import {createRequire} from 'node:module';
16
16
 
17
17
  /**
18
- * Resolve the project's own `typescript`, trying each directory in order.
18
+ * The package TypeScript publishes beside TypeScript 7 for tools that need a
19
+ * JavaScript compiler API: TypeScript 6's. Kept in a constant so the type
20
+ * check does not treat the load as a static import of an uninstalled package.
21
+ */
22
+ const TYPESCRIPT_6_API = '@typescript/typescript6';
23
+
24
+ /**
25
+ * Resolve the project's own `typescript`, trying each directory in order;
26
+ * where it has no JavaScript compiler API (TypeScript 7), the TypeScript 6
27
+ * API package installed beside it.
19
28
  * @param {Array<string | null | undefined>} dirs
20
29
  * @returns {{ts: any, version: string} | {ts: null, version: string} | null}
21
30
  * `ts: null` when a TypeScript is installed but has no `createProgram`
@@ -43,19 +52,38 @@ export function resolveProjectTypeScript(dirs) {
43
52
  unusable ??= installed();
44
53
  } catch {
45
54
  // Not installed from here, or installed without an entry this CLI can
46
- // load; try the next directory.
55
+ // load.
47
56
  unusable ??= installed();
48
57
  }
58
+ // TypeScript 7 has no JavaScript compiler API; the package TypeScript
59
+ // ships beside it for tools that need one carries TypeScript 6's.
60
+ try {
61
+ const ts = require(TYPESCRIPT_6_API);
62
+ if (ts && typeof ts.createProgram === 'function') {
63
+ return {ts, version: String(ts.version)};
64
+ }
65
+ } catch {
66
+ // Not installed from here; try the next directory.
67
+ }
49
68
  }
50
69
  return unusable ? {ts: null, version: unusable} : null;
51
70
  }
52
71
 
72
+ /**
73
+ * What to do when the project's TypeScript is missing or cannot be used:
74
+ * beside TypeScript 7, the TypeScript 6 API package it ships for tools;
75
+ * otherwise a version every check here reads, 5.0 (the oldest that checks a
76
+ * JavaScript doc) through 6.
77
+ */
78
+ export const TYPESCRIPT_FIX =
79
+ 'On TypeScript 7, add its TypeScript 6 API package (`npm install -D @typescript/typescript6`); otherwise install TypeScript 5.0 through 6 (`npm install -D typescript@6`). Then run this check again.';
80
+
53
81
  /**
54
82
  * Why a check that needs the compiler did not run, when the TypeScript
55
- * installed has no JavaScript compiler API.
83
+ * installed has no JavaScript compiler API, and what to do.
56
84
  * @param {string} version
57
85
  * @param {string} outcome what was not done, such as `docs were not checked`
58
86
  */
59
87
  export function unusableTypeScriptReason(version, outcome) {
60
- return `TypeScript ${version} is installed in this project, but it has no JavaScript compiler API (\`createProgram\`) to read types with, so ${outcome}.`;
88
+ return `TypeScript ${version} is installed in this project, but it has no JavaScript compiler API (\`createProgram\`) to read types with (TypeScript 7 ships none), so ${outcome}. ${TYPESCRIPT_FIX}`;
61
89
  }
@@ -25,7 +25,7 @@ export function comparePropDocs(components: PropDriftComponent[], options: {
25
25
  loadDoc?: (docPath: string) => Promise<any>;
26
26
  }): Promise<PropDriftReport>;
27
27
  /**
28
- * @typedef {'not_in_code' | 'not_in_doc' | 'required_mismatch' | 'type_mismatch'} PropDriftKind
28
+ * @typedef {'not_in_code' | 'not_in_doc' | 'required_mismatch' | 'type_mismatch' | 'default_mismatch'} PropDriftKind
29
29
  */
30
30
  /**
31
31
  * @typedef {object} PropDriftFinding
@@ -40,6 +40,9 @@ export function comparePropDocs(components: PropDriftComponent[], options: {
40
40
  * @property {string} [codeType] the type as the source declares it
41
41
  * @property {boolean} [docRequired]
42
42
  * @property {boolean} [codeRequired]
43
+ * @property {string} [docDefault] the documented default, as written
44
+ * @property {string} [codeDefault] the literal default the code writes
45
+ * @property {string} [fix] what to change, ready to paste
43
46
  */
44
47
  /**
45
48
  * @typedef {object} PropDriftUnchecked
@@ -53,8 +56,10 @@ export function comparePropDocs(components: PropDriftComponent[], options: {
53
56
  * @property {string} doc the doc file, relative to the package root
54
57
  * @property {string} reason why: not a form the check judges exactly, a
55
58
  * field the prop's variants give different types, a standard prop
56
- * (`className`, `style`, …), or a prop declared outside the package
57
- * @property {string[]} props documented props whose types were not compared
59
+ * (`className`, `style`, …), a prop declared outside the package, or a
60
+ * default that is not a literal on one side
61
+ * @property {string[]} props documented props whose types, or defaults, were
62
+ * not compared
58
63
  */
59
64
  /**
60
65
  * @typedef {object} PropDriftReport
@@ -96,7 +101,7 @@ export function comparePropDocs(components: PropDriftComponent[], options: {
96
101
  */
97
102
  export const PROPS_NOT_DOCUMENTED: readonly string[];
98
103
  /** The line both surfaces print when the compiler is missing. */
99
- export const TYPESCRIPT_MISSING_REASON: "TypeScript is not installed in this project, so documented props were not compared with the code. Install typescript and run this check again.";
104
+ export const TYPESCRIPT_MISSING_REASON: "TypeScript is not installed in this project, so documented props were not compared with the code. On TypeScript 7, add its TypeScript 6 API package (`npm install -D @typescript/typescript6`); otherwise install TypeScript 5.0 through 6 (`npm install -D typescript@6`). Then run this check again.";
100
105
  export type CodeProp = {
101
106
  name: string;
102
107
  /**
@@ -146,7 +151,7 @@ export type CodeProp = {
146
151
  */
147
152
  location: any;
148
153
  };
149
- export type PropDriftKind = "not_in_code" | "not_in_doc" | "required_mismatch" | "type_mismatch";
154
+ export type PropDriftKind = "not_in_code" | "not_in_doc" | "required_mismatch" | "type_mismatch" | "default_mismatch";
150
155
  export type PropDriftFinding = {
151
156
  /**
152
157
  * the documented component (export) name
@@ -174,6 +179,18 @@ export type PropDriftFinding = {
174
179
  codeType?: string | undefined;
175
180
  docRequired?: boolean | undefined;
176
181
  codeRequired?: boolean | undefined;
182
+ /**
183
+ * the documented default, as written
184
+ */
185
+ docDefault?: string | undefined;
186
+ /**
187
+ * the literal default the code writes
188
+ */
189
+ codeDefault?: string | undefined;
190
+ /**
191
+ * what to change, ready to paste
192
+ */
193
+ fix?: string | undefined;
177
194
  };
178
195
  export type PropDriftUnchecked = {
179
196
  component: string;
@@ -195,11 +212,13 @@ export type PropDriftTypesNotCompared = {
195
212
  /**
196
213
  * why: not a form the check judges exactly, a
197
214
  * field the prop's variants give different types, a standard prop
198
- * (`className`, `style`, …), or a prop declared outside the package
215
+ * (`className`, `style`, …), a prop declared outside the package, or a
216
+ * default that is not a literal on one side
199
217
  */
200
218
  reason: string;
201
219
  /**
202
- * documented props whose types were not compared
220
+ * documented props whose types, or defaults, were
221
+ * not compared
203
222
  */
204
223
  props: string[];
205
224
  };
@@ -31,7 +31,11 @@
31
31
  * each);
32
32
  * - `type_mismatch`: for a prop declared in the package, the documented type
33
33
  * differs from the code's where both sides read exactly (type-match.mjs
34
- * states the rules); every other type is listed as not compared.
34
+ * states the rules); every other type is listed as not compared;
35
+ * - `default_mismatch`: the doc's `default` and the literal default the
36
+ * component writes in its props parameter's destructuring (`size = 'md'`)
37
+ * differ, quotes and whitespace aside; where both write a default and
38
+ * either is not a literal, it is listed under `typesNotCompared`.
35
39
  *
36
40
  * @input Component records (name, docPath, sourcePath), or prop tables, the
37
41
  * package root, and the directories to resolve `typescript` from.
@@ -47,6 +51,7 @@ import {loadComponentDoc} from './component-loader.mjs';
47
51
  import {readPackageTsconfig} from './package-tsconfig.mjs';
48
52
  import {
49
53
  resolveProjectTypeScript,
54
+ TYPESCRIPT_FIX,
50
55
  unusableTypeScriptReason,
51
56
  } from './project-typescript.mjs';
52
57
  import {judgeType} from './type-match.mjs';
@@ -57,7 +62,7 @@ import {
57
62
  } from './unresolved-references.mjs';
58
63
 
59
64
  /**
60
- * @typedef {'not_in_code' | 'not_in_doc' | 'required_mismatch' | 'type_mismatch'} PropDriftKind
65
+ * @typedef {'not_in_code' | 'not_in_doc' | 'required_mismatch' | 'type_mismatch' | 'default_mismatch'} PropDriftKind
61
66
  */
62
67
 
63
68
  /**
@@ -73,6 +78,9 @@ import {
73
78
  * @property {string} [codeType] the type as the source declares it
74
79
  * @property {boolean} [docRequired]
75
80
  * @property {boolean} [codeRequired]
81
+ * @property {string} [docDefault] the documented default, as written
82
+ * @property {string} [codeDefault] the literal default the code writes
83
+ * @property {string} [fix] what to change, ready to paste
76
84
  */
77
85
 
78
86
  /**
@@ -88,8 +96,10 @@ import {
88
96
  * @property {string} doc the doc file, relative to the package root
89
97
  * @property {string} reason why: not a form the check judges exactly, a
90
98
  * field the prop's variants give different types, a standard prop
91
- * (`className`, `style`, …), or a prop declared outside the package
92
- * @property {string[]} props documented props whose types were not compared
99
+ * (`className`, `style`, …), a prop declared outside the package, or a
100
+ * default that is not a literal on one side
101
+ * @property {string[]} props documented props whose types, or defaults, were
102
+ * not compared
93
103
  */
94
104
 
95
105
  /**
@@ -148,6 +158,15 @@ const SKIP_TAGS = new Set(['internal']);
148
158
  const NOT_EXACT = 'not a form the check judges exactly';
149
159
  /** A field documented with one variant's type, where they differ. */
150
160
  const VARIANTS = "the prop's variants give this field different types";
161
+
162
+ /** A default the code writes that is not a literal (a constant, a call). */
163
+ const NOT_LITERAL = Symbol('not a literal');
164
+
165
+ /** Why a documented default was not compared with the code's. */
166
+ const CODE_DEFAULT_NOT_LITERAL =
167
+ 'its default in the code is not a literal, so the documented default was not compared';
168
+ const DOC_DEFAULT_NOT_LITERAL =
169
+ "its documented default is not a literal, so it was not compared with the code's";
151
170
  /** @type {(name: string, code?: CodeProp) => string} why a prop is not judged */
152
171
  const outside = (name, code) =>
153
172
  code?.untraced
@@ -158,8 +177,7 @@ const outside = (name, code) =>
158
177
  const HOOK_NAME = /^use[A-Z0-9]/;
159
178
 
160
179
  /** The line both surfaces print when the compiler is missing. */
161
- export const TYPESCRIPT_MISSING_REASON =
162
- 'TypeScript is not installed in this project, so documented props were not compared with the code. Install typescript and run this check again.';
180
+ export const TYPESCRIPT_MISSING_REASON = `TypeScript is not installed in this project, so documented props were not compared with the code. ${TYPESCRIPT_FIX}`;
163
181
 
164
182
  /**
165
183
  * @template T
@@ -252,7 +270,7 @@ function ownFileTest(root) {
252
270
  * @param {import('./unresolved-references.mjs').UnresolvedReference | null} ambient
253
271
  * what the program's other roots cannot resolve, which any component may
254
272
  * use
255
- * @returns {{ok: true, props: Map<string, CodeProp>, accepts: (name: string) => any} | {ok: false, reason: string}}
273
+ * @returns {{ok: true, props: Map<string, CodeProp>, accepts: (name: string) => any, defaults?: Map<string, string | number | boolean | null | symbol>} | {ok: false, reason: string}}
256
274
  */
257
275
  function readCodeProps(
258
276
  ts,
@@ -580,7 +598,118 @@ function readCodeProps(
580
598
  /** The index signatures of the props type that take this name. */
581
599
  const accepts = (/** @type {string} */ name) =>
582
600
  indexesFor(ts, checker, members, name);
583
- return {ok: true, props, accepts};
601
+ return {ok: true, props, accepts, defaults: literalDefaults(ts, symbol)};
602
+ }
603
+
604
+ /**
605
+ * The defaults a component writes in its props parameter's destructuring
606
+ * (`{size = 'md'}`), by prop name, each as its value: a string, number,
607
+ * boolean, or null, or NOT_LITERAL for any other default (a constant, a call,
608
+ * an object), which is listed as not compared.
609
+ * @param {any} ts
610
+ * @param {any} symbol the component
611
+ * @returns {Map<string, string | number | boolean | null | symbol>}
612
+ */
613
+ function literalDefaults(ts, symbol) {
614
+ /** @type {Map<string, string | number | boolean | null | symbol>} */
615
+ const out = new Map();
616
+ /** @param {any} node @param {number} depth @returns {any} */
617
+ const fnOf = (node, depth) => {
618
+ if (!node || depth > 4) return null;
619
+ if (
620
+ ts.isFunctionDeclaration(node) ||
621
+ ts.isArrowFunction(node) ||
622
+ ts.isFunctionExpression(node)
623
+ ) {
624
+ return node;
625
+ }
626
+ if (ts.isVariableDeclaration(node))
627
+ return fnOf(node.initializer, depth + 1);
628
+ if (
629
+ ts.isParenthesizedExpression(node) ||
630
+ ts.isAsExpression(node) ||
631
+ (ts.isSatisfiesExpression && ts.isSatisfiesExpression(node))
632
+ ) {
633
+ return fnOf(node.expression, depth + 1);
634
+ }
635
+ // `forwardRef(function …)`, `memo(…)`: the function they wrap.
636
+ if (ts.isCallExpression(node)) {
637
+ for (const argument of node.arguments) {
638
+ const found = fnOf(argument, depth + 1);
639
+ if (found) return found;
640
+ }
641
+ }
642
+ return null;
643
+ };
644
+ const fn = fnOf(symbol?.valueDeclaration, 0);
645
+ const pattern = fn?.parameters?.[0]?.name;
646
+ if (!pattern || !ts.isObjectBindingPattern(pattern)) return out;
647
+ for (const element of pattern.elements) {
648
+ if (element.dotDotDotToken || !element.initializer) continue;
649
+ const key = element.propertyName ?? element.name;
650
+ if (!(
651
+ ts.isIdentifier(key) ||
652
+ ts.isStringLiteral(key) ||
653
+ ts.isNumericLiteral(key)
654
+ )) {
655
+ continue;
656
+ }
657
+ const value = literalValue(ts, element.initializer);
658
+ out.set(key.text, value === undefined ? NOT_LITERAL : value);
659
+ }
660
+ return out;
661
+ }
662
+
663
+ /**
664
+ * A literal expression's value, or undefined for anything else.
665
+ * @param {any} ts
666
+ * @param {any} node
667
+ * @returns {string | number | boolean | null | undefined}
668
+ */
669
+ function literalValue(ts, node) {
670
+ if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) {
671
+ return node.text;
672
+ }
673
+ if (ts.isNumericLiteral(node)) return Number(node.text);
674
+ if (
675
+ ts.isPrefixUnaryExpression(node) &&
676
+ node.operator === ts.SyntaxKind.MinusToken &&
677
+ ts.isNumericLiteral(node.operand)
678
+ ) {
679
+ return -Number(node.operand.text);
680
+ }
681
+ if (node.kind === ts.SyntaxKind.TrueKeyword) return true;
682
+ if (node.kind === ts.SyntaxKind.FalseKeyword) return false;
683
+ if (node.kind === ts.SyntaxKind.NullKeyword) return null;
684
+ return undefined;
685
+ }
686
+
687
+ /**
688
+ * A documented default as a literal value: a quoted string (quotes of any
689
+ * kind, whitespace around it ignored), a number, `true`, `false`, or
690
+ * `null`; undefined for prose or an expression, which is never compared.
691
+ * @param {unknown} written
692
+ * @returns {string | number | boolean | null | undefined}
693
+ */
694
+ function documentedDefault(written) {
695
+ if (typeof written === 'number' || typeof written === 'boolean') {
696
+ return written;
697
+ }
698
+ if (written === null) return null;
699
+ if (typeof written !== 'string') return undefined;
700
+ const text = written.trim();
701
+ const quoted = /^(['"`])([^'"`]*)\1$/.exec(text);
702
+ if (quoted) return quoted[2];
703
+ if (/^-?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i.test(text)) return Number(text);
704
+ if (text === 'true') return true;
705
+ if (text === 'false') return false;
706
+ if (text === 'null') return null;
707
+ return undefined;
708
+ }
709
+
710
+ /** @param {string | number | boolean | null} value */
711
+ function defaultText(value) {
712
+ return typeof value === 'string' ? `'${value}'` : String(value);
584
713
  }
585
714
 
586
715
  /**
@@ -1952,6 +2081,42 @@ export function comparePropTables(tables, options) {
1952
2081
  codeRequired: code.required,
1953
2082
  });
1954
2083
  }
2084
+ // A literal default the code writes in its props destructuring and a
2085
+ // literal the doc writes must agree; where both write a default and
2086
+ // either is not a literal, the default is listed as not compared.
2087
+ const codeDefault = read.defaults?.get(propName);
2088
+ const docWrites =
2089
+ entries.length === 1 &&
2090
+ raw.default !== undefined &&
2091
+ raw.default !== '';
2092
+ const docDefault = docWrites
2093
+ ? documentedDefault(raw.default)
2094
+ : undefined;
2095
+ if (codeDefault !== undefined && docWrites) {
2096
+ if (codeDefault === NOT_LITERAL) {
2097
+ skip(CODE_DEFAULT_NOT_LITERAL, propName);
2098
+ } else if (docDefault === undefined) {
2099
+ skip(DOC_DEFAULT_NOT_LITERAL, propName);
2100
+ }
2101
+ }
2102
+ if (
2103
+ codeDefault !== undefined &&
2104
+ codeDefault !== NOT_LITERAL &&
2105
+ docDefault !== undefined &&
2106
+ codeDefault !== docDefault
2107
+ ) {
2108
+ const shown = defaultText(
2109
+ /** @type {string | number | boolean | null} */ (codeDefault),
2110
+ );
2111
+ findings.push({
2112
+ ...base,
2113
+ kind: 'default_mismatch',
2114
+ message: `"${propName}" is documented with default ${String(raw.default).trim()}, but the code defaults it to ${shown}.`,
2115
+ fix: `In ${table.doc}, set the "${propName}" prop's default to the code's: default: ${JSON.stringify(shown)}.`,
2116
+ docDefault: String(raw.default),
2117
+ codeDefault: shown,
2118
+ });
2119
+ }
1955
2120
  if (!code.own && typeof entry.type === 'string') {
1956
2121
  skip(outside(propName, code), propName);
1957
2122
  }
@@ -58,6 +58,37 @@ function withTypeScript() {
58
58
  );
59
59
  }
60
60
 
61
+ /**
62
+ * TypeScript 7 (no JavaScript compiler API) with the TypeScript 6 API package
63
+ * beside it, which re-exports a real TypeScript.
64
+ */
65
+ function withTypeScript7AndItsTypeScript6Api() {
66
+ const ts7 = path.join(pkg, 'node_modules', 'typescript');
67
+ fs.mkdirSync(ts7, {recursive: true});
68
+ fs.writeFileSync(
69
+ path.join(ts7, 'package.json'),
70
+ JSON.stringify({
71
+ name: 'typescript',
72
+ version: '7.0.2',
73
+ exports: {'./package.json': './package.json'},
74
+ }),
75
+ );
76
+ const ts6 = path.join(pkg, 'node_modules', '@typescript', 'typescript6');
77
+ fs.mkdirSync(ts6, {recursive: true});
78
+ fs.writeFileSync(
79
+ path.join(ts6, 'package.json'),
80
+ JSON.stringify({
81
+ name: '@typescript/typescript6',
82
+ version: '6.0.2',
83
+ main: 'index.js',
84
+ }),
85
+ );
86
+ fs.writeFileSync(
87
+ path.join(ts6, 'index.js'),
88
+ `module.exports = require(${JSON.stringify(TYPESCRIPT_DIR)});\n`,
89
+ );
90
+ }
91
+
61
92
  /**
62
93
  * Write `components/<name>.tsx` and its doc; returns its prop table, which
63
94
  * also carries the component record (name, docPath, sourcePath).
@@ -176,7 +207,8 @@ describe('comparePropTables', () => {
176
207
  expect(await compare([component('Badge', source, doc)])).toMatchObject({
177
208
  findings: [],
178
209
  typesCompared: 0,
179
- typesSkipped: `TypeScript 4.7.4 is older than 4.8, the oldest the type comparison reads`,
210
+ typesSkipped:
211
+ 'TypeScript 4.7.4 is older than 4.8, the oldest the type comparison reads; install TypeScript 5.0 through 6 (`npm install -D typescript@6`), or on TypeScript 7 add `@typescript/typescript6`, to judge them',
180
212
  });
181
213
  });
182
214
 
@@ -334,6 +366,71 @@ export function Badge(props: BadgeProps) { return null; }`,
334
366
  ).toMatchObject({docRequired: false, codeRequired: true});
335
367
  });
336
368
 
369
+ it('compares a documented default with a literal default in the props destructuring, quotes and whitespace aside, and skips any other default', async () => {
370
+ withTypeScript();
371
+ const widget = component(
372
+ 'Widget',
373
+ `const SIZE = 'md';
374
+ export interface WidgetProps { size?: 'sm' | 'md'; tone?: string; count?: number; open?: boolean; label?: string; gap?: number; mode?: string }
375
+ export function Widget({size = 'md', tone = "info", count = -2, open = false, label = SIZE, gap = 4, mode}: WidgetProps) { return null; }`,
376
+ {
377
+ props: [
378
+ prop('size', "'sm' | 'md'", {default: "'sm'"}),
379
+ prop('tone', 'string', {default: ' "info" '}),
380
+ prop('count', 'number', {default: '-2'}),
381
+ prop('open', 'boolean', {default: 'true'}),
382
+ prop('label', 'string', {default: "'x'"}),
383
+ prop('gap', 'number', {default: 'the theme gap'}),
384
+ prop('mode', 'string', {default: "'a'"}),
385
+ ],
386
+ },
387
+ );
388
+ const forwarded = component(
389
+ 'Forwarded',
390
+ `declare function forwardRef<T>(render: T): T;
391
+ export const Forwarded = forwardRef(function Forwarded({variant = 'solid'}: {variant?: string}) { return null; });`,
392
+ {props: [prop('variant', 'string', {default: "'ghost'"})]},
393
+ );
394
+
395
+ const report = await compare([widget, forwarded]);
396
+
397
+ expect(kinds(report)).toEqual([
398
+ 'Forwarded.variant default_mismatch',
399
+ 'Widget.open default_mismatch',
400
+ 'Widget.size default_mismatch',
401
+ ]);
402
+ // A default that is not a literal on either side is listed, not skipped.
403
+ expect(report.typesNotCompared).toEqual(
404
+ expect.arrayContaining([
405
+ expect.objectContaining({
406
+ component: 'Widget',
407
+ reason: expect.stringContaining(
408
+ 'default in the code is not a literal',
409
+ ),
410
+ props: ['label'],
411
+ }),
412
+ expect.objectContaining({
413
+ component: 'Widget',
414
+ reason: expect.stringContaining(
415
+ 'documented default is not a literal',
416
+ ),
417
+ props: ['gap'],
418
+ }),
419
+ ]),
420
+ );
421
+ expect(report.typesNotCompared.flatMap(entry => entry.props)).not.toContain(
422
+ 'mode',
423
+ );
424
+ expect(report.findings.find(f => f.prop === 'size')).toMatchObject({
425
+ severity: 'warning',
426
+ message:
427
+ "\"size\" is documented with default 'sm', but the code defaults it to 'md'.",
428
+ fix: 'In components/Widget.doc.mjs, set the "size" prop\'s default to the code\'s: default: "\'md\'".',
429
+ docDefault: "'sm'",
430
+ codeDefault: "'md'",
431
+ });
432
+ });
433
+
337
434
  it("judges a field, a name an index signature takes, and a prop declared in another file by the type's name where the prop is declared, not by the name the type was declared with", async () => {
338
435
  withTypeScript();
339
436
  const dir = path.join(pkg, 'components');
@@ -2179,6 +2276,23 @@ export const Hoc = withName((props: {label?: string}) => null);`;
2179
2276
  ]);
2180
2277
  });
2181
2278
 
2279
+ it("compares with TypeScript 7's TypeScript 6 API package when the project has one", async () => {
2280
+ const badge = component(
2281
+ 'Badge',
2282
+ 'export function Badge(props: {label: string}) { return null; }\n',
2283
+ {props: [prop('label', 'number')]},
2284
+ );
2285
+ withTypeScript7AndItsTypeScript6Api();
2286
+
2287
+ const report = await compare([badge]);
2288
+
2289
+ expect(report.status).toBe('checked');
2290
+ // The comparison ran: the documented `number` is judged against `string`.
2291
+ expect(
2292
+ report.findings.map(f => `${f.component}.${f.prop} ${f.kind}`),
2293
+ ).toContain('Badge.label type_mismatch');
2294
+ });
2295
+
2182
2296
  it('skips with a reason, and compares nothing, without a TypeScript it can use', async () => {
2183
2297
  const badge = component(
2184
2298
  'Badge',
@@ -2196,6 +2310,7 @@ export const Hoc = withName((props: {label?: string}) => null);`;
2196
2310
  });
2197
2311
 
2198
2312
  expect(await compare([badge])).toEqual(skipped(TYPESCRIPT_MISSING_REASON));
2313
+ expect(TYPESCRIPT_MISSING_REASON).toContain('npm install -D typescript@6');
2199
2314
  // TypeScript 7 has no JavaScript compiler API to load.
2200
2315
  const dir = path.join(pkg, 'node_modules', 'typescript');
2201
2316
  fs.mkdirSync(dir, {recursive: true});
@@ -2207,7 +2322,10 @@ export const Hoc = withName((props: {label?: string}) => null);`;
2207
2322
  exports: {'./package.json': './package.json'},
2208
2323
  }),
2209
2324
  );
2210
- expect(await compare([badge])).toEqual(
2325
+ const report = await compare([badge]);
2326
+ expect(report.reason).toContain('TypeScript 7.0.0');
2327
+ expect(report.reason).toContain('npm install -D @typescript/typescript6');
2328
+ expect(report).toEqual(
2211
2329
  skipped(
2212
2330
  unusableTypeScriptReason(
2213
2331
  '7.0.0',
@@ -0,0 +1,40 @@
1
+ // @generated by scripts/sync-api-types.mjs from the JSDoc in foundation/**/*.mjs.
2
+ // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
+
4
+ /**
5
+ * @file Where a runner may stand in front of an Astryx command in Astryx's own
6
+ * docs. Docs write commands bare (`astryx <command>`): the CLI prefixes each
7
+ * one with the reader's command when it prints a doc, and the docsite with
8
+ * `npx @astryxdesign/cli`. A few files show a runner on purpose, and some files
9
+ * are not docs at all. The rules, checked by test/runner-commands.test.mjs:
10
+ *
11
+ * - npx (or another download runner) with the unscoped name `astryx` is never
12
+ * written outside `skip`: it fetches an unrelated npm package.
13
+ * - In a doc (`*.doc.mjs`, and Core's docs.mjs), no runner precedes an Astryx
14
+ * command, except in `runnerExamples`, where `npx @astryxdesign/cli …` and a
15
+ * project's runner may (still never the unscoped name through npx).
16
+ *
17
+ * TODO(doctor-runner-check): the Doctor lane's integration-docs runner check
18
+ * (foundation/discovery/runner-commands.mjs) becomes the single rule; then the
19
+ * repo test runs that check over Core's and the CLI's own docs with this
20
+ * allowlist.
21
+ *
22
+ * @input nothing
23
+ * @output the allowlist
24
+ * @position packages/cli/foundation/discovery — data shared by the repo test
25
+ * and the Doctor runner check
26
+ */
27
+ export const RUNNER_COMMAND_ALLOWLIST: Readonly<{
28
+ /** Files never scanned: release notes, tests, and the helpers that build runner forms. */
29
+ skip: readonly RegExp[];
30
+ /** Docs that show a runner on purpose, and why. */
31
+ runnerExamples: Readonly<{
32
+ 'packages/core/docs.mjs': "Core's setup banner, for a project that has no CLI installed yet";
33
+ 'packages/cli/assets/docs/tree/updates.doc.mjs': "quotes the CLI's own update notice, which names the project's runner";
34
+ 'packages/cli/assets/docs/tree/cli-command.doc.mjs': "explains how printed commands start, the pinned `npx @astryxdesign/cli@<version>` among them";
35
+ 'packages/cli/assets/docs/tree/who-answers.doc.mjs': "explains how printed commands start, the pinned `npx @astryxdesign/cli@<version>` among them";
36
+ 'packages/cli/assets/docs/tree/project-global-or-both.doc.mjs': "compares running the CLI with npx to installing it, and is found by searching for that command";
37
+ 'packages/cli/assets/docs/tree/install-once.doc.mjs': "names a pinned release, `npx @astryxdesign/cli@<version>`, which answers as that version";
38
+ 'packages/cli/clients/cli/commands/upgrade.doc.mjs': "quotes the command upgrade prints when the CLI is older than Core, pinned to the matching release";
39
+ }>;
40
+ }>;