@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,33 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Whether a folder is outside a project (spec AST-081 FR3).
5
+ *
6
+ * A folder is inside a project when the CLI finds a Core or a CLI installed
7
+ * there or above it, or a package.json above it that declares either one; the
8
+ * release choice already worked that out (foundation/release/run-context.mjs).
9
+ * Outside a project, output never gives advice that works only inside one, such
10
+ * as the setup reminder, the getting-started steps, or a step that adds a theme
11
+ * to an app; each surface that prints such a step asks here first.
12
+ *
13
+ * @input a folder
14
+ * @output whether it is outside a project
15
+ * @position foundation/env — read by the setup reminder, init, doctor, upgrade,
16
+ * and the theme, search, discover, and integration-check surfaces.
17
+ */
18
+
19
+ import {runChoice} from '../release/run-context.mjs';
20
+
21
+ /**
22
+ * True when `cwd` is outside any project.
23
+ * @param {string} [cwd]
24
+ * @returns {boolean}
25
+ */
26
+ export function isOutsideProject(cwd = process.cwd()) {
27
+ try {
28
+ return !runChoice(cwd).inProject;
29
+ } catch {
30
+ // A folder the release choice cannot read keeps its in-project output.
31
+ return false;
32
+ }
33
+ }
@@ -0,0 +1,42 @@
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
+ * The Astryx CLI package an executable starts, or null.
6
+ * @param {string} file
7
+ * @returns {string | null}
8
+ */
9
+ export function astryxCliRootOf(file: string): string | null;
10
+ /**
11
+ * Every `astryx` command on the search path, in the order a shell tries
12
+ * them. The first row is the one that runs.
13
+ * @param {{searchPath?: string, platform?: NodeJS.Platform}} [options]
14
+ * @returns {SearchPathCommand[]}
15
+ */
16
+ export function astryxCommandsOnSearchPath({ searchPath, platform, }?: {
17
+ searchPath?: string;
18
+ platform?: NodeJS.Platform;
19
+ }): SearchPathCommand[];
20
+ export type SearchPathCommand = {
21
+ /**
22
+ * the command as the shell finds it
23
+ */
24
+ file: string;
25
+ /**
26
+ * whether it starts the Astryx CLI
27
+ */
28
+ astryx: boolean;
29
+ /**
30
+ * the CLI package it starts, when known
31
+ */
32
+ cliRoot: string | null;
33
+ /**
34
+ * that package's version, when known
35
+ */
36
+ version: string | null;
37
+ /**
38
+ * whether that release hands a project's
39
+ * run to the project's release (spec AST-081 FR9); `null` when unknown
40
+ */
41
+ handsOff: boolean | null;
42
+ };
@@ -0,0 +1,205 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file The `astryx` commands on the computer's search path (spec AST-081
5
+ * FR10, FR11): which program each one starts, in the order a shell tries
6
+ * them, so `doctor`, `init --user`, and the update notices can tell the Astryx CLI
7
+ * apart from another program and a release that predates the hand-off from
8
+ * one that hands a project's run to the project's release.
9
+ *
10
+ * A command belongs to the Astryx CLI when its real file sits in the CLI
11
+ * package (npm and Bun link it), or when it is a package manager's small shim
12
+ * script that starts the CLI package's bin (npm on Windows, pnpm, Yarn); the
13
+ * package folder is read from the shim's text.
14
+ *
15
+ * @input the search path and, on Windows, its executable names
16
+ * @output one row per `astryx` command found
17
+ * @position packages/cli/foundation/env — read by doctor, init --user, and
18
+ * the update notices.
19
+ */
20
+
21
+ import * as fs from 'node:fs';
22
+ import * as path from 'node:path';
23
+
24
+ /** The CLI package whose bin the `astryx` command starts. */
25
+ const CLI_PACKAGE = '@astryxdesign/cli';
26
+
27
+ /** The bare command name. */
28
+ const COMMAND = 'astryx';
29
+
30
+ /** Shims are small; anything larger is a program, not a shim. */
31
+ const MAX_SHIM_BYTES = 64 * 1024;
32
+
33
+ /**
34
+ * A CLI package folder named in a shim's text, with the shim's own folder
35
+ * written as `$basedir` (sh), `%~dp0` or `%dp0%` (cmd), or `$PSScriptRoot`
36
+ * (PowerShell).
37
+ */
38
+ const SHIM_PACKAGE =
39
+ /((?:\$basedir(?:_abs|_win)?|%~dp0|%dp0%|\$PSScriptRoot)?[^"'\s:;$%]*node_modules[\\/]@astryxdesign[\\/]cli)(?=[\\/"'])/gu;
40
+
41
+ /** The shim folder written in a shim's text, in each shell's spelling. */
42
+ const SHIM_BASE =
43
+ /^(?:\$basedir(?:_abs|_win)?|%~dp0|%dp0%|\$PSScriptRoot)[\\/]?/u;
44
+
45
+ /**
46
+ * The absolute target some package managers record in a shim's comment
47
+ * (`# cmd-shim-target=<file>`).
48
+ */
49
+ const SHIM_TARGET_LINE = /^\s*(?:#|@?rem|::)\s*cmd-shim-target=(.+?)\s*$/imu;
50
+
51
+ /**
52
+ * @typedef {object} SearchPathCommand
53
+ * @property {string} file the command as the shell finds it
54
+ * @property {boolean} astryx whether it starts the Astryx CLI
55
+ * @property {string | null} cliRoot the CLI package it starts, when known
56
+ * @property {string | null} version that package's version, when known
57
+ * @property {boolean | null} handsOff whether that release hands a project's
58
+ * run to the project's release (spec AST-081 FR9); `null` when unknown
59
+ */
60
+
61
+ /**
62
+ * The CLI package's version, when `dir` is the Astryx CLI package.
63
+ * @param {string} dir
64
+ * @returns {string | null}
65
+ */
66
+ function cliVersionAt(dir) {
67
+ try {
68
+ const pkg = JSON.parse(
69
+ fs.readFileSync(path.join(dir, 'package.json'), 'utf8'),
70
+ );
71
+ return pkg?.name === CLI_PACKAGE ? String(pkg.version ?? '') : null;
72
+ } catch {
73
+ return null;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Releases that hand off carry the release-choice module.
79
+ * @param {string} dir
80
+ * @returns {boolean}
81
+ */
82
+ function handsOffAt(dir) {
83
+ return fs.existsSync(path.join(dir, 'foundation', 'release', 'choose.mjs'));
84
+ }
85
+
86
+ /**
87
+ * The Astryx CLI package an executable starts, or null.
88
+ * @param {string} file
89
+ * @returns {string | null}
90
+ */
91
+ export function astryxCliRootOf(file) {
92
+ let real;
93
+ try {
94
+ real = fs.realpathSync(file);
95
+ } catch {
96
+ return null;
97
+ }
98
+ for (let dir = path.dirname(real); ;) {
99
+ if (cliVersionAt(dir) !== null) return dir;
100
+ const parent = path.dirname(dir);
101
+ if (parent === dir) break;
102
+ dir = parent;
103
+ }
104
+ let text;
105
+ try {
106
+ if (fs.statSync(real).size > MAX_SHIM_BYTES) return null;
107
+ text = fs.readFileSync(real, 'utf8');
108
+ } catch {
109
+ return null;
110
+ }
111
+ const base = path.dirname(file);
112
+ const target = SHIM_TARGET_LINE.exec(text)?.[1];
113
+ if (target && path.isAbsolute(target)) {
114
+ for (let dir = path.dirname(target); ;) {
115
+ if (cliVersionAt(dir) !== null) return dir;
116
+ const parent = path.dirname(dir);
117
+ if (parent === dir) break;
118
+ dir = parent;
119
+ }
120
+ }
121
+ for (const match of text.matchAll(SHIM_PACKAGE)) {
122
+ const named = match[1]
123
+ .replace(SHIM_BASE, `${base}${path.sep}`)
124
+ .replace(/[\\/]/gu, path.sep);
125
+ const dir = path.resolve(base, named);
126
+ if (cliVersionAt(dir) !== null) return dir;
127
+ }
128
+ return null;
129
+ }
130
+
131
+ /**
132
+ * Whether a small script names the CLI package's files, even when that
133
+ * package cannot be read from here.
134
+ * @param {string} file
135
+ * @returns {boolean}
136
+ */
137
+ function namesCliPackage(file) {
138
+ try {
139
+ const real = fs.realpathSync(file);
140
+ if (fs.statSync(real).size > MAX_SHIM_BYTES) return false;
141
+ return /node_modules[\\/]@astryxdesign[\\/]cli[\\/]/u.test(
142
+ fs.readFileSync(real, 'utf8'),
143
+ );
144
+ } catch {
145
+ return false;
146
+ }
147
+ }
148
+
149
+ /**
150
+ * Every `astryx` command on the search path, in the order a shell tries
151
+ * them. The first row is the one that runs.
152
+ * @param {{searchPath?: string, platform?: NodeJS.Platform}} [options]
153
+ * @returns {SearchPathCommand[]}
154
+ */
155
+ export function astryxCommandsOnSearchPath({
156
+ searchPath = process.env.PATH ?? process.env.Path ?? '',
157
+ platform = process.platform,
158
+ } = {}) {
159
+ const windows = platform === 'win32';
160
+ const names = windows
161
+ ? ['astryx.cmd', 'astryx.exe', 'astryx.ps1', 'astryx']
162
+ : [COMMAND];
163
+ /** @type {SearchPathCommand[]} */
164
+ const rows = [];
165
+ const seen = new Set();
166
+ for (const dir of searchPath.split(windows ? ';' : path.delimiter)) {
167
+ if (!dir) continue;
168
+ for (const name of names) {
169
+ const file = path.join(dir, name);
170
+ let stat;
171
+ try {
172
+ stat = fs.statSync(file);
173
+ } catch {
174
+ continue;
175
+ }
176
+ if (!stat.isFile()) continue;
177
+ if (!windows) {
178
+ try {
179
+ fs.accessSync(file, fs.constants.X_OK);
180
+ } catch {
181
+ continue;
182
+ }
183
+ }
184
+ let key = file;
185
+ try {
186
+ key = fs.realpathSync(file);
187
+ } catch {
188
+ // Keep the path as found.
189
+ }
190
+ if (seen.has(key)) break;
191
+ seen.add(key);
192
+ const cliRoot = astryxCliRootOf(file);
193
+ rows.push({
194
+ file,
195
+ astryx: cliRoot !== null || namesCliPackage(file),
196
+ cliRoot,
197
+ version: cliRoot ? cliVersionAt(cliRoot) : null,
198
+ handsOff: cliRoot ? handsOffAt(cliRoot) : null,
199
+ });
200
+ // One command per folder: the shell runs the first name it finds.
201
+ break;
202
+ }
203
+ }
204
+ return rows;
205
+ }
@@ -0,0 +1,122 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Reading the `astryx` commands on the search path (spec AST-081
5
+ * FR11): links, and each package manager's shim, down to the CLI package and
6
+ * its version.
7
+ */
8
+
9
+ import {afterEach, describe, expect, it} from 'vitest';
10
+ import * as fs from 'node:fs';
11
+ import * as path from 'node:path';
12
+ import {astryxCommandsOnSearchPath, astryxCliRootOf} from './search-path.mjs';
13
+ import {
14
+ cleanupFixtures,
15
+ tempDir,
16
+ writeJson,
17
+ } from '../../test-utils/release-fixtures.mjs';
18
+
19
+ afterEach(cleanupFixtures);
20
+
21
+ /**
22
+ * A CLI package at `dir`, with or without the hand-off.
23
+ * @param {string} dir
24
+ * @param {string} version
25
+ * @param {boolean} [handsOff]
26
+ */
27
+ function cliPackage(dir, version, handsOff = false) {
28
+ writeJson(path.join(dir, 'package.json'), {
29
+ name: '@astryxdesign/cli',
30
+ version,
31
+ });
32
+ if (handsOff) {
33
+ fs.mkdirSync(path.join(dir, 'foundation', 'release'), {recursive: true});
34
+ fs.writeFileSync(path.join(dir, 'foundation', 'release', 'choose.mjs'), '');
35
+ }
36
+ return dir;
37
+ }
38
+
39
+ /**
40
+ * An executable shim at `file` with `text`.
41
+ * @param {string} file
42
+ * @param {string} text
43
+ */
44
+ function shim(file, text) {
45
+ fs.mkdirSync(path.dirname(file), {recursive: true});
46
+ fs.writeFileSync(file, text);
47
+ fs.chmodSync(file, 0o755);
48
+ return file;
49
+ }
50
+
51
+ describe.skipIf(process.platform === 'win32')('astryxCliRootOf', () => {
52
+ it('reads a pnpm 10 shim ($basedir)', () => {
53
+ const home = tempDir('pnpm');
54
+ const pkg = cliPackage(
55
+ path.join(home, 'global', '5', 'node_modules', '@astryxdesign', 'cli'),
56
+ '0.6.8',
57
+ );
58
+ const bin = shim(
59
+ path.join(home, 'astryx'),
60
+ '#!/bin/sh\nbasedir=$(dirname "$0")\nexec node "$basedir/global/5/node_modules/@astryxdesign/cli/clients/cli/bin/astryx.mjs" "$@"\n',
61
+ );
62
+ expect(astryxCliRootOf(bin)).toBe(pkg);
63
+ });
64
+
65
+ it('reads a pnpm 12 shim ($basedir_abs, a folder above the shim)', () => {
66
+ const home = tempDir('pnpm12');
67
+ const pkg = cliPackage(
68
+ path.join(
69
+ home,
70
+ 'global',
71
+ 'v11',
72
+ '3f2a',
73
+ 'node_modules',
74
+ '@astryxdesign',
75
+ 'cli',
76
+ ),
77
+ '0.6.8',
78
+ );
79
+ const bin = shim(
80
+ path.join(home, 'bin', 'astryx'),
81
+ [
82
+ '#!/bin/sh',
83
+ 'basedir=$(dirname "$(echo "$0" | sed -e \'s,\\\\,/,g\')")',
84
+ 'basedir_abs=$(cd "$basedir" && pwd)',
85
+ 'exec node "$basedir_abs/../global/v11/3f2a/node_modules/@astryxdesign/cli/clients/cli/bin/astryx.mjs" "$@"',
86
+ '',
87
+ ].join('\n'),
88
+ );
89
+ expect(astryxCliRootOf(bin)).toBe(pkg);
90
+ const [row] = astryxCommandsOnSearchPath({
91
+ searchPath: path.dirname(bin),
92
+ platform: 'linux',
93
+ });
94
+ expect(row).toEqual({
95
+ file: bin,
96
+ astryx: true,
97
+ cliRoot: pkg,
98
+ version: '0.6.8',
99
+ handsOff: false,
100
+ });
101
+ });
102
+
103
+ it('reads a cmd-shim-target comment with an absolute target', () => {
104
+ const elsewhere = tempDir('target');
105
+ const pkg = cliPackage(
106
+ path.join(elsewhere, 'node_modules', '@astryxdesign', 'cli'),
107
+ '0.8.0',
108
+ true,
109
+ );
110
+ const bin = shim(
111
+ path.join(tempDir('bin'), 'astryx'),
112
+ `#!/bin/sh\n# cmd-shim-target=${path.join(pkg, 'clients', 'cli', 'bin', 'astryx.mjs')}\nexec node "$TARGET" "$@"\n`,
113
+ );
114
+ expect(astryxCliRootOf(bin)).toBe(pkg);
115
+ expect(
116
+ astryxCommandsOnSearchPath({
117
+ searchPath: path.dirname(bin),
118
+ platform: 'linux',
119
+ })[0],
120
+ ).toMatchObject({version: '0.8.0', handsOff: true});
121
+ });
122
+ });
@@ -0,0 +1,39 @@
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 environment folder setting, when it names an absolute path.
6
+ * @param {string | undefined} value
7
+ * @returns {string | null}
8
+ */
9
+ export function absoluteDirSetting(value: string | undefined): string | null;
10
+ /**
11
+ * @typedef {object} UserDirOptions
12
+ * @property {string} [home] the home folder; defaults to the current user's
13
+ * @property {NodeJS.Platform} [platform]
14
+ * @property {Record<string, string | undefined>} [env]
15
+ */
16
+ /**
17
+ * The CLI's per-user cache folder: `~/.cache/astryx` on Linux (or
18
+ * `$XDG_CACHE_HOME/astryx`), `~/Library/Caches/astryx` on macOS, and
19
+ * `%LOCALAPPDATA%\astryx\Cache` on Windows.
20
+ * @param {UserDirOptions} [options]
21
+ * @returns {string}
22
+ */
23
+ export function userCacheDir({ home, platform, env, }?: UserDirOptions): string;
24
+ /**
25
+ * The CLI's per-user configuration folder: `~/.config/astryx` on Linux (or
26
+ * `$XDG_CONFIG_HOME/astryx`), `~/Library/Application Support/astryx` on
27
+ * macOS, and `%APPDATA%\astryx` on Windows.
28
+ * @param {UserDirOptions} [options]
29
+ * @returns {string}
30
+ */
31
+ export function userConfigDir({ home, platform, env, }?: UserDirOptions): string;
32
+ export type UserDirOptions = {
33
+ /**
34
+ * the home folder; defaults to the current user's
35
+ */
36
+ home?: string | undefined;
37
+ platform?: NodeJS.Platform | undefined;
38
+ env?: Record<string, string | undefined> | undefined;
39
+ };
@@ -0,0 +1,93 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file The per-user folders the CLI may write to (spec AST-081 FR7): the
5
+ * platform's cache directory and its configuration directory, each with an
6
+ * `astryx` folder of its own.
7
+ *
8
+ * A folder named by the platform's own environment setting
9
+ * (`XDG_CACHE_HOME`, `XDG_CONFIG_HOME`, `LOCALAPPDATA`, `APPDATA`) is used
10
+ * only when it is an absolute path; a relative one is ignored, as the XDG
11
+ * base directory rules require, so a run never writes into the folder it
12
+ * starts in.
13
+ *
14
+ * @input the home folder, the platform, and those standard settings
15
+ * @output absolute folder paths
16
+ * @position packages/cli/foundation/env
17
+ */
18
+
19
+ import * as os from 'node:os';
20
+ import * as path from 'node:path';
21
+
22
+ /**
23
+ * An environment folder setting, when it names an absolute path.
24
+ * @param {string | undefined} value
25
+ * @returns {string | null}
26
+ */
27
+ export function absoluteDirSetting(value) {
28
+ return typeof value === 'string' && value !== '' && path.isAbsolute(value)
29
+ ? value
30
+ : null;
31
+ }
32
+
33
+ /**
34
+ * @typedef {object} UserDirOptions
35
+ * @property {string} [home] the home folder; defaults to the current user's
36
+ * @property {NodeJS.Platform} [platform]
37
+ * @property {Record<string, string | undefined>} [env]
38
+ */
39
+
40
+ /**
41
+ * The CLI's per-user cache folder: `~/.cache/astryx` on Linux (or
42
+ * `$XDG_CACHE_HOME/astryx`), `~/Library/Caches/astryx` on macOS, and
43
+ * `%LOCALAPPDATA%\astryx\Cache` on Windows.
44
+ * @param {UserDirOptions} [options]
45
+ * @returns {string}
46
+ */
47
+ export function userCacheDir({
48
+ home = os.homedir(),
49
+ platform = process.platform,
50
+ env = process.env,
51
+ } = {}) {
52
+ const join = platform === 'win32' ? path.win32.join : path.join;
53
+ if (platform === 'win32') {
54
+ return join(
55
+ absoluteDirSetting(env.LOCALAPPDATA) ?? join(home, 'AppData', 'Local'),
56
+ 'astryx',
57
+ 'Cache',
58
+ );
59
+ }
60
+ if (platform === 'darwin') return join(home, 'Library', 'Caches', 'astryx');
61
+ return join(
62
+ absoluteDirSetting(env.XDG_CACHE_HOME) ?? join(home, '.cache'),
63
+ 'astryx',
64
+ );
65
+ }
66
+
67
+ /**
68
+ * The CLI's per-user configuration folder: `~/.config/astryx` on Linux (or
69
+ * `$XDG_CONFIG_HOME/astryx`), `~/Library/Application Support/astryx` on
70
+ * macOS, and `%APPDATA%\astryx` on Windows.
71
+ * @param {UserDirOptions} [options]
72
+ * @returns {string}
73
+ */
74
+ export function userConfigDir({
75
+ home = os.homedir(),
76
+ platform = process.platform,
77
+ env = process.env,
78
+ } = {}) {
79
+ const join = platform === 'win32' ? path.win32.join : path.join;
80
+ if (platform === 'win32') {
81
+ return join(
82
+ absoluteDirSetting(env.APPDATA) ?? join(home, 'AppData', 'Roaming'),
83
+ 'astryx',
84
+ );
85
+ }
86
+ if (platform === 'darwin') {
87
+ return join(home, 'Library', 'Application Support', 'astryx');
88
+ }
89
+ return join(
90
+ absoluteDirSetting(env.XDG_CONFIG_HOME) ?? join(home, '.config'),
91
+ 'astryx',
92
+ );
93
+ }
@@ -0,0 +1,72 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ import * as path from 'node:path';
4
+ import {describe, expect, it} from 'vitest';
5
+ import {absoluteDirSetting, userCacheDir, userConfigDir} from './user-dirs.mjs';
6
+
7
+ const home = path.join(path.sep, 'home', 'ada');
8
+
9
+ describe('per-user folders (spec AST-081 FR7)', () => {
10
+ it('uses the platform defaults', () => {
11
+ expect(userCacheDir({home, platform: 'linux', env: {}})).toBe(
12
+ path.join(home, '.cache', 'astryx'),
13
+ );
14
+ expect(userConfigDir({home, platform: 'linux', env: {}})).toBe(
15
+ path.join(home, '.config', 'astryx'),
16
+ );
17
+ expect(userCacheDir({home, platform: 'darwin', env: {}})).toBe(
18
+ path.join(home, 'Library', 'Caches', 'astryx'),
19
+ );
20
+ expect(userConfigDir({home, platform: 'darwin', env: {}})).toBe(
21
+ path.join(home, 'Library', 'Application Support', 'astryx'),
22
+ );
23
+ });
24
+
25
+ it('uses an absolute XDG setting and ignores a relative or empty one', () => {
26
+ const xdg = path.join(path.sep, 'xdg');
27
+ expect(
28
+ userCacheDir({home, platform: 'linux', env: {XDG_CACHE_HOME: xdg}}),
29
+ ).toBe(path.join(xdg, 'astryx'));
30
+ expect(
31
+ userConfigDir({home, platform: 'linux', env: {XDG_CONFIG_HOME: xdg}}),
32
+ ).toBe(path.join(xdg, 'astryx'));
33
+ for (const value of ['rel-cache', './cache', '']) {
34
+ expect(
35
+ userCacheDir({home, platform: 'linux', env: {XDG_CACHE_HOME: value}}),
36
+ ).toBe(path.join(home, '.cache', 'astryx'));
37
+ expect(
38
+ userConfigDir({home, platform: 'linux', env: {XDG_CONFIG_HOME: value}}),
39
+ ).toBe(path.join(home, '.config', 'astryx'));
40
+ }
41
+ });
42
+
43
+ it.skipIf(process.platform !== 'win32')(
44
+ 'uses LOCALAPPDATA and APPDATA on Windows only when absolute',
45
+ () => {
46
+ const winHome = 'C:\\Users\\ada';
47
+ expect(
48
+ userCacheDir({
49
+ home: winHome,
50
+ platform: 'win32',
51
+ env: {LOCALAPPDATA: 'D:\\Local'},
52
+ }),
53
+ ).toBe('D:\\Local\\astryx\\Cache');
54
+ expect(
55
+ userConfigDir({
56
+ home: winHome,
57
+ platform: 'win32',
58
+ env: {APPDATA: 'Roaming'},
59
+ }),
60
+ ).toBe('C:\\Users\\ada\\AppData\\Roaming\\astryx');
61
+ },
62
+ );
63
+
64
+ it('reads only absolute folder settings', () => {
65
+ expect(absoluteDirSetting(undefined)).toBeNull();
66
+ expect(absoluteDirSetting('')).toBeNull();
67
+ expect(absoluteDirSetting('cache')).toBeNull();
68
+ expect(absoluteDirSetting(path.resolve('cache'))).toBe(
69
+ path.resolve('cache'),
70
+ );
71
+ });
72
+ });
@@ -0,0 +1,46 @@
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
+ * @typedef {object} ComputerAgentTextSettings
6
+ * @property {boolean} install Whether the computer-level text is wanted.
7
+ * @property {string[]} links The links to its skill folder Astryx made, so
8
+ * removal removes exactly those.
9
+ */
10
+ /**
11
+ * The settings file's path.
12
+ * @param {string} [configDir]
13
+ * @returns {string}
14
+ */
15
+ export function settingsFile(configDir?: string): string;
16
+ /**
17
+ * The whole settings object; `{}` when the file is missing or unreadable.
18
+ * @param {string} [configDir]
19
+ * @returns {Record<string, unknown>}
20
+ */
21
+ export function readSettings(configDir?: string): Record<string, unknown>;
22
+ /**
23
+ * The person's choices about the computer-level agent text.
24
+ * @param {string} [configDir]
25
+ * @returns {ComputerAgentTextSettings}
26
+ */
27
+ export function computerAgentTextSettings(configDir?: string): ComputerAgentTextSettings;
28
+ /**
29
+ * Record the person's choices about the computer-level agent text, keeping
30
+ * every other setting. Returns whether the file was written.
31
+ * @param {ComputerAgentTextSettings} choice
32
+ * @param {string} [configDir]
33
+ * @returns {boolean}
34
+ */
35
+ export function recordComputerAgentTextSettings(choice: ComputerAgentTextSettings, configDir?: string): boolean;
36
+ export type ComputerAgentTextSettings = {
37
+ /**
38
+ * Whether the computer-level text is wanted.
39
+ */
40
+ install: boolean;
41
+ /**
42
+ * The links to its skill folder Astryx made, so
43
+ * removal removes exactly those.
44
+ */
45
+ links: string[];
46
+ };