@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
@@ -0,0 +1,141 @@
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
+ * An installed package and its version.
6
+ * @typedef {object} InstalledAstryxPackage
7
+ * @property {string} dir the package folder
8
+ * @property {string} version its package.json version
9
+ */
10
+ /**
11
+ * What one folder's project says about releases.
12
+ * @typedef {object} ReleaseFacts
13
+ * @property {boolean} inProject the folder belongs to a project: it reads an
14
+ * installed Core or CLI, or a package.json above it declares one
15
+ * @property {InstalledAstryxPackage | null} core the Core the folder reads
16
+ * @property {InstalledAstryxPackage | null} cli the CLI the folder installs
17
+ * @property {string | null} declaringDir the nearest folder whose package.json
18
+ * declares the Core or the CLI
19
+ * @property {string | null} declaredCoreRange the Core range it declares
20
+ * @property {string | null} declaredCliRange the CLI range it declares
21
+ * @property {string | null} lockedCoreVersion the Core version its lockfile records
22
+ * @property {string | null} lockedCliVersion the CLI version its lockfile records
23
+ */
24
+ /**
25
+ * Read and parse a JSON file, or null.
26
+ * @param {string} file
27
+ * @returns {any}
28
+ */
29
+ export function readJson(file: string): any;
30
+ /**
31
+ * The Core the folder reads, found the way `findCoreDir` finds it: the
32
+ * folder and up to four folders above it, a workspace's `packages/core` or
33
+ * an installed `node_modules/@astryxdesign/core`, else the same from the
34
+ * folder of the package.json that makes the folder part of a project. A `packages/core` that is
35
+ * another package is skipped, because no release pairs with it.
36
+ * @param {string} startDir
37
+ * @returns {InstalledAstryxPackage | null}
38
+ */
39
+ export function findReadCore(startDir: string): InstalledAstryxPackage | null;
40
+ /**
41
+ * The CLI the folder installs, found the way reads find installed packages;
42
+ * else a workspace's own CLI package: the folder itself when it is the CLI
43
+ * package, or a `packages/cli` that is, in the folder or one of the five
44
+ * folders above it (spec AST-081, a folder's project). A repository that
45
+ * builds the CLI and Core side by side answers with its own CLI.
46
+ * @param {string} startDir
47
+ * @returns {InstalledAstryxPackage | null}
48
+ */
49
+ export function findProjectCli(startDir: string): InstalledAstryxPackage | null;
50
+ /**
51
+ * The nearest package.json at or above `startDir` that declares the Core or
52
+ * the CLI. The search stops after the first folder that holds
53
+ * version-control metadata, and passes the home folder by unless the run
54
+ * starts there, so a stray package.json in the home folder never claims every
55
+ * folder beneath it.
56
+ * @param {string} startDir
57
+ * @returns {{dir: string, core: string | null, cli: string | null} | null}
58
+ */
59
+ export function findDeclaringPackage(startDir: string): {
60
+ dir: string;
61
+ core: string | null;
62
+ cli: string | null;
63
+ } | null;
64
+ /**
65
+ * The version a lockfile records for `name`, for the package at `memberDir`.
66
+ * @param {string} lockfile
67
+ * @param {string} memberDir the folder whose package.json declares it
68
+ * @param {string} name
69
+ * @param {string | null} range the range that folder declares
70
+ * @returns {string | null}
71
+ */
72
+ export function lockedVersion(lockfile: string, memberDir: string, name: string, range: string | null): string | null;
73
+ /**
74
+ * The lockfile that records the package at `memberDir`: the nearest one at or
75
+ * above it, up to the repository root.
76
+ * @param {string} memberDir
77
+ * @returns {string | null}
78
+ */
79
+ export function findLockfile(memberDir: string): string | null;
80
+ /**
81
+ * Read every release fact for `startDir`.
82
+ * @param {string} startDir
83
+ * @returns {ReleaseFacts}
84
+ */
85
+ export function readReleaseFacts(startDir: string): ReleaseFacts;
86
+ /** The CLI package. */
87
+ export const CLI_PACKAGE_NAME: "@astryxdesign/cli";
88
+ /** The Core package. */
89
+ export const CORE_PACKAGE_NAME: "@astryxdesign/core";
90
+ /**
91
+ * An installed package and its version.
92
+ */
93
+ export type InstalledAstryxPackage = {
94
+ /**
95
+ * the package folder
96
+ */
97
+ dir: string;
98
+ /**
99
+ * its package.json version
100
+ */
101
+ version: string;
102
+ };
103
+ /**
104
+ * What one folder's project says about releases.
105
+ */
106
+ export type ReleaseFacts = {
107
+ /**
108
+ * the folder belongs to a project: it reads an
109
+ * installed Core or CLI, or a package.json above it declares one
110
+ */
111
+ inProject: boolean;
112
+ /**
113
+ * the Core the folder reads
114
+ */
115
+ core: InstalledAstryxPackage | null;
116
+ /**
117
+ * the CLI the folder installs
118
+ */
119
+ cli: InstalledAstryxPackage | null;
120
+ /**
121
+ * the nearest folder whose package.json
122
+ * declares the Core or the CLI
123
+ */
124
+ declaringDir: string | null;
125
+ /**
126
+ * the Core range it declares
127
+ */
128
+ declaredCoreRange: string | null;
129
+ /**
130
+ * the CLI range it declares
131
+ */
132
+ declaredCliRange: string | null;
133
+ /**
134
+ * the Core version its lockfile records
135
+ */
136
+ lockedCoreVersion: string | null;
137
+ /**
138
+ * the CLI version its lockfile records
139
+ */
140
+ lockedCliVersion: string | null;
141
+ };
@@ -0,0 +1,466 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file What a folder's project says about which CLI release answers there.
5
+ *
6
+ * Global mode picks one release per folder (spec AST-081 FR2): the project's
7
+ * own CLI when it matches the project's Core, otherwise the CLI release that
8
+ * matches the Core. This module reads the facts that choice needs, and nothing
9
+ * else: the Core the folder reads, the CLI the folder installs, and the Astryx
10
+ * versions its package.json and lockfile record.
11
+ *
12
+ * It finds Core and the CLI with the CLI's released reach, the same lookups
13
+ * every read uses (`findCoreDir`, `findInstalledPackage`), so the release that
14
+ * answers always pairs with the Core its reads load. A folder inside another
15
+ * project therefore belongs to that project, as it does for reads.
16
+ *
17
+ * Plain files only: no imports beyond Node built-ins and the path helpers, so
18
+ * the bin can read these facts before it loads anything else.
19
+ *
20
+ * @input a folder
21
+ * @output {@link ReleaseFacts}
22
+ * @position foundation/release — read by the bin's hand-off and by the run
23
+ * context that names who answered.
24
+ */
25
+
26
+ import * as fs from 'node:fs';
27
+ import * as os from 'node:os';
28
+ import * as path from 'node:path';
29
+ import {findInstalledPackage} from '../fs/paths.mjs';
30
+
31
+ /** The CLI package. */
32
+ export const CLI_PACKAGE_NAME = '@astryxdesign/cli';
33
+ /** The Core package. */
34
+ export const CORE_PACKAGE_NAME = '@astryxdesign/core';
35
+
36
+ /**
37
+ * An installed package and its version.
38
+ * @typedef {object} InstalledAstryxPackage
39
+ * @property {string} dir the package folder
40
+ * @property {string} version its package.json version
41
+ */
42
+
43
+ /**
44
+ * What one folder's project says about releases.
45
+ * @typedef {object} ReleaseFacts
46
+ * @property {boolean} inProject the folder belongs to a project: it reads an
47
+ * installed Core or CLI, or a package.json above it declares one
48
+ * @property {InstalledAstryxPackage | null} core the Core the folder reads
49
+ * @property {InstalledAstryxPackage | null} cli the CLI the folder installs
50
+ * @property {string | null} declaringDir the nearest folder whose package.json
51
+ * declares the Core or the CLI
52
+ * @property {string | null} declaredCoreRange the Core range it declares
53
+ * @property {string | null} declaredCliRange the CLI range it declares
54
+ * @property {string | null} lockedCoreVersion the Core version its lockfile records
55
+ * @property {string | null} lockedCliVersion the CLI version its lockfile records
56
+ */
57
+
58
+ /**
59
+ * Read and parse a JSON file, or null.
60
+ * @param {string} file
61
+ * @returns {any}
62
+ */
63
+ export function readJson(file) {
64
+ try {
65
+ return JSON.parse(fs.readFileSync(file, 'utf-8'));
66
+ } catch {
67
+ // Missing or unreadable: the caller treats it as absent.
68
+ return null;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * The version of an installed package folder, when it is the package named.
74
+ * @param {string} dir
75
+ * @param {string} name
76
+ * @returns {InstalledAstryxPackage | null}
77
+ */
78
+ function installedAs(dir, name) {
79
+ const pkg = readJson(path.join(dir, 'package.json'));
80
+ if (!pkg || pkg.name !== name || typeof pkg.version !== 'string') {
81
+ return null;
82
+ }
83
+ return {dir, version: pkg.version};
84
+ }
85
+
86
+ /**
87
+ * The Core the folder reads, found the way `findCoreDir` finds it: the
88
+ * folder and up to four folders above it, a workspace's `packages/core` or
89
+ * an installed `node_modules/@astryxdesign/core`, else the same from the
90
+ * folder of the package.json that makes the folder part of a project. A `packages/core` that is
91
+ * another package is skipped, because no release pairs with it.
92
+ * @param {string} startDir
93
+ * @returns {InstalledAstryxPackage | null}
94
+ */
95
+ export function findReadCore(startDir) {
96
+ const near = nearbyReadCore(startDir);
97
+ if (near) return near;
98
+ // A folder deeper than that reach still belongs to the project the walk to
99
+ // its package.json finds, so its Core is read from there (spec AST-081, a
100
+ // folder's project).
101
+ const declaring = findDeclaringPackage(startDir);
102
+ return declaring && declaring.dir !== path.resolve(startDir)
103
+ ? nearbyReadCore(declaring.dir)
104
+ : null;
105
+ }
106
+
107
+ /**
108
+ * The Core installed in the folder or one of the four folders above it, or a
109
+ * workspace's own Core package there.
110
+ * @param {string} startDir
111
+ * @returns {InstalledAstryxPackage | null}
112
+ */
113
+ function nearbyReadCore(startDir) {
114
+ let dir = path.resolve(startDir);
115
+ for (let i = 0; i < 5; i++) {
116
+ const workspace = installedAs(
117
+ path.join(dir, 'packages', 'core'),
118
+ CORE_PACKAGE_NAME,
119
+ );
120
+ if (workspace) return workspace;
121
+ const installed = installedAs(
122
+ path.join(dir, 'node_modules', '@astryxdesign', 'core'),
123
+ CORE_PACKAGE_NAME,
124
+ );
125
+ if (installed) return installed;
126
+ const parent = path.dirname(dir);
127
+ if (parent === dir) break;
128
+ dir = parent;
129
+ }
130
+ return null;
131
+ }
132
+
133
+ /**
134
+ * The CLI the folder installs, found the way reads find installed packages;
135
+ * else a workspace's own CLI package: the folder itself when it is the CLI
136
+ * package, or a `packages/cli` that is, in the folder or one of the five
137
+ * folders above it (spec AST-081, a folder's project). A repository that
138
+ * builds the CLI and Core side by side answers with its own CLI.
139
+ * @param {string} startDir
140
+ * @returns {InstalledAstryxPackage | null}
141
+ */
142
+ export function findProjectCli(startDir) {
143
+ const start = path.resolve(startDir);
144
+ const dir = findInstalledPackage(start, CLI_PACKAGE_NAME);
145
+ if (dir) return installedAs(dir, CLI_PACKAGE_NAME);
146
+ let at = start;
147
+ for (let i = 0; i < 6; i++) {
148
+ const own =
149
+ installedAs(at, CLI_PACKAGE_NAME) ??
150
+ installedAs(path.join(at, 'packages', 'cli'), CLI_PACKAGE_NAME);
151
+ if (own) return own;
152
+ const parent = path.dirname(at);
153
+ if (parent === at) break;
154
+ at = parent;
155
+ }
156
+ return null;
157
+ }
158
+
159
+ /** Version-control metadata that marks a repository's root. */
160
+ const REPOSITORY_MARKERS = ['.git', '.hg', '.sl'];
161
+
162
+ /**
163
+ * The Astryx ranges a package.json declares, from any dependency field.
164
+ * @param {any} pkg
165
+ * @returns {{core: string | null, cli: string | null}}
166
+ */
167
+ function declaredRanges(pkg) {
168
+ /** @type {{core: string | null, cli: string | null}} */
169
+ const out = {core: null, cli: null};
170
+ if (!pkg || typeof pkg !== 'object') return out;
171
+ for (const field of [
172
+ 'dependencies',
173
+ 'devDependencies',
174
+ 'optionalDependencies',
175
+ 'peerDependencies',
176
+ ]) {
177
+ const deps = pkg[field];
178
+ if (!deps || typeof deps !== 'object') continue;
179
+ if (out.core === null && typeof deps[CORE_PACKAGE_NAME] === 'string') {
180
+ out.core = deps[CORE_PACKAGE_NAME];
181
+ }
182
+ if (out.cli === null && typeof deps[CLI_PACKAGE_NAME] === 'string') {
183
+ out.cli = deps[CLI_PACKAGE_NAME];
184
+ }
185
+ }
186
+ return out;
187
+ }
188
+
189
+ /**
190
+ * The nearest package.json at or above `startDir` that declares the Core or
191
+ * the CLI. The search stops after the first folder that holds
192
+ * version-control metadata, and passes the home folder by unless the run
193
+ * starts there, so a stray package.json in the home folder never claims every
194
+ * folder beneath it.
195
+ * @param {string} startDir
196
+ * @returns {{dir: string, core: string | null, cli: string | null} | null}
197
+ */
198
+ export function findDeclaringPackage(startDir) {
199
+ const home = path.resolve(os.homedir());
200
+ const start = path.resolve(startDir);
201
+ let dir = start;
202
+ for (;;) {
203
+ if (dir !== home || dir === start) {
204
+ const ranges = declaredRanges(readJson(path.join(dir, 'package.json')));
205
+ if (ranges.core !== null || ranges.cli !== null) return {dir, ...ranges};
206
+ }
207
+ if (REPOSITORY_MARKERS.some(m => fs.existsSync(path.join(dir, m)))) {
208
+ return null;
209
+ }
210
+ const parent = path.dirname(dir);
211
+ if (parent === dir) return null;
212
+ dir = parent;
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Every lockfile name the version reader understands.
218
+ */
219
+ const LOCKFILES = [
220
+ 'package-lock.json',
221
+ 'npm-shrinkwrap.json',
222
+ 'pnpm-lock.yaml',
223
+ 'yarn.lock',
224
+ 'bun.lock',
225
+ ];
226
+
227
+ /**
228
+ * The version a lockfile records for `name`, for the package at `memberDir`.
229
+ * @param {string} lockfile
230
+ * @param {string} memberDir the folder whose package.json declares it
231
+ * @param {string} name
232
+ * @param {string | null} range the range that folder declares
233
+ * @returns {string | null}
234
+ */
235
+ export function lockedVersion(lockfile, memberDir, name, range) {
236
+ let text;
237
+ try {
238
+ text = fs.readFileSync(lockfile, 'utf-8');
239
+ } catch {
240
+ // An unreadable lockfile records nothing.
241
+ return null;
242
+ }
243
+ const base = path.basename(lockfile);
244
+ const rel = path
245
+ .relative(path.dirname(lockfile), memberDir)
246
+ .split(path.sep)
247
+ .join('/');
248
+ if (base === 'package-lock.json' || base === 'npm-shrinkwrap.json') {
249
+ const lock = safeJson(text);
250
+ const packages = lock?.packages;
251
+ if (packages && typeof packages === 'object') {
252
+ for (const key of [
253
+ rel ? `${rel}/node_modules/${name}` : null,
254
+ `node_modules/${name}`,
255
+ ]) {
256
+ const version = key ? packages[key]?.version : undefined;
257
+ if (typeof version === 'string') return version;
258
+ }
259
+ }
260
+ const legacy = lock?.dependencies?.[name]?.version;
261
+ return typeof legacy === 'string' ? legacy : null;
262
+ }
263
+ if (base === 'pnpm-lock.yaml') return pnpmLockedVersion(text, rel, name);
264
+ if (base === 'yarn.lock') return yarnLockedVersion(text, name, range);
265
+ if (base === 'bun.lock') return bunLockedVersion(text, name);
266
+ return null;
267
+ }
268
+
269
+ /**
270
+ * @param {string} text
271
+ * @returns {any}
272
+ */
273
+ function safeJson(text) {
274
+ try {
275
+ return JSON.parse(text);
276
+ } catch {
277
+ return null;
278
+ }
279
+ }
280
+
281
+ /** @param {string} s */
282
+ const escapeRe = s => s.replace(/[.*+?^${}()|[\]\\/]/g, '\\$&');
283
+
284
+ /**
285
+ * A pnpm lockfile's version for `name` in the importer at `rel` (`.` at the
286
+ * root): the `version:` under that importer's dependency entry, with any
287
+ * peer suffix (`0.7.1(react@19.0.0)`) dropped.
288
+ * @param {string} text
289
+ * @param {string} rel
290
+ * @param {string} name
291
+ * @returns {string | null}
292
+ */
293
+ function pnpmLockedVersion(text, rel, name) {
294
+ const lines = text.split(/\r?\n/);
295
+ const importer = rel || '.';
296
+ let inImporters = false;
297
+ let inThisImporter = false;
298
+ for (let i = 0; i < lines.length; i++) {
299
+ const line = lines[i];
300
+ if (/^importers:\s*$/.test(line)) {
301
+ inImporters = true;
302
+ continue;
303
+ }
304
+ if (inImporters && /^\S/.test(line)) break;
305
+ if (!inImporters) continue;
306
+ const importerMatch = /^ {2}(?! )(['"]?)(.+?)\1:\s*$/.exec(line);
307
+ if (importerMatch) {
308
+ inThisImporter = importerMatch[2] === importer;
309
+ continue;
310
+ }
311
+ if (!inThisImporter) continue;
312
+ const depMatch = new RegExp(`^ {6}(['"]?)${escapeRe(name)}\\1:\\s*$`).exec(
313
+ line,
314
+ );
315
+ if (!depMatch) continue;
316
+ for (let j = i + 1; j < lines.length && /^ {8}/.test(lines[j]); j++) {
317
+ const v = /^ {8}version:\s*['"]?([^'"\s(]+)/.exec(lines[j]);
318
+ if (v) return cleanVersion(v[1]);
319
+ }
320
+ }
321
+ // An older lockfile without importers lists `/name@version` keys.
322
+ const key = new RegExp(
323
+ `^ {2}['"]?/?${escapeRe(name)}[@/](\\d[^:'"\\s(]*)`,
324
+ 'm',
325
+ );
326
+ const m = key.exec(text);
327
+ return m ? cleanVersion(m[1]) : null;
328
+ }
329
+
330
+ /**
331
+ * A yarn.lock's version for `name`: the entry whose descriptors include the
332
+ * declared range (classic `name@^1`, Berry `name@npm:^1`), else the only
333
+ * entry for the name.
334
+ * @param {string} text
335
+ * @param {string} name
336
+ * @param {string | null} range
337
+ * @returns {string | null}
338
+ */
339
+ function yarnLockedVersion(text, name, range) {
340
+ const blocks = text.split(/\r?\n(?=\S)/);
341
+ /** @type {string[]} */
342
+ const versions = [];
343
+ for (const block of blocks) {
344
+ const [head, ...rest] = block.split(/\r?\n/);
345
+ const descriptors = head
346
+ .replace(/:\s*$/, '')
347
+ .split(',')
348
+ .map(d => d.trim().replace(/^"|"$/g, ''));
349
+ const ours = descriptors.filter(
350
+ d => d.startsWith(`${name}@`) && !d.startsWith(`${name}@patch:`),
351
+ );
352
+ if (ours.length === 0) continue;
353
+ const versionLine = rest.find(l => /^\s+version:?\s/.test(l));
354
+ const v = versionLine && /version:?\s+"?([^"\s]+)"?/.exec(versionLine);
355
+ const version = v ? cleanVersion(v[1]) : null;
356
+ if (!version) continue;
357
+ if (
358
+ range &&
359
+ ours.some(d => d === `${name}@${range}` || d === `${name}@npm:${range}`)
360
+ ) {
361
+ return version;
362
+ }
363
+ versions.push(version);
364
+ }
365
+ return versions.length === 1 ? versions[0] : null;
366
+ }
367
+
368
+ /**
369
+ * A bun.lock's version for `name`: its `packages` entry,
370
+ * `"name": ["name@version", …]`.
371
+ * @param {string} text
372
+ * @param {string} name
373
+ * @returns {string | null}
374
+ */
375
+ function bunLockedVersion(text, name) {
376
+ const m = new RegExp(
377
+ `"${escapeRe(name)}"\\s*:\\s*\\[\\s*"${escapeRe(name)}@([^"]+)"`,
378
+ ).exec(text);
379
+ return m ? cleanVersion(m[1]) : null;
380
+ }
381
+
382
+ /**
383
+ * A plain version from a lockfile value: strips an `npm:` protocol and any
384
+ * peer suffix.
385
+ * @param {string} value
386
+ * @returns {string | null}
387
+ */
388
+ function cleanVersion(value) {
389
+ const v = value.replace(/^npm:/, '').replace(/\(.*$/, '');
390
+ return /^\d+\.\d+\.\d+/.test(v) ? v : null;
391
+ }
392
+
393
+ /**
394
+ * The lockfile that records the package at `memberDir`: the nearest one at or
395
+ * above it, up to the repository root.
396
+ * @param {string} memberDir
397
+ * @returns {string | null}
398
+ */
399
+ export function findLockfile(memberDir) {
400
+ let dir = path.resolve(memberDir);
401
+ for (;;) {
402
+ for (const name of LOCKFILES) {
403
+ const file = path.join(dir, name);
404
+ if (fs.existsSync(file)) return file;
405
+ }
406
+ if (REPOSITORY_MARKERS.some(m => fs.existsSync(path.join(dir, m)))) {
407
+ return null;
408
+ }
409
+ const parent = path.dirname(dir);
410
+ if (parent === dir) return null;
411
+ dir = parent;
412
+ }
413
+ }
414
+
415
+ /**
416
+ * Read every release fact for `startDir`.
417
+ * @param {string} startDir
418
+ * @returns {ReleaseFacts}
419
+ */
420
+ export function readReleaseFacts(startDir) {
421
+ const declaring = findDeclaringPackage(startDir);
422
+ // A folder deeper than the nearby look reaches still belongs to the project
423
+ // the walk found, so its own CLI is looked up from there too, as a package
424
+ // runner resolves the project's command from any depth (spec AST-081, a
425
+ // folder's project); findReadCore does the same for Core.
426
+ const fromRoot =
427
+ declaring && declaring.dir !== path.resolve(startDir)
428
+ ? declaring.dir
429
+ : null;
430
+ const core = findReadCore(startDir);
431
+ const cli =
432
+ findProjectCli(startDir) ?? (fromRoot ? findProjectCli(fromRoot) : null);
433
+ let lockedCoreVersion = null;
434
+ let lockedCliVersion = null;
435
+ if (declaring && (!core || !cli)) {
436
+ const lockfile = findLockfile(declaring.dir);
437
+ if (lockfile) {
438
+ lockedCoreVersion = declaring.core
439
+ ? lockedVersion(
440
+ lockfile,
441
+ declaring.dir,
442
+ CORE_PACKAGE_NAME,
443
+ declaring.core,
444
+ )
445
+ : null;
446
+ lockedCliVersion = declaring.cli
447
+ ? lockedVersion(
448
+ lockfile,
449
+ declaring.dir,
450
+ CLI_PACKAGE_NAME,
451
+ declaring.cli,
452
+ )
453
+ : null;
454
+ }
455
+ }
456
+ return {
457
+ inProject: Boolean(core || cli || declaring),
458
+ core,
459
+ cli,
460
+ declaringDir: declaring?.dir ?? null,
461
+ declaredCoreRange: declaring?.core ?? null,
462
+ declaredCliRange: declaring?.cli ?? null,
463
+ lockedCoreVersion,
464
+ lockedCliVersion,
465
+ };
466
+ }