@astryxdesign/cli 0.6.4 → 0.6.5-canary.031021b

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 (288) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +97 -90
  3. package/api/build/build.doc.mjs +6 -1
  4. package/api/build/build.test.mjs +22 -0
  5. package/api/build/kit/kit.mjs +44 -5
  6. package/api/component/_adapter.d.mts +25 -0
  7. package/api/component/_adapter.mjs +59 -5
  8. package/api/component/component.d.mts +6 -3
  9. package/api/component/component.doc.mjs +37 -17
  10. package/api/component/component.mjs +249 -9
  11. package/api/component/component.type.d.mts +25 -0
  12. package/api/component/component.type.mjs +44 -0
  13. package/api/discover/_adapter.d.mts +114 -6
  14. package/api/discover/_adapter.mjs +372 -17
  15. package/api/discover/_adapter.test.mjs +215 -0
  16. package/api/discover/_catalog-view.d.mts +115 -0
  17. package/api/discover/_catalog-view.mjs +203 -0
  18. package/api/discover/_catalog-view.test.mjs +128 -0
  19. package/api/discover/detail/detail.d.mts +18 -6
  20. package/api/discover/detail/detail.mjs +67 -13
  21. package/api/discover/detail/detail.test.mjs +85 -0
  22. package/api/discover/detail/item/item.d.mts +26 -0
  23. package/api/discover/detail/item/item.mjs +78 -0
  24. package/api/discover/detail/item/item.test.mjs +73 -0
  25. package/api/discover/discover.d.mts +3 -9
  26. package/api/discover/discover.doc.mjs +61 -18
  27. package/api/discover/discover.mjs +220 -36
  28. package/api/discover/discover.test.mjs +11 -2
  29. package/api/discover/discover.type.d.mts +147 -8
  30. package/api/discover/discover.type.mjs +102 -12
  31. package/api/discover/list/list.d.mts +20 -6
  32. package/api/discover/list/list.mjs +45 -12
  33. package/api/discover/list/list.test.mjs +46 -0
  34. package/api/discover/search/search.d.mts +18 -16
  35. package/api/discover/search/search.mjs +102 -56
  36. package/api/discover/search/search.test.mjs +144 -10
  37. package/api/docs/_adapter.d.mts +8 -3
  38. package/api/docs/_adapter.mjs +14 -6
  39. package/api/docs/docOverlays.test.mjs +27 -1
  40. package/api/docs/docs.doc.mjs +2 -2
  41. package/api/doctor/doctor.d.mts +8 -3
  42. package/api/doctor/doctor.doc.mjs +17 -8
  43. package/api/doctor/doctor.mjs +90 -9
  44. package/api/doctor/doctor.test.mjs +122 -10
  45. package/api/doctor/doctor.type.d.mts +1 -1
  46. package/api/doctor/doctor.type.mjs +1 -1
  47. package/api/gap-report/gap-report.doc.mjs +19 -10
  48. package/api/hook/hook.doc.mjs +6 -3
  49. package/api/index.d.mts +1 -0
  50. package/api/index.mjs +5 -3
  51. package/api/init/init.doc.mjs +17 -12
  52. package/api/integration/add-helpers.d.mts +5 -2
  53. package/api/integration/add-helpers.mjs +36 -9
  54. package/api/integration/add-theme.mjs +22 -1
  55. package/api/integration/add-theme.test.mjs +34 -0
  56. package/api/integration/authoring-checks.mjs +2 -2
  57. package/api/integration/integrationPackCheck.doc.mjs +3 -3
  58. package/api/integration/pack-check.lifecycle-output.test.mjs +107 -0
  59. package/api/integration/pack-check.mjs +82 -9
  60. package/api/integration/pack-check.test.mjs +90 -0
  61. package/api/integration/pack-check.type.mjs +1 -1
  62. package/api/json/assertResponse.doc.mjs +1 -1
  63. package/api/json/isError.doc.mjs +1 -1
  64. package/api/search/search.d.mts +27 -1
  65. package/api/search/search.doc.mjs +2 -2
  66. package/api/search/search.mjs +228 -16
  67. package/api/swizzle/swizzle.doc.mjs +7 -5
  68. package/api/template/copy/copy.mjs +1 -1
  69. package/api/template/copy/copy.test.mjs +9 -0
  70. package/api/template/template.doc.mjs +2 -1
  71. package/api/theme/add/add.mjs +17 -25
  72. package/api/theme/add/add.rollback.test.mjs +158 -0
  73. package/api/theme/add/add.staging.test.mjs +40 -23
  74. package/api/theme/build/build.family.test.mjs +7 -12
  75. package/api/theme/build/build.mjs +8 -18
  76. package/api/theme/build/build.rollback.test.mjs +148 -0
  77. package/api/theme/generateTonalPalette.doc.mjs +1 -2
  78. package/api/theme/listThemes.doc.mjs +1 -1
  79. package/api/theme/themeAdd.doc.mjs +9 -10
  80. package/api/theme/themeBuild.doc.mjs +13 -13
  81. package/api/theme/themeList.doc.mjs +1 -1
  82. package/api/theme/themeListAvailable.doc.mjs +2 -1
  83. package/api/theme/themePaletteGenerate.doc.mjs +15 -8
  84. package/api/theme/themeTargets.doc.mjs +3 -2
  85. package/api/theme/themeTemplate.doc.mjs +2 -1
  86. package/api/upgrade/run/files-changed.test.mjs +111 -0
  87. package/api/upgrade/run/run.mjs +5 -3
  88. package/api/upgrade/upgrade.doc.mjs +24 -22
  89. package/api/upgrade/upgrade.type.mjs +2 -2
  90. package/assets/codemods/__tests__/runner.test.mjs +3 -1
  91. package/assets/codemods/file-count.test.mjs +163 -0
  92. package/assets/codemods/integration-runner.mjs +3 -3
  93. package/assets/codemods/runner.mjs +5 -4
  94. package/assets/docs/README.md +4 -2
  95. package/assets/docs/browser-support.doc.mjs +11 -11
  96. package/assets/docs/color.doc.mjs +8 -2
  97. package/assets/docs/elevation.doc.mjs +6 -4
  98. package/assets/docs/getting-started.doc.mjs +5 -16
  99. package/assets/docs/icons.doc.mjs +2 -21
  100. package/assets/docs/illustrations.doc.mjs +7 -15
  101. package/assets/docs/internationalization.doc.mjs +7 -5
  102. package/assets/docs/layout.doc.dense.mjs +130 -82
  103. package/assets/docs/layout.doc.mjs +133 -77
  104. package/assets/docs/migration.doc.mjs +19 -21
  105. package/assets/docs/motion.doc.mjs +16 -3
  106. package/assets/docs/principles.doc.dense.mjs +5 -5
  107. package/assets/docs/principles.doc.mjs +8 -0
  108. package/assets/docs/principles.doc.zh.mjs +6 -6
  109. package/assets/docs/shape.doc.mjs +8 -3
  110. package/assets/docs/spacing.doc.mjs +7 -2
  111. package/assets/docs/styling-libraries.doc.mjs +6 -2
  112. package/assets/docs/styling.doc.mjs +19 -23
  113. package/assets/docs/theme.doc.dense.mjs +58 -18
  114. package/assets/docs/theme.doc.mjs +57 -47
  115. package/assets/docs/theme.doc.zh.mjs +9 -8
  116. package/assets/docs/tokens.doc.dense.mjs +2 -2
  117. package/assets/docs/tokens.doc.mjs +389 -8
  118. package/assets/docs/tokens.doc.zh.mjs +2 -2
  119. package/assets/docs/tree/add-a-component.doc.mjs +75 -0
  120. package/assets/docs/tree/add-a-theme.doc.mjs +85 -0
  121. package/assets/docs/tree/add-a-topic.doc.mjs +144 -0
  122. package/assets/docs/tree/agent-guidance.doc.mjs +138 -0
  123. package/assets/docs/tree/block-template.doc.mjs +130 -0
  124. package/assets/docs/tree/build-the-template.doc.mjs +28 -0
  125. package/assets/docs/tree/building-blocks.doc.mjs +46 -0
  126. package/assets/docs/tree/check-your-docs.doc.mjs +137 -0
  127. package/assets/docs/tree/checks.doc.mjs +119 -0
  128. package/assets/docs/tree/codemods.doc.mjs +147 -0
  129. package/assets/docs/tree/component-family.doc.mjs +113 -0
  130. package/assets/docs/tree/component-imports.doc.mjs +69 -0
  131. package/assets/docs/tree/component-lookups.doc.mjs +149 -0
  132. package/assets/docs/tree/components.doc.mjs +23 -0
  133. package/assets/docs/tree/configuration.doc.mjs +23 -0
  134. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +182 -0
  135. package/assets/docs/tree/define-the-theme.doc.mjs +118 -0
  136. package/assets/docs/tree/describe-the-component.doc.mjs +57 -0
  137. package/assets/docs/tree/docs.doc.mjs +21 -0
  138. package/assets/docs/tree/document-the-template.doc.mjs +28 -0
  139. package/assets/docs/tree/document-the-theme.doc.mjs +68 -0
  140. package/assets/docs/tree/export-template-assets.doc.mjs +147 -0
  141. package/assets/docs/tree/extend-or-replace.doc.mjs +103 -0
  142. package/assets/docs/tree/fonts-and-assets.doc.mjs +106 -0
  143. package/assets/docs/tree/generate-a-palette.doc.mjs +66 -0
  144. package/assets/docs/tree/grade-template-with-agent.doc.mjs +105 -0
  145. package/assets/docs/tree/help.doc.mjs +16 -0
  146. package/assets/docs/tree/integrations.doc.mjs +25 -451
  147. package/assets/docs/tree/links.doc.mjs +98 -0
  148. package/assets/docs/tree/package-and-test.doc.mjs +32 -0
  149. package/assets/docs/tree/page-template.doc.mjs +71 -0
  150. package/assets/docs/tree/publishing.doc.mjs +111 -0
  151. package/assets/docs/tree/quick-start.doc.mjs +272 -0
  152. package/assets/docs/tree/replace-a-core-component.doc.mjs +104 -0
  153. package/assets/docs/tree/replace-a-core-template.doc.mjs +172 -0
  154. package/assets/docs/tree/sections-and-placement.doc.mjs +108 -0
  155. package/assets/docs/tree/see-it-in-an-app.doc.mjs +59 -0
  156. package/assets/docs/tree/ship.doc.mjs +16 -0
  157. package/assets/docs/tree/short-and-findable.doc.mjs +108 -0
  158. package/assets/docs/tree/single-component.doc.mjs +165 -0
  159. package/assets/docs/tree/start-a-template.doc.mjs +143 -0
  160. package/assets/docs/tree/subcomponent.doc.mjs +115 -0
  161. package/assets/docs/tree/template-assets.doc.mjs +64 -0
  162. package/assets/docs/tree/template-doc-overview.doc.mjs +109 -0
  163. package/assets/docs/tree/template-fonts.doc.mjs +102 -0
  164. package/assets/docs/tree/template-grading-rubric.doc.mjs +452 -0
  165. package/assets/docs/tree/template-icons.doc.mjs +97 -0
  166. package/assets/docs/tree/template-images-media.doc.mjs +127 -0
  167. package/assets/docs/tree/template-styles.doc.mjs +93 -0
  168. package/assets/docs/tree/templates.doc.mjs +34 -0
  169. package/assets/docs/tree/test-in-an-app.doc.mjs +115 -0
  170. package/assets/docs/tree/test-template-in-app.doc.mjs +128 -0
  171. package/assets/docs/tree/themes.doc.mjs +39 -0
  172. package/assets/docs/tree/troubleshooting.doc.mjs +149 -0
  173. package/assets/docs/tree/upgrading.doc.mjs +103 -0
  174. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +51 -0
  175. package/assets/docs/tree/verify-packed-template.doc.mjs +77 -0
  176. package/assets/docs/tree/versioning.doc.mjs +161 -0
  177. package/assets/docs/tree/write-good-templates.doc.mjs +64 -0
  178. package/assets/docs/tree/write-the-template-file.doc.mjs +154 -0
  179. package/assets/docs/typography.doc.mjs +24 -4
  180. package/assets/docs/working-with-ai.doc.mjs +30 -22
  181. package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
  182. package/authoring/config/config.doc.mjs +9 -1
  183. package/authoring/config/parse.d.mts +2 -0
  184. package/authoring/config/parse.mjs +19 -0
  185. package/authoring/config/parse.test.mjs +8 -0
  186. package/authoring/config/type.ts +11 -0
  187. package/authoring/discover/discover.doc.d.mts +13 -0
  188. package/authoring/discover/discover.doc.mjs +138 -0
  189. package/authoring/discover/parse.d.mts +24 -0
  190. package/authoring/discover/parse.mjs +128 -0
  191. package/authoring/discover/parse.test.mjs +124 -0
  192. package/authoring/discover/type.ts +87 -0
  193. package/authoring/doctypes/_schema.d.mts +3 -2
  194. package/authoring/doctypes/_schema.mjs +6 -0
  195. package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
  196. package/authoring/doctypes/base/type.ts +4 -2
  197. package/authoring/doctypes/component/component.doc.mjs +6 -0
  198. package/authoring/doctypes/component/type.ts +8 -0
  199. package/authoring/doctypes/reference/reference.doc.mjs +7 -0
  200. package/authoring/doctypes/reference/type.ts +5 -0
  201. package/authoring/doctypes/schema/schema.doc.mjs +2 -2
  202. package/authoring/doctypes/template/template.doc.mjs +1 -1
  203. package/authoring/doctypes/template/type.ts +2 -2
  204. package/authoring/index.d.mts +1 -0
  205. package/authoring/index.d.ts +10 -0
  206. package/authoring/index.mjs +1 -0
  207. package/authoring/integration/integration.doc.mjs +12 -10
  208. package/clients/cli/commands/component/index.mjs +152 -55
  209. package/clients/cli/commands/component-batch.test.mjs +341 -0
  210. package/clients/cli/commands/component-ownership.test.mjs +89 -0
  211. package/clients/cli/commands/component.doc.mjs +27 -9
  212. package/clients/cli/commands/discover.doc.mjs +53 -9
  213. package/clients/cli/commands/discover.mjs +393 -118
  214. package/clients/cli/commands/discover.sources.test.mjs +267 -0
  215. package/clients/cli/commands/docs.doc.mjs +1 -1
  216. package/clients/cli/commands/docs.mjs +60 -17
  217. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -2
  218. package/clients/cli/commands/doctor-integration.test.mjs +53 -0
  219. package/clients/cli/commands/doctor.doc.mjs +3 -1
  220. package/clients/cli/commands/doctor.mjs +49 -5
  221. package/clients/cli/commands/gap-report.doc.mjs +10 -9
  222. package/clients/cli/commands/init.doc.mjs +9 -6
  223. package/clients/cli/commands/integration-add.doc.mjs +9 -9
  224. package/clients/cli/commands/integration-authoring.test.mjs +61 -10
  225. package/clients/cli/commands/integration-pack.doc.mjs +5 -9
  226. package/clients/cli/commands/integration-real-world.test.mjs +1 -1
  227. package/clients/cli/commands/integration-verify.doc.mjs +22 -0
  228. package/clients/cli/commands/integration.doc.mjs +4 -4
  229. package/clients/cli/commands/integration.mjs +74 -43
  230. package/clients/cli/commands/manifest.doc.mjs +1 -1
  231. package/clients/cli/commands/search.doc.mjs +10 -3
  232. package/clients/cli/commands/search.mjs +21 -2
  233. package/clients/cli/commands/search.test.mjs +21 -4
  234. package/clients/cli/commands/swizzle.doc.mjs +1 -1
  235. package/clients/cli/commands/template.doc.mjs +1 -1
  236. package/clients/cli/commands/text-json-parity.test.mjs +7 -1
  237. package/clients/cli/commands/theme-add.doc.mjs +1 -1
  238. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -2
  239. package/clients/cli/commands/theme-palette.doc.mjs +1 -2
  240. package/clients/cli/commands/theme-targets.doc.mjs +2 -2
  241. package/clients/cli/commands/theme.doc.mjs +2 -1
  242. package/clients/cli/commands/upgrade.doc.mjs +62 -3
  243. package/clients/cli/index.mjs +28 -6
  244. package/clients/cli/lib/define-command.mjs +28 -4
  245. package/clients/cli/lib/define-command.test.mjs +54 -0
  246. package/clients/cli/lib/exit-codes.test.mjs +17 -1
  247. package/clients/cli/lib/json-shim.mjs +24 -14
  248. package/clients/cli/lib/manifest.mjs +18 -5
  249. package/clients/cli/lib/manifest.test.mjs +5 -2
  250. package/clients/cli/lib/parse-error-format.test.mjs +81 -0
  251. package/foundation/agent-docs/agent-docs.mjs +1 -1
  252. package/foundation/discovery/authoring-self-docs.mjs +1 -0
  253. package/foundation/discovery/authoring-self-docs.test.mjs +6 -2
  254. package/foundation/discovery/cli-self-docs.mjs +16 -2
  255. package/foundation/discovery/cli-self-docs.test.mjs +20 -0
  256. package/foundation/discovery/docs-discovery.mjs +5 -1
  257. package/foundation/discovery/docs-discovery.test.mjs +21 -0
  258. package/foundation/discovery/docs-section-key.d.mts +1 -1
  259. package/foundation/discovery/docs-section-key.mjs +1 -1
  260. package/foundation/doc-compiler/doc-loads.test.mjs +3 -2
  261. package/foundation/doc-compiler/inputs.test.mjs +0 -1
  262. package/foundation/doc-compiler/tree.d.mts +4 -0
  263. package/foundation/doc-compiler/tree.mjs +6 -1
  264. package/foundation/integrations/cli-requirement.d.mts +26 -6
  265. package/foundation/integrations/cli-requirement.mjs +46 -11
  266. package/foundation/integrations/cli-requirement.test.mjs +7 -2
  267. package/foundation/integrations/contribution-inventory.mjs +1 -1
  268. package/foundation/integrations/integrations.d.mts +14 -1
  269. package/foundation/integrations/integrations.mjs +41 -1
  270. package/foundation/integrations/integrations.test.mjs +31 -0
  271. package/foundation/response/batch.type.d.mts +33 -0
  272. package/foundation/response/batch.type.mjs +34 -0
  273. package/foundation/response/error-codes.doc.mjs +6 -8
  274. package/foundation/response/error-codes.test.mjs +30 -5
  275. package/foundation/response/response-types.doc.d.mts +4 -3
  276. package/foundation/response/response-types.doc.mjs +40 -10
  277. package/foundation/response/response-types.doc.test.mjs +23 -0
  278. package/foundation/response/response.doc.mjs +11 -10
  279. package/package.json +9 -9
  280. package/api/docs/docs.test.mjs +0 -243
  281. package/api/docs/integration-tree.test.mjs +0 -555
  282. package/api/docs/integrationDocs.test.mjs +0 -314
  283. package/api/search/search.test.mjs +0 -512
  284. package/assets/docs/tree/integrations.test.mjs +0 -62
  285. package/assets/docs/tree/writing-docs.doc.mjs +0 -286
  286. package/clients/cli/commands/docs.test.mjs +0 -294
  287. package/foundation/agent-docs/agent-docs.test.mjs +0 -1159
  288. package/foundation/doc-compiler/tree.test.mjs +0 -598
