@astryxdesign/cli 0.6.4-canary.06c8fa3 → 0.6.4-canary.0e1fbdb

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 (254) hide show
  1. package/README.md +49 -40
  2. package/api/build/build.doc.mjs +6 -1
  3. package/api/build/build.test.mjs +22 -0
  4. package/api/build/kit/kit.mjs +44 -5
  5. package/api/component/component.doc.mjs +14 -7
  6. package/api/docs/_adapter.d.mts +8 -3
  7. package/api/docs/_adapter.mjs +14 -6
  8. package/api/docs/docOverlays.test.mjs +27 -1
  9. package/api/docs/docs.doc.mjs +2 -2
  10. package/api/doctor/doctor.doc.mjs +17 -8
  11. package/api/doctor/doctor.type.d.mts +1 -1
  12. package/api/doctor/doctor.type.mjs +1 -1
  13. package/api/gap-report/gap-report.doc.mjs +19 -10
  14. package/api/hook/hook.doc.mjs +6 -3
  15. package/api/index.d.mts +2 -0
  16. package/api/index.mjs +3 -1
  17. package/api/init/init.doc.mjs +17 -12
  18. package/api/integration/add-theme.mjs +22 -1
  19. package/api/integration/add-theme.test.mjs +34 -0
  20. package/api/integration/authoring-checks.mjs +2 -2
  21. package/api/integration/integrationPackCheck.doc.mjs +3 -3
  22. package/api/integration/pack-check.lifecycle-output.test.mjs +2 -0
  23. package/api/integration/pack-check.mjs +54 -6
  24. package/api/integration/pack-check.test.mjs +90 -0
  25. package/api/integration/pack-check.type.mjs +1 -1
  26. package/api/json/assertResponse.doc.mjs +1 -1
  27. package/api/json/index.ts +1 -0
  28. package/api/json/isError.doc.mjs +1 -1
  29. package/api/layout/_adapter.d.mts +34 -0
  30. package/api/layout/_adapter.mjs +148 -0
  31. package/api/layout/check/check.d.mts +16 -0
  32. package/api/layout/check/check.mjs +40 -0
  33. package/api/layout/expand/expand.d.mts +22 -0
  34. package/api/layout/expand/expand.mjs +155 -0
  35. package/api/layout/expand/expand.path-safety.test.mjs +53 -0
  36. package/api/layout/grammar/grammar.d.mts +13 -0
  37. package/api/layout/grammar/grammar.mjs +87 -0
  38. package/api/layout/layout.d.mts +6 -0
  39. package/api/layout/layout.mjs +17 -0
  40. package/api/layout/layout.test.mjs +297 -0
  41. package/api/layout/layout.type.d.mts +89 -0
  42. package/api/layout/layout.type.mjs +103 -0
  43. package/api/layout/layoutCheck.doc.d.mts +11 -0
  44. package/api/layout/layoutCheck.doc.mjs +85 -0
  45. package/api/layout/layoutExpand.doc.d.mts +11 -0
  46. package/api/layout/layoutExpand.doc.mjs +107 -0
  47. package/api/layout/layoutGrammar.doc.d.mts +11 -0
  48. package/api/layout/layoutGrammar.doc.mjs +57 -0
  49. package/api/search/search.d.mts +27 -1
  50. package/api/search/search.doc.mjs +2 -2
  51. package/api/search/search.mjs +228 -16
  52. package/api/swizzle/swizzle.doc.mjs +7 -5
  53. package/api/template/copy/copy.mjs +1 -1
  54. package/api/template/copy/copy.test.mjs +9 -0
  55. package/api/template/template-integration.test.mjs +65 -1
  56. package/api/template/template.doc.mjs +2 -1
  57. package/api/template/template.mjs +1 -1
  58. package/api/theme/generateTonalPalette.doc.mjs +1 -2
  59. package/api/theme/listThemes.doc.mjs +1 -1
  60. package/api/theme/themeAdd.doc.mjs +9 -10
  61. package/api/theme/themeBuild.doc.mjs +13 -13
  62. package/api/theme/themeList.doc.mjs +1 -1
  63. package/api/theme/themeListAvailable.doc.mjs +2 -1
  64. package/api/theme/themePaletteGenerate.doc.mjs +15 -8
  65. package/api/theme/themeTargets.doc.mjs +3 -2
  66. package/api/theme/themeTemplate.doc.mjs +2 -1
  67. package/api/upgrade/run/run.mjs +1 -1
  68. package/api/upgrade/upgrade.doc.mjs +24 -22
  69. package/assets/docs/README.md +4 -2
  70. package/assets/docs/browser-support.doc.mjs +11 -11
  71. package/assets/docs/color.doc.mjs +8 -2
  72. package/assets/docs/elevation.doc.mjs +6 -4
  73. package/assets/docs/getting-started.doc.mjs +5 -16
  74. package/assets/docs/icons.doc.mjs +2 -21
  75. package/assets/docs/illustrations.doc.mjs +7 -15
  76. package/assets/docs/layout.doc.dense.mjs +130 -82
  77. package/assets/docs/layout.doc.mjs +133 -77
  78. package/assets/docs/migration.doc.mjs +19 -21
  79. package/assets/docs/motion.doc.mjs +16 -3
  80. package/assets/docs/principles.doc.dense.mjs +5 -5
  81. package/assets/docs/principles.doc.mjs +8 -0
  82. package/assets/docs/principles.doc.zh.mjs +6 -6
  83. package/assets/docs/shape.doc.mjs +8 -3
  84. package/assets/docs/spacing.doc.mjs +7 -2
  85. package/assets/docs/styling-libraries.doc.mjs +6 -2
  86. package/assets/docs/styling.doc.mjs +19 -23
  87. package/assets/docs/theme.doc.dense.mjs +58 -18
  88. package/assets/docs/theme.doc.mjs +56 -46
  89. package/assets/docs/theme.doc.zh.mjs +9 -8
  90. package/assets/docs/tokens.doc.dense.mjs +2 -2
  91. package/assets/docs/tokens.doc.mjs +389 -8
  92. package/assets/docs/tokens.doc.zh.mjs +2 -2
  93. package/assets/docs/tree/add-a-component.doc.mjs +75 -0
  94. package/assets/docs/tree/add-a-theme.doc.mjs +85 -0
  95. package/assets/docs/tree/add-a-topic.doc.mjs +144 -0
  96. package/assets/docs/tree/agent-guidance.doc.mjs +138 -0
  97. package/assets/docs/tree/block-template.doc.mjs +130 -0
  98. package/assets/docs/tree/build-the-template.doc.mjs +28 -0
  99. package/assets/docs/tree/building-blocks.doc.mjs +46 -0
  100. package/assets/docs/tree/check-your-docs.doc.mjs +137 -0
  101. package/assets/docs/tree/checks.doc.mjs +119 -0
  102. package/assets/docs/tree/codemods.doc.mjs +147 -0
  103. package/assets/docs/tree/component-family.doc.mjs +113 -0
  104. package/assets/docs/tree/component-imports.doc.mjs +69 -0
  105. package/assets/docs/tree/components.doc.mjs +23 -0
  106. package/assets/docs/tree/configuration.doc.mjs +23 -0
  107. package/assets/docs/tree/debug-and-gap-reports.doc.mjs +182 -0
  108. package/assets/docs/tree/define-the-theme.doc.mjs +118 -0
  109. package/assets/docs/tree/describe-the-component.doc.mjs +57 -0
  110. package/assets/docs/tree/docs.doc.mjs +21 -0
  111. package/assets/docs/tree/document-the-template.doc.mjs +28 -0
  112. package/assets/docs/tree/document-the-theme.doc.mjs +68 -0
  113. package/assets/docs/tree/export-template-assets.doc.mjs +147 -0
  114. package/assets/docs/tree/extend-or-replace.doc.mjs +103 -0
  115. package/assets/docs/tree/fonts-and-assets.doc.mjs +106 -0
  116. package/assets/docs/tree/generate-a-palette.doc.mjs +66 -0
  117. package/assets/docs/tree/grade-template-with-agent.doc.mjs +105 -0
  118. package/assets/docs/tree/help.doc.mjs +16 -0
  119. package/assets/docs/tree/integrations.doc.mjs +25 -470
  120. package/assets/docs/tree/links.doc.mjs +98 -0
  121. package/assets/docs/tree/package-and-test.doc.mjs +32 -0
  122. package/assets/docs/tree/page-template.doc.mjs +71 -0
  123. package/assets/docs/tree/publishing.doc.mjs +111 -0
  124. package/assets/docs/tree/quick-start.doc.mjs +272 -0
  125. package/assets/docs/tree/replace-a-core-component.doc.mjs +104 -0
  126. package/assets/docs/tree/replace-a-core-template.doc.mjs +172 -0
  127. package/assets/docs/tree/sections-and-placement.doc.mjs +108 -0
  128. package/assets/docs/tree/see-it-in-an-app.doc.mjs +59 -0
  129. package/assets/docs/tree/ship.doc.mjs +16 -0
  130. package/assets/docs/tree/short-and-findable.doc.mjs +108 -0
  131. package/assets/docs/tree/single-component.doc.mjs +165 -0
  132. package/assets/docs/tree/start-a-template.doc.mjs +143 -0
  133. package/assets/docs/tree/subcomponent.doc.mjs +115 -0
  134. package/assets/docs/tree/template-assets.doc.mjs +64 -0
  135. package/assets/docs/tree/template-doc-overview.doc.mjs +109 -0
  136. package/assets/docs/tree/template-fonts.doc.mjs +102 -0
  137. package/assets/docs/tree/template-grading-rubric.doc.mjs +452 -0
  138. package/assets/docs/tree/template-icons.doc.mjs +97 -0
  139. package/assets/docs/tree/template-images-media.doc.mjs +127 -0
  140. package/assets/docs/tree/template-styles.doc.mjs +93 -0
  141. package/assets/docs/tree/templates.doc.mjs +34 -0
  142. package/assets/docs/tree/test-in-an-app.doc.mjs +115 -0
  143. package/assets/docs/tree/test-template-in-app.doc.mjs +128 -0
  144. package/assets/docs/tree/themes.doc.mjs +39 -0
  145. package/assets/docs/tree/troubleshooting.doc.mjs +149 -0
  146. package/assets/docs/tree/upgrading.doc.mjs +103 -0
  147. package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +51 -0
  148. package/assets/docs/tree/verify-packed-template.doc.mjs +77 -0
  149. package/assets/docs/tree/versioning.doc.mjs +161 -0
  150. package/assets/docs/tree/write-good-templates.doc.mjs +64 -0
  151. package/assets/docs/tree/write-the-template-file.doc.mjs +154 -0
  152. package/assets/docs/typography.doc.mjs +24 -4
  153. package/assets/docs/working-with-ai.doc.mjs +30 -22
  154. package/authoring/config/config.doc.mjs +2 -2
  155. package/authoring/config/type.ts +2 -2
  156. package/authoring/doctypes/_schema.d.mts +3 -2
  157. package/authoring/doctypes/_schema.mjs +6 -0
  158. package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
  159. package/authoring/doctypes/base/type.ts +4 -2
  160. package/authoring/doctypes/command/command.doc.mjs +1 -1
  161. package/authoring/doctypes/command/type.ts +1 -1
  162. package/authoring/doctypes/component/component.doc.mjs +6 -0
  163. package/authoring/doctypes/component/type.ts +8 -0
  164. package/authoring/doctypes/reference/reference.doc.mjs +7 -0
  165. package/authoring/doctypes/reference/type.ts +5 -0
  166. package/authoring/doctypes/schema/schema.doc.mjs +2 -2
  167. package/authoring/doctypes/template/template.doc.mjs +1 -1
  168. package/authoring/doctypes/template/type.ts +2 -2
  169. package/authoring/integration/integration.doc.mjs +12 -10
  170. package/clients/cli/command-result-coverage.test.mjs +7 -7
  171. package/clients/cli/commands/component.doc.mjs +4 -3
  172. package/clients/cli/commands/debug-result-summary.test.mjs +2 -2
  173. package/clients/cli/commands/docs.doc.mjs +1 -1
  174. package/clients/cli/commands/docs.mjs +60 -17
  175. package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -2
  176. package/clients/cli/commands/doctor-integration.test.mjs +53 -0
  177. package/clients/cli/commands/doctor.doc.mjs +3 -1
  178. package/clients/cli/commands/doctor.mjs +49 -5
  179. package/clients/cli/commands/gap-report.doc.mjs +10 -9
  180. package/clients/cli/commands/init.doc.mjs +9 -6
  181. package/clients/cli/commands/integration-add.doc.mjs +9 -9
  182. package/clients/cli/commands/integration-authoring.test.mjs +61 -10
  183. package/clients/cli/commands/integration-pack.doc.mjs +5 -9
  184. package/clients/cli/commands/integration-real-world.test.mjs +1 -1
  185. package/clients/cli/commands/integration-verify.doc.mjs +22 -0
  186. package/clients/cli/commands/integration.doc.mjs +4 -4
  187. package/clients/cli/commands/integration.mjs +74 -43
  188. package/clients/cli/commands/layout-check.doc.mjs +65 -0
  189. package/clients/cli/commands/layout-expand.doc.mjs +83 -0
  190. package/clients/cli/commands/layout-grammar.doc.mjs +30 -0
  191. package/clients/cli/commands/layout.doc.mjs +34 -0
  192. package/clients/cli/commands/layout.error-codes.test.mjs +66 -0
  193. package/clients/cli/commands/layout.exit-parity.test.mjs +41 -0
  194. package/clients/cli/commands/layout.mjs +275 -0
  195. package/clients/cli/commands/layout.path-help.test.mjs +33 -0
  196. package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
  197. package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
  198. package/clients/cli/commands/manifest.doc.mjs +1 -1
  199. package/clients/cli/commands/search.doc.mjs +10 -3
  200. package/clients/cli/commands/search.mjs +21 -2
  201. package/clients/cli/commands/search.test.mjs +21 -4
  202. package/clients/cli/commands/swizzle.doc.mjs +1 -1
  203. package/clients/cli/commands/template.doc.mjs +1 -1
  204. package/clients/cli/commands/text-json-parity.test.mjs +24 -1
  205. package/clients/cli/commands/theme-add.doc.mjs +1 -1
  206. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -2
  207. package/clients/cli/commands/theme-palette.doc.mjs +1 -2
  208. package/clients/cli/commands/theme-targets.doc.mjs +2 -2
  209. package/clients/cli/commands/theme.doc.mjs +2 -1
  210. package/clients/cli/commands/upgrade.doc.mjs +62 -3
  211. package/clients/cli/index.mjs +32 -6
  212. package/clients/cli/lib/define-command.mjs +28 -4
  213. package/clients/cli/lib/define-command.test.mjs +54 -0
  214. package/clients/cli/lib/exit-codes.test.mjs +25 -2
  215. package/clients/cli/lib/json-shim.test.mjs +20 -6
  216. package/clients/cli/lib/manifest.mjs +23 -5
  217. package/foundation/agent-docs/agent-docs.mjs +1 -1
  218. package/foundation/discovery/authoring-self-docs.test.mjs +6 -2
  219. package/foundation/discovery/cli-self-docs.mjs +16 -2
  220. package/foundation/discovery/cli-self-docs.test.mjs +20 -0
  221. package/foundation/discovery/docs-discovery.mjs +5 -1
  222. package/foundation/discovery/docs-discovery.test.mjs +21 -0
  223. package/foundation/discovery/docs-section-key.d.mts +1 -1
  224. package/foundation/discovery/docs-section-key.mjs +1 -1
  225. package/foundation/discovery/template-adapter.mjs +1 -1
  226. package/foundation/doc-compiler/doc-loads.test.mjs +15 -2
  227. package/foundation/doc-compiler/inputs.test.mjs +0 -1
  228. package/foundation/doc-compiler/tree.d.mts +4 -0
  229. package/foundation/doc-compiler/tree.mjs +6 -1
  230. package/foundation/integrations/cli-requirement.d.mts +26 -6
  231. package/foundation/integrations/cli-requirement.mjs +46 -11
  232. package/foundation/integrations/cli-requirement.test.mjs +7 -2
  233. package/foundation/integrations/contribution-inventory.mjs +1 -1
  234. package/foundation/response/error-codes.doc.mjs +6 -8
  235. package/foundation/response/error-codes.test.mjs +30 -5
  236. package/foundation/response/response-types.doc.d.mts +4 -3
  237. package/foundation/response/response-types.doc.mjs +42 -6
  238. package/foundation/response/response.doc.mjs +11 -10
  239. package/foundation/xle/browser.d.mts +3 -3
  240. package/foundation/xle/browser.mjs +3 -3
  241. package/foundation/xle/expand.mjs +2 -2
  242. package/foundation/xle/parse.mjs +1 -1
  243. package/foundation/xle/print.mjs +2 -2
  244. package/foundation/xle/splice.mjs +1 -1
  245. package/package.json +9 -9
  246. package/api/docs/docs.test.mjs +0 -245
  247. package/api/docs/integration-tree.test.mjs +0 -555
  248. package/api/docs/integrationDocs.test.mjs +0 -314
  249. package/api/search/search.test.mjs +0 -530
  250. package/assets/docs/tree/integrations.test.mjs +0 -62
  251. package/assets/docs/tree/writing-docs.doc.mjs +0 -286
  252. package/clients/cli/commands/docs.test.mjs +0 -323
  253. package/foundation/agent-docs/agent-docs.test.mjs +0 -1159
  254. package/foundation/doc-compiler/tree.test.mjs +0 -606