@@ -8,6 +8,7 @@ export const docs = {
8
8
  category: 'guide',
9
9
  description:
10
10
  'How to set up AI coding tools to generate correct component code.',
11
+ keywords: ['claude', 'cursor', 'codex', 'copilot', 'agents', 'mcp'],
11
12
 
12
13
  sections: [
13
14
  {
@@ -24,7 +25,8 @@ export const docs = {
24
25
  ],
25
26
  },
26
27
  {
27
- title: 'Quick Start',
28
+ id: 'quick-start',
29
+ title: 'Set up agent docs',
28
30
  content: [
29
31
  {
30
32
  type: 'prose',
@@ -38,7 +40,7 @@ export const docs = {
38
40
  },
39
41
  {
40
42
  type: 'prose',
41
- text: "That's it. The `init --features agents` command generates everything your AI needs (component index, behavioral rules, CLI reference, and package guidance from configured integrations) from the installed project. After a dependency bump, `astryx upgrade` reports a stale block and `astryx upgrade --apply` refreshes it.",
43
+ text: "That's it. The `init --features agents` command generates everything your AI needs (component index, behavioral rules, CLI reference, and package guidance from configured integrations) from the installed project. After a dependency bump, `astryx upgrade --from <old version>` reports a stale block and adding `--apply` refreshes it.",
42
44
  },
43
45
  {
44
46
  type: 'prose',
@@ -48,10 +50,12 @@ export const docs = {
48
50
  type: 'code',
49
51
  lang: 'bash',
50
52
  label: 'Manual options',
51
- code: `npx @astryxdesign/cli init --features agents --agent claude # .claude/CLAUDE.md
52
- npx @astryxdesign/cli init --features agents --agent cursor # .cursorrules
53
+ code: `npx @astryxdesign/cli init --features agents --agent claude # CLAUDE.md if present, else .claude/CLAUDE.md
54
+ npx @astryxdesign/cli init --features agents --agent cursor # .cursorrules if present, else AGENTS.md
53
55
  npx @astryxdesign/cli init --features agents --agent codex # AGENTS.md (Copilot, Codex, etc.)
54
- npx @astryxdesign/cli init --features agents --agent muse # AGENTS.md (Muse)`,
56
+ npx @astryxdesign/cli init --features agents --agent hermes # .hermes.md or HERMES.md if present, else AGENTS.md
57
+ npx @astryxdesign/cli init --features agents --agent muse # AGENTS.md (Muse)
58
+ npx @astryxdesign/cli init --features agents --agent all # every agent file present, else AGENTS.md and .claude/CLAUDE.md`,
55
59
  },
56
60
  ],
57
61
  },
@@ -82,14 +86,17 @@ npx @astryxdesign/cli init --features agents --agent muse # AGENTS.md (Muse
82
86
  content: [
83
87
  {
84
88
  type: 'prose',
85
- text: 'Cursor project rules aren\'t always picked up; it selects which rules to apply based on relevance. For reliable inclusion, install the design system context as a User Rule instead. User Rules live at ~/.cursor/rules/ and apply across all projects.',
89
+ text: 'Cursor reads project rules from `.cursor/rules/`. To keep the Astryx context in a rule of its own, write it there. Give a path relative to the project root, such as `.cursor/rules/astryx.mdc`; an absolute path is refused.',
86
90
  },
87
91
  {
88
92
  type: 'code',
89
93
  lang: 'bash',
90
- label: 'Install as a Cursor user rule',
91
- code: `mkdir -p ~/.cursor/rules
92
- npx @astryxdesign/cli init --features agents --agent-docs-path ~/.cursor/rules/xds.mdc`,
94
+ label: 'Install as a Cursor project rule',
95
+ code: `npx @astryxdesign/cli init --features agents --agent-docs-path .cursor/rules/astryx.mdc`,
96
+ },
97
+ {
98
+ type: 'prose',
99
+ text: 'Rerunning the same command rewrites only the Astryx block, so frontmatter you add above it (such as `alwaysApply: true`) stays.',
93
100
  },
94
101
  ],
95
102
  },
@@ -98,7 +105,7 @@ npx @astryxdesign/cli init --features agents --agent-docs-path ~/.cursor/rules/x
98
105
  content: [
99
106
  {
100
107
  type: 'prose',
101
- text: 'Paste this into your AI before writing any component code. These three questions have a 0% pass rate without docs; models confidently guess wrong on all of them. If your AI can\'t answer them, it\'ll know to install the agent docs first.',
108
+ text: 'Paste this into your AI before writing any component code. If your AI can\'t answer these questions, it\'ll know to install the agent docs first.',
102
109
  },
103
110
  {
104
111
  type: 'code',
@@ -107,7 +114,7 @@ npx @astryxdesign/cli init --features agents --agent-docs-path ~/.cursor/rules/x
107
114
  code: `Before writing any Astryx code, check your knowledge:
108
115
 
109
116
  1. What is the correct import path for Button?
110
- 2. How do you make an Dialog non-dismissible?
117
+ 2. How do you make a Dialog non-dismissible?
111
118
  3. What prop does Selector use for its items?
112
119
 
113
120
  If you don't know all three, run \`npx @astryxdesign/cli init --features agents\` to generate agent docs, then read the generated file.`,
@@ -131,33 +138,34 @@ If you don't know all three, run \`npx @astryxdesign/cli init --features agents\
131
138
  },
132
139
  {
133
140
  type: 'prose',
134
- text: 'With this alias, agents use `astryx component --list` instead of guessing the binary path. The `--` separator is standard npm convention for passing flags to scripts.',
141
+ text: 'With this alias, agents run `npm run astryx -- component --list` instead of guessing the binary path. The `--` separator is standard npm convention for passing flags to scripts.',
135
142
  },
136
143
  {
137
144
  type: 'code',
138
145
  lang: 'bash',
139
146
  label: 'Reliable CLI invocation',
140
- code: `astryx component --list
141
- astryx component Dialog --dense
142
- astryx docs styling --dense
143
- astryx docs tokens --dense`,
147
+ code: `npm run astryx -- component --list
148
+ npm run astryx -- component Dialog --dense
149
+ npm run astryx -- docs styling --full --detail brief
150
+ npm run astryx -- docs tokens --dense`,
144
151
  },
145
152
  ],
146
153
  },
147
154
  {
148
- title: 'The --dense Flag',
155
+ id: 'the-dense-flag',
156
+ title: 'Shorter output: --detail and --dense',
149
157
  content: [
150
158
  {
151
159
  type: 'prose',
152
- text: 'Every CLI command supports --dense, which outputs a token-efficient format designed for AI context windows. Use it when pasting CLI output into a web-based AI tool like ChatGPT or Claude.',
160
+ text: 'For a shorter read, add `--detail brief` (one line per section) or `--detail compact`. `--dense` swaps in a shorter text where a doc ships one. Use them when pasting CLI output into a web-based AI tool like ChatGPT or Claude.',
153
161
  },
154
162
  {
155
163
  type: 'code',
156
164
  lang: 'bash',
157
- label: 'Dense output for pasting into AI conversations',
158
- code: `astryx component Dialog --dense
159
- astryx docs styling --dense
160
- astryx docs tokens --dense`,
165
+ label: 'Short output for pasting into AI conversations',
166
+ code: `astryx docs styling --full --detail brief
167
+ astryx component Dialog --detail compact
168
+ astryx docs principles --dense`,
161
169
  },
162
170
  ],
163
171
  },
@@ -4,7 +4,7 @@
4
4
 
5
5
  import {useState} from 'react';
6
6
  import {InternationalizationProvider} from '@astryxdesign/core/i18n';
7
- import frFR from '@astryxdesign/core/locales/fr-FR.json';
7
+ import frFR from '@astryxdesign/core/locales/fr-FR.generated.js';
8
8
  import {Stack} from '@astryxdesign/core/Layout';
9
9
  import {
10
10
  SegmentedControl,
@@ -10,7 +10,7 @@
10
10
  export const doc = {
11
11
  type: 'schema',
12
12
  name: 'config',
13
- displayName: 'Astryx Config',
13
+ displayName: 'astryx.config',
14
14
  namespace: 'authoring',
15
15
  description:
16
16
  'The optional astryx.config.* file at your project root. Declares which ' +
@@ -60,6 +60,14 @@ export const doc = {
60
60
  example:
61
61
  "{ audience: 'internal', async handle(report, {signal}) { return sendGap(report, {signal}); } }",
62
62
  },
63
+ {
64
+ name: 'discover',
65
+ type: 'DiscoverSource',
66
+ description:
67
+ 'Tell `astryx discover` which integrations this project could add: an async function that returns a catalog. An integration can provide one too, as a `discover` named export from its manifest. Discover calls every source, yours first, and one that fails never hides the others. Discover only reads; your package manager installs.',
68
+ example:
69
+ "async ({signal, package: name, version}) => fetchCatalog({signal, name, version})",
70
+ },
63
71
  {
64
72
  name: 'experimental',
65
73
  type: '{ xle?: { components?: Record<string, XleComponent> } }',
@@ -30,6 +30,7 @@ export type XleComponent = import("./type.js").XleComponent;
30
30
  export type DebugConfig = import("./type.js").DebugConfig;
31
31
  export type DebugEventHandler = import("../debug/type.js").DebugEventHandler;
32
32
  export type GapReportHandler = import("../gap-report/type.js").GapReportHandler;
33
+ export type DiscoverSource = import("../discover/type.js").DiscoverSource;
33
34
  import { z } from 'zod';
34
35
  declare const configSchema: z.ZodObject<{
35
36
  integrations: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -48,6 +49,7 @@ declare const configSchema: z.ZodObject<{
48
49
  }, z.core.$strict>>;
49
50
  debug: z.ZodOptional<z.ZodType<import("../debug/type.js").DebugEventHandler, any, z.core.$ZodTypeInternals<import("../debug/type.js").DebugEventHandler, any>>>;
50
51
  gapReport: z.ZodOptional<z.ZodType<import("../gap-report/type.js").GapReportHandler, any, z.core.$ZodTypeInternals<import("../gap-report/type.js").GapReportHandler, any>>>;
52
+ discover: z.ZodOptional<z.ZodType<import("../discover/type.js").DiscoverSource, any, z.core.$ZodTypeInternals<import("../discover/type.js").DiscoverSource, any>>>;
51
53
  experimental: z.ZodOptional<z.ZodObject<{
52
54
  xle: z.ZodOptional<z.ZodObject<{
53
55
  components: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
@@ -12,6 +12,7 @@
12
12
  import {z} from 'zod';
13
13
  import {formatZodError} from '../_shared/errors.mjs';
14
14
  import {parseGapReportHandler} from '../gap-report/parse.mjs';
15
+ import {parseDiscoverSource} from '../discover/parse.mjs';
15
16
 
16
17
  /** @typedef {import('./type.js').AstryxConfig} AstryxConfig */
17
18
  /** @typedef {import('./type.js').PostCodemodHook} PostCodemodHook */
@@ -19,6 +20,7 @@ import {parseGapReportHandler} from '../gap-report/parse.mjs';
19
20
  /** @typedef {import('./type.js').DebugConfig} DebugConfig */
20
21
  /** @typedef {import('../debug/type.js').DebugEventHandler} DebugEventHandler */
21
22
  /** @typedef {import('../gap-report/type.js').GapReportHandler} GapReportHandler */
23
+ /** @typedef {import('../discover/type.js').DiscoverSource} DiscoverSource */
22
24
 
23
25
  // Typed `z.custom` so `z.infer` reproduces the real function type (not `unknown`).
24
26
  const buildCommand = /** @type {z.ZodType<PostCodemodHook['buildCommand']>} */ (
@@ -66,6 +68,22 @@ const gapReportHandlerSchema = /** @type {z.ZodType<GapReportHandler>} */ (
66
68
  )
67
69
  );
68
70
 
71
+ // The same check an integration's `discover` named export passes. Typed
72
+ // z.custom preserves the public function type.
73
+ const discoverSourceSchema = /** @type {z.ZodType<DiscoverSource>} */ (
74
+ z.custom(
75
+ value => {
76
+ try {
77
+ parseDiscoverSource(value, 'discover');
78
+ return true;
79
+ } catch {
80
+ return false;
81
+ }
82
+ },
83
+ {message: 'Expected a discover source function'},
84
+ )
85
+ );
86
+
69
87
  const configSchema = z
70
88
  .object({
71
89
  integrations: z.array(z.string()).optional(),
@@ -76,6 +94,7 @@ const configSchema = z
76
94
  .optional(),
77
95
  debug: debugSchema.optional(),
78
96
  gapReport: gapReportHandlerSchema.optional(),
97
+ discover: discoverSourceSchema.optional(),
79
98
  experimental: z
80
99
  .object({
81
100
  xle: z
@@ -63,6 +63,14 @@ describe('parseConfig (load boundary)', () => {
63
63
  ).toEqual({audience: 'internal', handle});
64
64
  });
65
65
 
66
+ it('accepts a discover source function and refuses anything else', () => {
67
+ const discover = async () => ({});
68
+ expect(parseConfig({discover}).discover).toBe(discover);
69
+ expect(reason({discover: 'https://example.com/catalog.json'})).toContain(
70
+ 'discover',
71
+ );
72
+ });
73
+
66
74
  it('rejects obsolete or extended gap-report handler shapes', () => {
67
75
  expect(reason({gapReport: {command: './report.mjs'}})).toContain(
68
76
  'gapReport',
@@ -11,6 +11,7 @@
11
11
 
12
12
  import type {DebugEventHandler} from '../debug/type.js';
13
13
  import type {GapReportHandler} from '../gap-report/type.js';
14
+ import type {DiscoverSource} from '../discover/type.js';
14
15
 
15
16
  /**
16
17
  * A command to run as part of a post-codemod hook. Returned by a hook's
@@ -96,6 +97,16 @@ export interface AstryxConfig {
96
97
  debug?: DebugConfig;
97
98
  /** Route gap reports through a project-owned handler. See {@link GapReportHandler}. */
98
99
  gapReport?: GapReportHandler;
100
+ /**
101
+ * Tell `astryx discover` about integrations this project could add. See
102
+ * {@link DiscoverSource}.
103
+ *
104
+ * An integration can provide a source too, as a `discover` named export from
105
+ * its `astryx.integration.*` module. Discover calls every source: this one
106
+ * first, then each integration's in load order, and one that fails never
107
+ * hides the others.
108
+ */
109
+ discover?: DiscoverSource;
99
110
  /**
100
111
  * EXPERIMENTAL — shape may change and is not part of the stable config
101
112
  * contract. Provisional home for features still being proven out.
@@ -0,0 +1,13 @@
1
+ // @generated by scripts/sync-api-types.mjs from the JSDoc in authoring/**/*.mjs.
2
+ // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
+
4
+ /**
5
+ * @file SchemaDoc for DiscoverSource, the function `astryx discover` calls to
6
+ * learn which integrations a project could add.
7
+ * @input The DiscoverSource type and the catalog types beside it (`type.ts`),
8
+ * which `parse.mjs` validates.
9
+ * @output The `discover-source` section of `astryx docs authoring`.
10
+ * @position packages/cli/authoring/discover — schema documentation
11
+ */
12
+ /** @type {import('@astryxdesign/cli/authoring').SchemaDoc} */
13
+ export const doc: import("@astryxdesign/cli/authoring").SchemaDoc;
@@ -0,0 +1,138 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file SchemaDoc for DiscoverSource, the function `astryx discover` calls to
5
+ * learn which integrations a project could add.
6
+ * @input The DiscoverSource type and the catalog types beside it (`type.ts`),
7
+ * which `parse.mjs` validates.
8
+ * @output The `discover-source` section of `astryx docs authoring`.
9
+ * @position packages/cli/authoring/discover — schema documentation
10
+ */
11
+
12
+ /** @type {import('@astryxdesign/cli/authoring').SchemaDoc} */
13
+ export const doc = {
14
+ type: 'schema',
15
+ name: 'discover-source',
16
+ displayName: 'DiscoverSource',
17
+ namespace: 'authoring',
18
+ description:
19
+ 'A source for `astryx discover`: an async function that returns a catalog of packages a project could add, their versions, and what each version adds. Set it as `discover` in astryx.config, or export it as `discover` from an integration manifest. Discover calls every source, the project one first, and one that throws, runs past 30 seconds, or returns an invalid catalog never hides the others; discover then uses the last good answer it saved for that source. Discover only reads: it prints the command that adds a package and never runs it.',
20
+ appliesTo:
21
+ '`discover` in astryx.config.*, or the `discover` named export of astryx.integration.*',
22
+ fields: [
23
+ {
24
+ name: 'context',
25
+ type: 'DiscoverSourceContext',
26
+ description: 'The one argument the source is called with.',
27
+ required: true,
28
+ fields: [
29
+ {
30
+ name: 'context.signal',
31
+ type: 'AbortSignal',
32
+ description: 'Aborted when the source runs past 30 seconds.',
33
+ required: true,
34
+ },
35
+ {
36
+ name: 'context.package',
37
+ type: 'string',
38
+ description:
39
+ 'Set when discover shows one package: return that package with every version.',
40
+ },
41
+ {
42
+ name: 'context.version',
43
+ type: 'string',
44
+ description:
45
+ "With `package`: return that version's contributions. Without it, the latest release's.",
46
+ },
47
+ ],
48
+ },
49
+ {
50
+ name: 'returns',
51
+ type: 'Promise<DiscoverCatalog>',
52
+ description:
53
+ 'The catalog. Discover checks it, ignores fields and item kinds it does not know, and refuses any schemaVersion but 1.',
54
+ required: true,
55
+ fields: [
56
+ {
57
+ name: 'schemaVersion',
58
+ type: '1',
59
+ description: 'Version of the catalog shape.',
60
+ required: true,
61
+ },
62
+ {
63
+ name: 'source',
64
+ type: '{name: string, generatedAt: string, complete: boolean}',
65
+ description:
66
+ 'Who answered, when the data was produced (ISO 8601), and false when the source knows its list is partial.',
67
+ required: true,
68
+ },
69
+ {
70
+ name: 'packages',
71
+ type: 'DiscoverPackage[]',
72
+ description:
73
+ 'One entry per npm package. When two sources list the same package, the earlier source wins.',
74
+ required: true,
75
+ fields: [
76
+ {
77
+ name: 'packages[].package',
78
+ type: 'string',
79
+ description: 'The npm name.',
80
+ required: true,
81
+ },
82
+ {
83
+ name: 'packages[].integration',
84
+ type: 'string',
85
+ description:
86
+ 'Shared by every npm name that publishes the same integration. Discover lists an integration once.',
87
+ required: true,
88
+ },
89
+ {
90
+ name: 'packages[].aliases',
91
+ type: 'string[]',
92
+ description:
93
+ "The integration's other npm names. Discover never offers a package the project has under another name.",
94
+ required: true,
95
+ },
96
+ {
97
+ name: 'packages[].description',
98
+ type: 'string',
99
+ description: 'One line, for the list and search.',
100
+ },
101
+ {
102
+ name: 'packages[].latest',
103
+ type: 'string | null',
104
+ description: 'The latest release. Null when there are only prereleases.',
105
+ required: true,
106
+ },
107
+ {
108
+ name: 'packages[].versions',
109
+ type: 'DiscoverVersion[]',
110
+ description:
111
+ 'Every version, newest first: `{version, publishedAt, prerelease, status}`, where status is `ok` or why the version could not be read.',
112
+ required: true,
113
+ },
114
+ {
115
+ name: 'packages[].contributions',
116
+ type: 'DiscoverContribution[]',
117
+ description:
118
+ "What the requested (else latest) version adds: `{kind, name, title?, summary?, keywords?}`, where kind is `component`, `template`, `doc`, `theme`, `codemod`, or `agent-doc` (a DiscoverKind) and name is the name the CLI uses for it.",
119
+ required: true,
120
+ },
121
+ ],
122
+ },
123
+ ],
124
+ },
125
+ ],
126
+ examples: [
127
+ {
128
+ label: 'A project source in astryx.config',
129
+ code:
130
+ 'export default {\n' +
131
+ ' async discover({signal, package: name, version}) {\n' +
132
+ ' const res = await fetch(catalogUrl(name, version), {signal});\n' +
133
+ ' return res.json();\n' +
134
+ ' },\n' +
135
+ '};',
136
+ },
137
+ ],
138
+ };
@@ -0,0 +1,24 @@
1
+ // @generated by scripts/sync-api-types.mjs from the JSDoc in authoring/**/*.mjs.
2
+ // DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
3
+
4
+ /**
5
+ * Check a catalog a discover source returned. Throws an Error naming the first
6
+ * problem. Items of a kind this CLI does not know are dropped, and versions are
7
+ * put newest first whatever order the source used.
8
+ *
9
+ * @param {unknown} value
10
+ * @param {string} [label]
11
+ * @returns {import('./type.js').DiscoverCatalog}
12
+ */
13
+ export function parseDiscoverCatalog(value: unknown, label?: string): import("./type.js").DiscoverCatalog;
14
+ /**
15
+ * Check a discover source itself: an async function, like `debug`, that takes
16
+ * `{signal, package?, version?}` and resolves to a catalog.
17
+ *
18
+ * @param {unknown} value
19
+ * @param {string} label
20
+ * @returns {import('./type.js').DiscoverSource}
21
+ */
22
+ export function parseDiscoverSource(value: unknown, label: string): import("./type.js").DiscoverSource;
23
+ /** Item kinds a catalog may list, in display order. */
24
+ export const DISCOVER_KINDS: readonly ["component", "template", "doc", "theme", "codemod", "agent-doc"];
@@ -0,0 +1,128 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file Runtime checks for discover sources and the catalogs they return.
5
+ *
6
+ * The catalog schema is deliberately not strict: a source may add fields this
7
+ * CLI does not know, and they are dropped. An unknown `schemaVersion` is
8
+ * refused, and an item of a kind this CLI does not know is skipped, so a newer
9
+ * source never breaks an older CLI.
10
+ *
11
+ * @position packages/cli/authoring/discover — parse + validate, no I/O.
12
+ */
13
+
14
+ import {z} from 'zod';
15
+
16
+ /** Item kinds a catalog may list, in display order. */
17
+ export const DISCOVER_KINDS = /** @type {const} */ ([
18
+ 'component',
19
+ 'template',
20
+ 'doc',
21
+ 'theme',
22
+ 'codemod',
23
+ 'agent-doc',
24
+ ]);
25
+
26
+ const text = (/** @type {number} */ max) => z.string().min(1).max(max);
27
+
28
+ const contributionSchema = z.object({
29
+ kind: text(32),
30
+ name: text(512),
31
+ title: z.string().max(512).optional(),
32
+ summary: z.string().max(4096).optional(),
33
+ keywords: z.array(z.string().max(128)).max(64).optional(),
34
+ });
35
+
36
+ const versionSchema = z.object({
37
+ version: text(256),
38
+ publishedAt: z.string().max(64).nullable(),
39
+ prerelease: z.boolean(),
40
+ status: text(64),
41
+ });
42
+
43
+ const packageSchema = z.object({
44
+ package: text(214),
45
+ integration: text(214),
46
+ aliases: z.array(text(214)).max(64),
47
+ description: z.string().max(1024).optional(),
48
+ latest: text(256).nullable(),
49
+ versions: z.array(versionSchema).max(50_000),
50
+ contributions: z.array(contributionSchema).max(50_000),
51
+ });
52
+
53
+ const catalogSchema = z.object({
54
+ schemaVersion: z.literal(1),
55
+ source: z.object({
56
+ name: text(256),
57
+ generatedAt: text(64),
58
+ complete: z.boolean(),
59
+ }),
60
+ packages: z.array(packageSchema).max(20_000),
61
+ });
62
+
63
+ /**
64
+ * Newest first by publish time. A version with no known publish time goes
65
+ * last, and ties fall back to the version number.
66
+ * @param {{version: string, publishedAt: string | null}} a
67
+ * @param {{version: string, publishedAt: string | null}} b
68
+ */
69
+ function newestFirst(a, b) {
70
+ const at = Date.parse(a.publishedAt ?? '');
71
+ const bt = Date.parse(b.publishedAt ?? '');
72
+ if (Number.isNaN(at) !== Number.isNaN(bt)) return Number.isNaN(at) ? 1 : -1;
73
+ if (!Number.isNaN(at) && at !== bt) return bt - at;
74
+ return b.version.localeCompare(a.version, 'en', {numeric: true});
75
+ }
76
+
77
+ /**
78
+ * Check a catalog a discover source returned. Throws an Error naming the first
79
+ * problem. Items of a kind this CLI does not know are dropped, and versions are
80
+ * put newest first whatever order the source used.
81
+ *
82
+ * @param {unknown} value
83
+ * @param {string} [label]
84
+ * @returns {import('./type.js').DiscoverCatalog}
85
+ */
86
+ export function parseDiscoverCatalog(value, label = 'discover source') {
87
+ const version =
88
+ value != null && typeof value === 'object'
89
+ ? /** @type {{schemaVersion?: unknown}} */ (value).schemaVersion
90
+ : undefined;
91
+ if (version !== undefined && version !== 1) {
92
+ throw new Error(
93
+ `${label} returned schemaVersion ${String(version)}; this CLI reads schemaVersion 1`,
94
+ );
95
+ }
96
+ const parsed = catalogSchema.safeParse(value);
97
+ if (!parsed.success) {
98
+ const issue = parsed.error.issues[0];
99
+ const where = issue?.path.length ? ` at ${issue.path.join('.')}` : '';
100
+ throw new Error(
101
+ `${label} returned an invalid catalog${where}: ${issue?.message}`,
102
+ );
103
+ }
104
+ const known = /** @type {readonly string[]} */ (DISCOVER_KINDS);
105
+ return /** @type {import('./type.js').DiscoverCatalog} */ ({
106
+ ...parsed.data,
107
+ packages: parsed.data.packages.map(pkg => ({
108
+ ...pkg,
109
+ versions: [...pkg.versions].sort(newestFirst),
110
+ contributions: pkg.contributions.filter(c => known.includes(c.kind)),
111
+ })),
112
+ });
113
+ }
114
+
115
+ /**
116
+ * Check a discover source itself: an async function, like `debug`, that takes
117
+ * `{signal, package?, version?}` and resolves to a catalog.
118
+ *
119
+ * @param {unknown} value
120
+ * @param {string} label
121
+ * @returns {import('./type.js').DiscoverSource}
122
+ */
123
+ export function parseDiscoverSource(value, label) {
124
+ if (typeof value !== 'function') {
125
+ throw new Error(`${label} must be a function`);
126
+ }
127
+ return /** @type {import('./type.js').DiscoverSource} */ (value);
128
+ }