@@ -0,0 +1,119 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file `astryx docs cli/integrations/checks`: what each package check
5
+ * proves, what fails and what only warns, and one command to run them all.
6
+ */
7
+
8
+ /** @type {import('@astryxdesign/cli/authoring').ReferenceDoc} */
9
+ export const docs = {
10
+ type: 'generic',
11
+ name: 'checks',
12
+ placement: {parent: 'namespace:ship', slot: 'guides', order: 20},
13
+ title: 'Check an integration',
14
+ category: 'guide',
15
+ keywords: ['check before publishing', 'validate an integration', 'ci'],
16
+ description:
17
+ 'Pick the check for each problem, learn what fails and what only warns, and run every check in CI.',
18
+ sections: [
19
+ {
20
+ id: 'pick-a-check',
21
+ title: 'Pick a check',
22
+ content: [
23
+ {
24
+ type: 'prose',
25
+ text: 'Run these in the package folder. The four `doctor integration` checks read your source; `integration verify` checks the package npm would publish.',
26
+ },
27
+ {
28
+ type: 'table',
29
+ headers: ['Command', 'Proves', 'Exits 1 when', 'Only warns when'],
30
+ rows: [
31
+ [
32
+ '`npx astryx doctor integration validate`',
33
+ 'The manifest loads, and each root holds contributions the CLI can read',
34
+ 'A declared root is missing (`missing_root`), a contribution does not load (`invalid_doc`, `invalid_component`, `invalid_theme`), or two templates in the package replace one Core id (`ambiguous_template_replacement`)',
35
+ 'The manifest has a key this CLI does not know (`unknown_manifest_key`). With no `astryx.integration.mjs` it prints a hint and exits 0',
36
+ ],
37
+ [
38
+ '`npx astryx doctor integration components`',
39
+ 'No component name clashes with a Core component',
40
+ 'Core is not installed (`core_not_found`)',
41
+ 'A name clashes with Core',
42
+ ],
43
+ [
44
+ '`npx astryx doctor integration templates`',
45
+ 'Each `replaces` names a Core template of the same type',
46
+ 'A `replaces` target is missing (`missing_template_replacement_target`) or of the other type (`invalid_template_replacement`), or two templates replace one id (`ambiguous_template_replacement`)',
47
+ 'A template id matches a Core id without `replaces`',
48
+ ],
49
+ [
50
+ '`npx astryx doctor integration docs`',
51
+ 'Your docs tree, every link, and topic names against Core',
52
+ 'A topic takes a Core topic name without `replaces` or `extends`, a doc is invalid (`invalid_doc`), or a namespace or placement fails, which hides the doc (`invalid_doc_graph`)',
53
+ 'A link names no doc (`invalid_doc_graph`)',
54
+ ],
55
+ [
56
+ '`npx astryx integration verify`',
57
+ 'The packed package holds every file, shows the same contributions, resolves every public import, and declares the CLI it needs',
58
+ 'Anything `validate` fails on, no manifest, a file left out of the `.tgz` file, an import that does not resolve, or a missing CLI peer',
59
+ 'Anything `validate` warns about',
60
+ ],
61
+ ],
62
+ },
63
+ {
64
+ type: 'prose',
65
+ text: 'Pass a package name, such as `npx astryx doctor integration validate @acme/astryx-widgets`, to check an installed copy from an app instead.',
66
+ },
67
+ ],
68
+ },
69
+ {
70
+ id: 'run-every-check-in-ci',
71
+ title: 'Run every check in CI',
72
+ content: [
73
+ {
74
+ type: 'prose',
75
+ text: 'Chain the five checks so the first failure stops the run. Install devDependencies first, because the components check needs Core.',
76
+ },
77
+ {
78
+ type: 'code',
79
+ lang: 'bash',
80
+ code: 'npx astryx doctor integration validate && npx astryx doctor integration components && npx astryx doctor integration templates && npx astryx doctor integration docs && npx astryx integration verify',
81
+ },
82
+ {
83
+ type: 'list',
84
+ style: 'unordered',
85
+ items: [
86
+ '`integration verify` runs `validate` but none of the other three: a Core name clash, a `replaces` that names no Core template, a topic that takes a Core name, or a hidden guide still passes it.',
87
+ 'Warnings keep exit code 0, so read them before you publish.',
88
+ 'Bare `npx astryx doctor` in the package also warns about a doc section over 32 KB, which no check above measures.',
89
+ ],
90
+ },
91
+ ],
92
+ },
93
+ {
94
+ id: 'what-integration-verify-does',
95
+ title: 'Verify the packed package',
96
+ content: [
97
+ {
98
+ type: 'prose',
99
+ text: '`integration verify` packs your package with npm, unpacks it into a temporary app, and checks that the app sees everything your source has. It publishes nothing and leaves no `.tgz` file or temporary folder behind.',
100
+ },
101
+ {
102
+ type: 'list',
103
+ style: 'ordered',
104
+ items: [
105
+ 'It runs `npm pack` the way `npm publish` would, including your `prepack` script.',
106
+ 'It checks that every contribution file is in the `.tgz` file. A root missing from `files` fails with `Add "templates" to "files" in package.json.`',
107
+ 'It lists the components, templates, themes, docs, and codemods the temporary app sees, and compares them with your source.',
108
+ "It resolves each component's `import`, and each template's public import, the way Node does, and checks that the module exports the component, or a default export for a template.",
109
+ 'It fails a package that ships a docs section, a placed guide, a template `replaces`, a doc section with an `id`, or a theme without an `@astryxdesign/cli` peer of `>=0.7.0`.',
110
+ ],
111
+ },
112
+ {
113
+ type: 'prose',
114
+ text: '`integration pack --check`, the name this check had in 0.6, still runs it and prints a note; it will be removed in a later release. The options and exit codes are in {@link command:integration verify}.',
115
+ },
116
+ ],
117
+ },
118
+ ],
119
+ };
@@ -0,0 +1,147 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file `astryx docs cli/integrations/codemods`: add codemods to an
5
+ * integration package, and know which of them `astryx upgrade` runs in an app.
6
+ */
7
+
8
+ /** @type {import('@astryxdesign/cli/authoring').ReferenceDoc} */
9
+ export const docs = {
10
+ type: 'generic',
11
+ name: 'codemods',
12
+ placement: {parent: 'namespace:building-blocks', slot: 'guides', order: 50},
13
+ title: 'Codemods',
14
+ category: 'guide',
15
+ keywords: ['breaking change', 'migrate apps', 'integration codemod'],
16
+ description:
17
+ 'Ship codemods that `astryx upgrade` runs to migrate app code, and know which of them an app runs.',
18
+ sections: [
19
+ {
20
+ id: 'add-a-codemod',
21
+ title: 'Add a codemod',
22
+ content: [
23
+ {
24
+ type: 'prose',
25
+ text: '`integration add codemod` writes a codemod into a folder named after a version. Apps run it with `astryx upgrade` to migrate their code.',
26
+ },
27
+ {
28
+ type: 'code',
29
+ lang: 'bash',
30
+ code: 'npx astryx integration add codemod rename-delay --to 0.7.0',
31
+ },
32
+ {
33
+ type: 'code',
34
+ lang: 'text',
35
+ code: `codemods/
36
+ 0.7.0/
37
+ rename-delay.mjs # the codemod
38
+ rename-delay.test.mjs # skipped: a test file
39
+ __tests__/ # skipped: a test folder`,
40
+ },
41
+ {
42
+ type: 'prose',
43
+ text: "The first add declares `codemods: './codemods'` in `astryx.integration.mjs`. The codemod's id is its path inside the version folder, without the extension: `rename-delay`. An id must be unique across all version folders in the package.",
44
+ },
45
+ {
46
+ type: 'prose',
47
+ text: 'The loader skips `*.test.*`, `*.spec.*`, and `*.fixture.*` files and everything under `__tests__/` or `__fixtures__/`, so tests can sit beside the codemod. The folder name decides when an app runs the codemod; see "Choose when a codemod runs".',
48
+ },
49
+ ],
50
+ },
51
+ {
52
+ id: 'write-the-transform',
53
+ title: 'Write the transform',
54
+ content: [
55
+ {
56
+ type: 'prose',
57
+ text: 'A codemod default-exports a plain object with a `type`, a `title`, and a `transform` function. `transform` returns the new source, or `null` to leave the file as it is.',
58
+ },
59
+ {
60
+ type: 'code',
61
+ lang: 'js',
62
+ code: `// codemods/0.7.0/rename-delay.mjs
63
+ /** @type {import('@astryxdesign/cli/authoring').AstryxCodemod} */
64
+ export default {
65
+ type: 'code',
66
+ title: 'Rename AcmeCarousel delay to interval',
67
+ description: 'Renames the delay prop on AcmeCarousel.',
68
+ fileExtensions: ['.tsx', '.jsx'],
69
+ transform(file, api) {
70
+ const j = api.jscodeshift;
71
+ const root = j(file.source);
72
+ const props = root
73
+ .find(j.JSXOpeningElement, {name: {name: 'AcmeCarousel'}})
74
+ .find(j.JSXAttribute, {name: {name: 'delay'}});
75
+ if (props.size() === 0) return null;
76
+ props.forEach(path => {
77
+ path.node.name.name = 'interval';
78
+ });
79
+ return root.toSource();
80
+ },
81
+ };`,
82
+ },
83
+ {
84
+ type: 'prose',
85
+ text: "`type: 'code'` rewrites the app's source files that match `fileExtensions`. `type: 'config'` rewrites the app's `astryx.config` file instead, and runs before code codemods. `title` shows in the upgrade output, and `api.jscodeshift` is a jscodeshift instance for the file. Every field is in {@link generic:authoring}.",
86
+ },
87
+ ],
88
+ },
89
+ {
90
+ id: 'which-codemods-run',
91
+ title: 'Choose when a codemod runs',
92
+ content: [
93
+ {
94
+ type: 'prose',
95
+ text: "Two rules decide whether an app's `astryx upgrade` runs your codemods: the app's Core versions, and whether the app names your package.",
96
+ },
97
+ {
98
+ type: 'list',
99
+ style: 'ordered',
100
+ items: [
101
+ "Version folders are matched against the app's `@astryxdesign/core` versions, not your package's version. `upgrade --from <version>` runs each folder above `--from`, up to and including the Core version installed in the app. With Core 0.7.0 installed, `--from 0.6.3` runs `0.7.0/`, and `--from 0.7.0` runs nothing. A folder named after your own release, such as `1.0.0/`, waits until the app has Core 1.0.0.",
102
+ '`upgrade` runs your codemods only when the app lists your package in `integrations` in its `astryx.config`, or passes `--integration @acme/astryx-widgets`. Having your package installed is not enough: the run then skips your codemods with no warning.',
103
+ ],
104
+ },
105
+ ],
106
+ },
107
+ {
108
+ id: 'run-codemods-in-an-app',
109
+ title: 'Run codemods in an app',
110
+ content: [
111
+ {
112
+ type: 'prose',
113
+ text: 'An app previews codemods with `astryx upgrade` and writes the changes with `--apply`. Without `--apply`, nothing on disk changes.',
114
+ },
115
+ {
116
+ type: 'code',
117
+ lang: 'bash',
118
+ code: `# Preview each codemod and the files it would change
119
+ npx astryx upgrade --from 0.6.3 --integration @acme/astryx-widgets
120
+ # Write the changes
121
+ npx astryx upgrade --from 0.6.3 --integration @acme/astryx-widgets --apply`,
122
+ },
123
+ {
124
+ type: 'code',
125
+ lang: 'text',
126
+ code: `Integrations: @acme/astryx-widgets
127
+ 1 codemod to run (dry run)
128
+ Applying integration codemods...
129
+ Rename AcmeCarousel delay to interval (v0.7.0, @acme/astryx-widgets)
130
+ ! ~ src/Hero.tsx (would change)`,
131
+ },
132
+ {
133
+ type: 'prose',
134
+ text: "The count includes Core's codemods for the same versions, which run first and print above `Integrations:`. To run only yours, as when you test it, add `--codemod rename-delay`.",
135
+ },
136
+ {
137
+ type: 'prose',
138
+ text: '`--from` is the Core version the app had before it upgraded. The run scans `./src` unless the app passes `--path`, and it never writes a file the app marks as generated, vendored, or ignored; see {@link command:upgrade}. `upgrade --list` shows only Core codemods.',
139
+ },
140
+ {
141
+ type: 'prose',
142
+ text: "An integration manifest has no `hooks` field. Commands that run after codemods, such as a formatter, are the app's to set, in `hooks.postCodemod` in its `astryx.config`.",
143
+ },
144
+ ],
145
+ },
146
+ ],
147
+ };
@@ -0,0 +1,113 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file `astryx docs cli/integrations/components/describe-the-component/component-family`:
5
+ * author one ComponentDoc for several public exports in a component family.
6
+ */
7
+
8
+ /** @type {import('@astryxdesign/cli/authoring').ReferenceDoc} */
9
+ export const docs = {
10
+ type: 'generic',
11
+ name: 'component-family',
12
+ placement: {
13
+ parent: 'namespace:describe-the-component',
14
+ slot: 'guides',
15
+ order: 30,
16
+ },
17
+ title: 'Component family',
18
+ category: 'guide',
19
+ description:
20
+ 'Adapt a single-component doc when one module exposes several public components or hooks that belong to one family.',
21
+ sections: [
22
+ {
23
+ id: 'choose-the-family-shape',
24
+ title: 'Choose the family shape',
25
+ content: [
26
+ {
27
+ type: 'prose',
28
+ text: 'Start with a complete single-component doc. Convert its top-level `props` into a `components` array only when one source module or component directory exposes several public components or hooks as one family. The family doc keeps the shared usage guidance; each array entry owns one public export.',
29
+ },
30
+ {
31
+ type: 'list',
32
+ style: 'unordered',
33
+ items: [
34
+ 'Put the primary or most-used export first.',
35
+ 'Use a full entry when this file owns that export\'s description and signature.',
36
+ 'Use `props` for a component entry. Use `params` and `returns` for a hook entry.',
37
+ 'Do not add private implementation helpers or exports that people should not use directly.',
38
+ ],
39
+ },
40
+ {
41
+ type: 'reference',
42
+ target: 'schema:component-doc',
43
+ projection: {fields: ['components']},
44
+ presentation: 'full',
45
+ },
46
+ ],
47
+ },
48
+ {
49
+ id: 'document-the-family-inline',
50
+ title: 'Document the family inline',
51
+ content: [
52
+ {
53
+ type: 'code',
54
+ lang: 'javascript',
55
+ label: 'components/AcmeTabs.doc.mjs',
56
+ code: `/** @type {import('@astryxdesign/cli/authoring').ComponentDoc} */
57
+ export default {
58
+ type: 'component',
59
+ name: 'AcmeTabs',
60
+ displayName: 'Acme Tabs',
61
+ import: '@acme/astryx-widgets/components/AcmeTabs',
62
+ usage: {
63
+ description:
64
+ 'Switches between related views without leaving the page.',
65
+ },
66
+ components: [
67
+ {
68
+ name: 'AcmeTabs',
69
+ displayName: 'Acme Tabs',
70
+ description: 'Owns selection and lays out the tab list and panels.',
71
+ props: [
72
+ {
73
+ name: 'value',
74
+ type: 'string',
75
+ description: 'The selected tab value.',
76
+ required: true,
77
+ },
78
+ ],
79
+ },
80
+ {
81
+ name: 'AcmeTab',
82
+ displayName: 'Acme Tab',
83
+ description: 'Selects one view in Acme Tabs.',
84
+ props: [
85
+ {
86
+ name: 'value',
87
+ type: 'string',
88
+ description: 'The value this tab selects.',
89
+ required: true,
90
+ },
91
+ ],
92
+ },
93
+ ],
94
+ };`,
95
+ },
96
+ {
97
+ type: 'prose',
98
+ text: 'The public module named by `import` must export every component or hook named by a full entry.',
99
+ },
100
+ ],
101
+ },
102
+ {
103
+ id: 'give-a-member-its-own-file',
104
+ title: 'Give a member its own file',
105
+ content: [
106
+ {
107
+ type: 'prose',
108
+ text: 'When one family member needs its own doc, replace its full entry with `{name: \'MemberName\'}` and move the details into a sibling doc. The parent keeps the family relationship without copying the child\'s content. Continue with {@link generic:subcomponent}.',
109
+ },
110
+ ],
111
+ },
112
+ ],
113
+ };
@@ -0,0 +1,69 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file `astryx docs cli/integrations/components/component-imports`: make an
5
+ * integration component's documented import resolve from the packed package.
6
+ */
7
+
8
+ /** @type {import('@astryxdesign/cli/authoring').ReferenceDoc} */
9
+ export const docs = {
10
+ type: 'generic',
11
+ name: 'component-imports',
12
+ placement: {parent: 'namespace:components', slot: 'guides', order: 30},
13
+ title: 'Resolve the import',
14
+ category: 'guide',
15
+ description:
16
+ 'Keep the component doc import and package exports map aligned, then verify the packed package.',
17
+ sections: [
18
+ {
19
+ id: 'export-the-component',
20
+ title: 'Export the component',
21
+ content: [
22
+ {
23
+ type: 'prose',
24
+ text: 'Apps copy the component doc\'s `import` field into their code, so that exact specifier must resolve from your packed package. `integration add` writes it together with an `exports` entry in package.json.',
25
+ },
26
+ {
27
+ type: 'code',
28
+ lang: 'json',
29
+ label: 'package.json',
30
+ code: `"exports": {
31
+ "./components/AcmeCarousel": "./components/AcmeCarousel.tsx"
32
+ }`,
33
+ },
34
+ {
35
+ type: 'prose',
36
+ text: 'Add writes the entry only when package.json already has an `exports` map, so start every package with `"exports": {}`.',
37
+ },
38
+ ],
39
+ },
40
+ {
41
+ id: 'verify-the-packed-import',
42
+ title: 'Verify the packed import',
43
+ content: [
44
+ {
45
+ type: 'prose',
46
+ text: '`integration verify` installs the packed package in a temporary app, resolves each documented import, and checks that the module exports the documented component name.',
47
+ },
48
+ {
49
+ type: 'code',
50
+ lang: 'bash',
51
+ code: 'npx astryx integration verify',
52
+ },
53
+ {
54
+ type: 'list',
55
+ style: 'unordered',
56
+ items: [
57
+ '`component_import_unresolvable` means the exports map has no entry for the documented import.',
58
+ '`component_export_missing` means the module does not export the documented name, or package.json has no exports map.',
59
+ '`typescript_extension_in_specifier` means the public import ends in `.ts` or `.tsx`.',
60
+ ],
61
+ },
62
+ {
63
+ type: 'prose',
64
+ text: 'To import from the package root, set `import: \'@acme/astryx-widgets\'` and re-export the component from the file that `exports["."]` points to. See {@link command:integration verify}.',
65
+ },
66
+ ],
67
+ },
68
+ ],
69
+ };
@@ -0,0 +1,23 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file `astryx docs cli/integrations/components`: guides for adding and
5
+ * documenting components in an integration package.
6
+ */
7
+
8
+ /** @type {import('@astryxdesign/cli/authoring').NamespaceDoc} */
9
+ export const docs = {
10
+ type: 'namespace',
11
+ name: 'components',
12
+ placement: {parent: 'namespace:building-blocks', slot: 'guides', order: 10},
13
+ title: 'Components',
14
+ summary:
15
+ 'Add components to an integration, document their public contract, and make them work in every app that installs the package.',
16
+ keywords: ['integration component', 'ship a component', 'component docs'],
17
+ slots: {
18
+ guides: {
19
+ title: 'Components',
20
+ accepts: {kinds: ['generic', 'namespace']},
21
+ },
22
+ },
23
+ };
@@ -0,0 +1,23 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /** @file astryx docs cli/integrations/building-blocks/configuration — set how your integration behaves. */
4
+
5
+ /** @type {import('@astryxdesign/cli/authoring').NamespaceDoc} */
6
+ export const docs = {
7
+ type: 'namespace',
8
+ name: 'configuration',
9
+ placement: {parent: 'namespace:building-blocks', slot: 'guides', order: 60},
10
+ title: 'Configuration',
11
+ summary:
12
+ 'Set how your integration behaves in an app: agent guidance, debug and gap reports, and more as it grows.',
13
+ keywords: ['configuration', 'agent guidance', 'debug', 'gap reports'],
14
+ slots: {
15
+ guides: {title: 'Configuration', accepts: {kinds: ['generic', 'namespace']}},
16
+ },
17
+ blocks: [
18
+ {
19
+ type: 'prose',
20
+ text: 'Beyond the things you ship, an integration can set how it behaves in an app: the guidance it gives the AI agents working there, and the record it keeps of each CLI run. Open one below to set it up.',
21
+ },
22
+ ],
23
+ };
@@ -0,0 +1,182 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file `astryx docs cli/integrations/debug-and-gap-reports`: receive a record
5
+ * of each CLI run with `debug`, and handle `astryx gap-report` with
6
+ * `gapReport`, both named exports of the integration manifest.
7
+ */
8
+
9
+ /** @type {import('@astryxdesign/cli/authoring').ReferenceDoc} */
10
+ export const docs = {
11
+ type: 'generic',
12
+ name: 'debug-and-gap-reports',
13
+ placement: {parent: 'namespace:configuration', slot: 'guides', order: 20},
14
+ title: 'Debug and gap reports',
15
+ category: 'guide',
16
+ keywords: ['gap report', 'debug handler'],
17
+ description:
18
+ 'Receive a record of each CLI run in apps that use your package, and handle the gap reports they send about it.',
19
+ sections: [
20
+ {
21
+ id: 'record-runs-with-debug',
22
+ title: 'Record runs with debug',
23
+ content: [
24
+ {
25
+ type: 'prose',
26
+ text: 'Export a `debug` function from `astryx.integration.mjs`, and the CLI calls it once for each command run in an app that loads your package.',
27
+ },
28
+ {
29
+ type: 'code',
30
+ lang: 'js',
31
+ code: `// astryx.integration.mjs
32
+ import {appendFileSync} from 'node:fs';
33
+
34
+ /** @param {import('@astryxdesign/cli/authoring').DebugEvent} event */
35
+ export function debug(event) {
36
+ if (event.outcome !== 'ok') {
37
+ appendFileSync('acme-failed-runs.ndjson', JSON.stringify(event) + '\\n');
38
+ }
39
+ }
40
+
41
+ export default {
42
+ components: './components',
43
+ };`,
44
+ },
45
+ {
46
+ type: 'prose',
47
+ text: 'The event is a `DebugEvent` with `command`, `outcome`, `exitCode`, `durationMs`, `error`, and more, its values scrubbed (`redacted: true`). Every field is in {@link generic:authoring}.',
48
+ },
49
+ {
50
+ type: 'prose',
51
+ text: "Keep the function synchronous: the CLI calls it as the process exits and never waits for a promise. The app's own `debug` handler runs first, then yours. A handler that throws is skipped, and the command's output and exit code stay the same.",
52
+ },
53
+ {
54
+ type: 'prose',
55
+ text: "An app records every command only when its `astryx.config` names `integrations` or `debug`, as listing your package does. Otherwise your handler runs only for commands that load the app's project, such as `component` and `docs`, and not for `--version` or a mistyped command. In an app whose config names neither word, each of those commands also prints a warning on stderr.",
56
+ },
57
+ {
58
+ type: 'prose',
59
+ text: '`debug` is a named export, not a manifest field, so a CLI that does not know it ignores it and loads the rest of your manifest.',
60
+ },
61
+ ],
62
+ },
63
+ {
64
+ id: 'turn-off-debug-in-an-app',
65
+ title: 'Turn off debug in an app',
66
+ content: [
67
+ {
68
+ type: 'prose',
69
+ text: "An app can refuse every integration's `debug` handler and keep its own. It sets `inheritDebug` in its package.json:",
70
+ },
71
+ {
72
+ type: 'code',
73
+ lang: 'json',
74
+ code: '{"astryx": {"inheritDebug": false}}',
75
+ },
76
+ {
77
+ type: 'prose',
78
+ text: 'From then on, your handler no longer runs in that app.',
79
+ },
80
+ ],
81
+ },
82
+ {
83
+ id: 'handle-gap-reports',
84
+ title: 'Handle gap reports',
85
+ content: [
86
+ {
87
+ type: 'prose',
88
+ text: 'Export a `gapReport` handler, and `astryx gap-report` in an app sends it each gap report, such as a missing component or variant. The handler files the report and returns a receipt.',
89
+ },
90
+ {
91
+ type: 'code',
92
+ lang: 'js',
93
+ code: `/** @type {import('@astryxdesign/cli/authoring').GapReportHandler} */
94
+ export const gapReport = {
95
+ audience: 'public',
96
+ async handle(report, {signal}) {
97
+ if (report.target.package !== '@acme/astryx-widgets') return {status: 'skipped'};
98
+ const body = JSON.stringify(report);
99
+ const response = await fetch('https://tracker.example.com/issues', {method: 'POST', body, signal});
100
+ const {url} = await response.json();
101
+ return {status: 'filed', url};
102
+ },
103
+ };`,
104
+ },
105
+ {
106
+ type: 'prose',
107
+ text: 'Every handler in the app gets every report, so check `report.target.package` and skip reports about other packages. The receipt `status` is one of:',
108
+ },
109
+ {
110
+ type: 'table',
111
+ headers: ['`status`', 'Meaning'],
112
+ rows: [
113
+ [
114
+ '`filed`',
115
+ 'You created or queued the report. Return `url` or `message`.',
116
+ ],
117
+ [
118
+ '`routed_only`',
119
+ 'You point the caller to where to file it. `url` is required.',
120
+ ],
121
+ ['`skipped`', 'You chose not to act, for example on a duplicate.'],
122
+ ],
123
+ },
124
+ {
125
+ type: 'prose',
126
+ text: 'The CLI waits 30 seconds, then aborts `signal`. A throw, a timeout, or an invalid receipt fails your delivery, and the command exits 1; the other handlers still run. Like `debug`, `gapReport` is a named export that older CLIs ignore.',
127
+ },
128
+ ],
129
+ },
130
+ {
131
+ id: 'ask-before-filing-in-public',
132
+ title: 'Ask before filing in public',
133
+ content: [
134
+ {
135
+ type: 'prose',
136
+ text: "Set `audience: 'public'` when your handler writes somewhere the public can read. The CLI runs it only when the caller passes `--confirm-public`; an `'internal'` handler always runs.",
137
+ },
138
+ {
139
+ type: 'code',
140
+ lang: 'bash',
141
+ code: "npx astryx gap-report AcmeCarousel --category missing_variant --reason 'Need a vertical layout'",
142
+ },
143
+ {
144
+ type: 'code',
145
+ lang: 'text',
146
+ code: `handlerType: integration
147
+ handler: @acme/astryx-widgets
148
+ audience: public
149
+ status: consent_required
150
+ message: Rerun with --confirm-public to file this report.`,
151
+ },
152
+ {
153
+ type: 'prose',
154
+ text: 'With `--confirm-public`, the same delivery reads `status: filed` and shows your `url`. The report goes to the package named by `--package`, else the package that owns the component, else Core.',
155
+ },
156
+ ],
157
+ },
158
+ {
159
+ id: 'fall-back-to-issues-url',
160
+ title: 'Fall back to issuesUrl',
161
+ content: [
162
+ {
163
+ type: 'prose',
164
+ text: "When the app has no `gapReport` handler at all, the CLI routes the report to the target package's `issuesUrl` from its manifest instead.",
165
+ },
166
+ {
167
+ type: 'list',
168
+ style: 'unordered',
169
+ items: [
170
+ 'A GitHub issues URL, such as `https://github.com/acme/widgets/issues`, gets an issue filed with the GitHub CLI, `gh`, once the caller passes `--confirm-public`.',
171
+ 'Any other URL comes back as a `routed_only` receipt for the caller to open.',
172
+ 'With no `issuesUrl`, the command fails: `Package "@acme/astryx-widgets" provides neither a report handler nor an issues URL.`',
173
+ ],
174
+ },
175
+ {
176
+ type: 'prose',
177
+ text: 'One handler anywhere in the app, from the app or from any package, turns the fallback off for every report. See {@link command:gap-report}.',
178
+ },
179
+ ],
180
+ },
181
+ ],
182
+ };