@astryxdesign/cli 0.6.3-canary.dea6813 → 0.6.3-canary.df1837b

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 (284) hide show
  1. package/README.md +79 -58
  2. package/api/blog/blog.doc.mjs +1 -0
  3. package/api/build/build.doc.mjs +1 -0
  4. package/api/component/component.doc.mjs +2 -1
  5. package/api/component/component.mjs +3 -3
  6. package/api/component/component.type.d.mts +5 -4
  7. package/api/component/component.type.mjs +5 -4
  8. package/api/component/detail/blocks/blocks.d.mts +2 -1
  9. package/api/component/detail/blocks/blocks.mjs +4 -3
  10. package/api/component/list/list.d.mts +0 -5
  11. package/api/component/list/list.mjs +37 -9
  12. package/api/discover/discover.doc.mjs +1 -0
  13. package/api/docs/_adapter.d.mts +3 -8
  14. package/api/docs/_adapter.mjs +13 -105
  15. package/api/docs/docs.doc.mjs +1 -0
  16. package/api/docs/list/list.mjs +3 -7
  17. package/api/doctor/doctor.d.mts +25 -3
  18. package/api/doctor/doctor.doc.mjs +1 -0
  19. package/api/doctor/doctor.mjs +185 -13
  20. package/api/doctor/doctor.test.mjs +326 -1
  21. package/api/gap-report/gap-report.doc.mjs +1 -0
  22. package/api/hook/_adapter.mjs +19 -5
  23. package/api/hook/hook.doc.mjs +1 -0
  24. package/api/hook/list/list.d.mts +1 -1
  25. package/api/hook/list/list.mjs +69 -17
  26. package/api/init/init.doc.mjs +1 -0
  27. package/api/integration/add-contribution.mjs +7 -7
  28. package/api/integration/add-contribution.test.mjs +37 -3
  29. package/api/integration/add-theme.mjs +34 -64
  30. package/api/integration/add-theme.test.mjs +105 -21
  31. package/api/integration/authoring-checks.test.mjs +8 -4
  32. package/api/integration/integration-block-exports.test.mjs +10 -6
  33. package/api/integration/integrationAdd.doc.mjs +1 -0
  34. package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
  35. package/api/integration/integrationAddCodemod.doc.mjs +1 -0
  36. package/api/integration/integrationAddComponent.doc.mjs +1 -0
  37. package/api/integration/integrationAddDoc.doc.mjs +1 -0
  38. package/api/integration/integrationAddTemplate.doc.mjs +1 -0
  39. package/api/integration/integrationAddTheme.doc.mjs +6 -5
  40. package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
  41. package/api/integration/integrationDocConflicts.doc.mjs +1 -0
  42. package/api/integration/integrationPackCheck.doc.mjs +1 -0
  43. package/api/integration/integrationTemplateConflicts.doc.mjs +1 -0
  44. package/api/integration/pack-check.test.mjs +17 -47
  45. package/api/integration/summarizeIssues.doc.mjs +1 -0
  46. package/api/integration/validate-integration-fixes.test.mjs +1389 -0
  47. package/api/integration/validate-integration.mjs +50 -102
  48. package/api/integration/validate-integration.test.mjs +85 -23
  49. package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
  50. package/api/integration/validateIntegration.doc.mjs +1 -0
  51. package/api/json/assertResponse.doc.mjs +1 -0
  52. package/api/json/isError.doc.mjs +1 -0
  53. package/api/json/parseResponse.doc.mjs +1 -0
  54. package/api/layout/layoutCheck.doc.mjs +1 -0
  55. package/api/layout/layoutExpand.doc.mjs +1 -0
  56. package/api/layout/layoutGrammar.doc.mjs +1 -0
  57. package/api/search/search.doc.mjs +1 -0
  58. package/api/search/search.mjs +16 -6
  59. package/api/swizzle/swizzle.doc.mjs +1 -0
  60. package/api/template/template-suffix.test.mjs +41 -21
  61. package/api/template/template.doc.mjs +1 -0
  62. package/api/theme/_adapter.d.mts +2 -3
  63. package/api/theme/_adapter.mjs +4 -5
  64. package/api/theme/add/add.binary.test.mjs +10 -17
  65. package/api/theme/add/add.test.mjs +14 -1
  66. package/api/theme/generateTonalPalette.doc.mjs +1 -0
  67. package/api/theme/integration-themes.test.mjs +39 -28
  68. package/api/theme/list/list.test.mjs +19 -20
  69. package/api/theme/listThemes.doc.mjs +6 -5
  70. package/api/theme/themeAdd.doc.mjs +4 -3
  71. package/api/theme/themeBuild.doc.mjs +1 -0
  72. package/api/theme/themeList.doc.mjs +6 -3
  73. package/api/theme/themeListAvailable.doc.mjs +5 -3
  74. package/api/theme/themePaletteGenerate.doc.mjs +1 -0
  75. package/api/theme/themeTargets.doc.mjs +1 -0
  76. package/api/theme/themeTemplate.doc.mjs +1 -0
  77. package/api/upgrade/_adapter.d.mts +32 -5
  78. package/api/upgrade/_adapter.mjs +97 -69
  79. package/api/upgrade/provider-agreement.test.mjs +152 -0
  80. package/api/upgrade/run/run.mjs +356 -59
  81. package/api/upgrade/upgrade.doc.mjs +6 -1
  82. package/api/upgrade/upgrade.type.d.mts +34 -0
  83. package/api/upgrade/upgrade.type.mjs +15 -0
  84. package/assets/codemods/__tests__/runner.test.mjs +330 -8
  85. package/assets/codemods/integration-discovery.mjs +8 -2
  86. package/assets/codemods/integration-discovery.test.mjs +15 -0
  87. package/assets/codemods/integration-runner.mjs +56 -4
  88. package/assets/codemods/integration-runner.protection.test.mjs +153 -0
  89. package/assets/codemods/run-codemod.mjs +177 -34
  90. package/assets/codemods/runner.mjs +350 -102
  91. package/assets/codemods/transform-prop.mjs +109 -0
  92. package/assets/codemods/transform-prop.test.mjs +95 -0
  93. package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
  94. package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
  95. package/assets/codemods/transforms/next/index.mjs +19 -1
  96. package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
  97. package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
  98. package/assets/codemods/transforms/v0.0.14/__tests__/rename-status-variants.test.mjs +86 -165
  99. package/assets/codemods/transforms/v0.0.14/rename-status-variants.mjs +72 -210
  100. package/assets/codemods/transforms/v0.1.8/__tests__/rename-avatar-size-scale.test.mjs +83 -115
  101. package/assets/codemods/transforms/v0.1.8/rename-avatar-size-scale.mjs +57 -186
  102. package/assets/docs/cli-integrations.doc.mjs +30 -30
  103. package/assets/docs/cli.doc.mjs +15 -0
  104. package/assets/docs/theme.doc.mjs +1 -1
  105. package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
  106. package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
  107. package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
  108. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.doc.mjs +14 -0
  109. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaInlineRail.tsx +61 -0
  110. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.doc.mjs +14 -0
  111. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaOverscrollChaining.tsx +126 -0
  112. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.doc.mjs +15 -0
  113. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaShowcase.tsx +86 -0
  114. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.doc.mjs +14 -0
  115. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyGroupHeaders.tsx +99 -0
  116. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.doc.mjs +14 -0
  117. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaStickyPassthrough.tsx +122 -0
  118. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.doc.mjs +14 -0
  119. package/assets/templates/blocks/components/ScrollableArea/ScrollableAreaTwoAxisBoard.tsx +95 -0
  120. package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
  121. package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
  122. package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
  123. package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
  124. package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
  125. package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
  126. package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
  127. package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
  128. package/authoring/codemod/codemod.doc.mjs +1 -1
  129. package/authoring/codemod/type.ts +12 -0
  130. package/authoring/config/config.doc.mjs +1 -1
  131. package/authoring/debug/debug.doc.d.mts +11 -0
  132. package/authoring/debug/debug.doc.mjs +182 -0
  133. package/authoring/doctypes/base/graph-fields.doc.mjs +1 -1
  134. package/authoring/doctypes/command/command.doc.mjs +1 -1
  135. package/authoring/doctypes/command/type.ts +1 -1
  136. package/authoring/doctypes/component/type.ts +2 -2
  137. package/authoring/doctypes/doctypes-new.test.mjs +48 -6
  138. package/authoring/doctypes/enum/enum.doc.mjs +1 -1
  139. package/authoring/doctypes/enum/type.ts +1 -1
  140. package/authoring/doctypes/function/function.doc.mjs +1 -1
  141. package/authoring/doctypes/function/type.ts +1 -1
  142. package/authoring/doctypes/hook/type.ts +2 -2
  143. package/authoring/doctypes/load-contract.test.mjs +2 -1
  144. package/authoring/doctypes/parse.d.mts +4 -2
  145. package/authoring/doctypes/parse.mjs +7 -3
  146. package/authoring/doctypes/reference/reference.doc.mjs +1 -1
  147. package/authoring/doctypes/reference/type.ts +2 -2
  148. package/authoring/doctypes/schema/schema.doc.mjs +1 -1
  149. package/authoring/doctypes/schema/type.ts +1 -2
  150. package/authoring/doctypes/template/template.doc.mjs +3 -3
  151. package/authoring/doctypes/theme/parse.d.mts +35 -0
  152. package/authoring/doctypes/theme/parse.mjs +76 -0
  153. package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
  154. package/authoring/doctypes/theme/theme.doc.mjs +79 -0
  155. package/authoring/doctypes/theme/type.ts +42 -0
  156. package/authoring/doctypes/types.ts +2 -1
  157. package/authoring/gap-report/gap-report.doc.d.mts +12 -0
  158. package/authoring/gap-report/gap-report.doc.mjs +183 -0
  159. package/authoring/index.d.mts +1 -0
  160. package/authoring/index.d.ts +6 -4
  161. package/authoring/index.mjs +2 -1
  162. package/authoring/integration/integration.doc.mjs +2 -2
  163. package/authoring/integration/type.ts +3 -9
  164. package/clients/cli/__tests__/cliManifest.test.ts +27 -29
  165. package/clients/cli/commands/blog.doc.mjs +1 -1
  166. package/clients/cli/commands/build.doc.mjs +1 -1
  167. package/clients/cli/commands/component-package.test.mjs +28 -0
  168. package/clients/cli/commands/component.doc.mjs +1 -1
  169. package/clients/cli/commands/discover.doc.mjs +1 -1
  170. package/clients/cli/commands/docs.doc.mjs +1 -1
  171. package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
  172. package/clients/cli/commands/doctor-integration-docs.doc.mjs +1 -1
  173. package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -1
  174. package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
  175. package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
  176. package/clients/cli/commands/doctor-integration.test.mjs +15 -7
  177. package/clients/cli/commands/doctor.doc.mjs +1 -1
  178. package/clients/cli/commands/gap-report.doc.mjs +1 -1
  179. package/clients/cli/commands/hook.doc.mjs +1 -1
  180. package/clients/cli/commands/init.doc.mjs +1 -1
  181. package/clients/cli/commands/integration-add.controls.test.mjs +1 -1
  182. package/clients/cli/commands/integration-add.doc.mjs +1 -1
  183. package/clients/cli/commands/integration-pack.doc.mjs +1 -1
  184. package/clients/cli/commands/integration-real-world.test.mjs +3 -9
  185. package/clients/cli/commands/integration.doc.mjs +1 -1
  186. package/clients/cli/commands/layout-check.doc.mjs +1 -1
  187. package/clients/cli/commands/layout-expand.doc.mjs +1 -1
  188. package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
  189. package/clients/cli/commands/layout.doc.mjs +1 -1
  190. package/clients/cli/commands/manifest.doc.mjs +1 -1
  191. package/clients/cli/commands/search.doc.mjs +1 -1
  192. package/clients/cli/commands/swizzle.doc.mjs +1 -1
  193. package/clients/cli/commands/template.doc.mjs +1 -1
  194. package/clients/cli/commands/theme-add.doc.mjs +2 -2
  195. package/clients/cli/commands/theme-build.doc.mjs +1 -1
  196. package/clients/cli/commands/theme-list.doc.mjs +2 -2
  197. package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
  198. package/clients/cli/commands/theme-palette.doc.mjs +1 -1
  199. package/clients/cli/commands/theme-targets.doc.mjs +1 -1
  200. package/clients/cli/commands/theme-template.doc.mjs +1 -1
  201. package/clients/cli/commands/theme.doc.mjs +1 -1
  202. package/clients/cli/commands/upgrade.doc.mjs +3 -2
  203. package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
  204. package/clients/cli/commands/upgrade.mjs +3 -0
  205. package/clients/cli/lib/hook-format.mjs +14 -5
  206. package/foundation/config/project-themes.test.mjs +11 -19
  207. package/foundation/config/project.d.mts +8 -0
  208. package/foundation/config/project.mjs +50 -21
  209. package/foundation/config/project.test.mjs +3 -16
  210. package/foundation/discovery/authoring-self-docs.d.mts +6 -0
  211. package/foundation/discovery/authoring-self-docs.mjs +17 -7
  212. package/foundation/discovery/authoring-surface.d.mts +74 -0
  213. package/foundation/discovery/authoring-surface.mjs +525 -0
  214. package/foundation/discovery/authoring-surface.test.mjs +392 -0
  215. package/foundation/discovery/cli-self-docs.d.mts +113 -0
  216. package/foundation/discovery/cli-self-docs.mjs +514 -0
  217. package/foundation/discovery/cli-self-docs.test.mjs +437 -0
  218. package/foundation/discovery/component-loader.d.mts +35 -38
  219. package/foundation/discovery/component-loader.mjs +53 -222
  220. package/foundation/discovery/docs-discovery.d.mts +3 -2
  221. package/foundation/discovery/docs-discovery.mjs +8 -12
  222. package/foundation/discovery/docs-discovery.test.mjs +8 -5
  223. package/foundation/discovery/template-adapter.d.mts +7 -0
  224. package/foundation/discovery/template-adapter.mjs +27 -40
  225. package/foundation/discovery/template-adapter.test.mjs +15 -0
  226. package/foundation/discovery/theme-discovery.d.mts +67 -7
  227. package/foundation/discovery/theme-discovery.mjs +916 -186
  228. package/foundation/discovery/theme-discovery.test.mjs +613 -219
  229. package/foundation/doc-compiler/bundle.d.mts +47 -0
  230. package/foundation/doc-compiler/bundle.mjs +218 -0
  231. package/foundation/doc-compiler/bundle.test.mjs +255 -0
  232. package/foundation/doc-compiler/compile.d.mts +200 -0
  233. package/foundation/doc-compiler/compile.mjs +254 -5
  234. package/foundation/doc-compiler/diagnostics.d.mts +126 -0
  235. package/foundation/doc-compiler/diagnostics.mjs +277 -0
  236. package/foundation/doc-compiler/doc-compiler.test.mjs +28 -1
  237. package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
  238. package/foundation/doc-compiler/import.d.mts +24 -0
  239. package/foundation/doc-compiler/import.mjs +59 -0
  240. package/foundation/doc-compiler/inputs.d.mts +102 -0
  241. package/foundation/doc-compiler/inputs.mjs +286 -0
  242. package/foundation/doc-compiler/inputs.test.mjs +299 -0
  243. package/foundation/doc-compiler/ir.d.mts +13 -0
  244. package/foundation/doc-compiler/ir.mjs +189 -12
  245. package/foundation/doc-compiler/lower-doc.test.mjs +492 -0
  246. package/foundation/doc-compiler/overlays.d.mts +37 -0
  247. package/foundation/doc-compiler/overlays.mjs +206 -0
  248. package/foundation/doc-compiler/parse-readable.d.mts +9 -0
  249. package/foundation/doc-compiler/parse-readable.mjs +29 -0
  250. package/foundation/doc-compiler/read.d.mts +126 -0
  251. package/foundation/doc-compiler/read.mjs +320 -0
  252. package/foundation/doc-compiler/read.test.mjs +313 -0
  253. package/foundation/doc-compiler/source.d.mts +33 -0
  254. package/foundation/doc-compiler/source.mjs +128 -0
  255. package/foundation/fs/file-protection.d.mts +33 -0
  256. package/foundation/fs/file-protection.mjs +825 -0
  257. package/foundation/fs/file-protection.test.mjs +250 -0
  258. package/foundation/integrations/autolink.d.mts +58 -1
  259. package/foundation/integrations/autolink.mjs +143 -57
  260. package/foundation/integrations/contribution-fixes.d.mts +145 -0
  261. package/foundation/integrations/contribution-fixes.mjs +1284 -0
  262. package/foundation/integrations/contribution-inventory.d.mts +1 -1
  263. package/foundation/integrations/contribution-inventory.mjs +17 -20
  264. package/foundation/integrations/contribution-inventory.test.mjs +67 -27
  265. package/foundation/integrations/integrations.d.mts +3 -0
  266. package/foundation/integrations/integrations.mjs +11 -97
  267. package/foundation/integrations/provider-ledger.test.mjs +275 -0
  268. package/foundation/integrations/provider-resolution.d.mts +152 -0
  269. package/foundation/integrations/provider-resolution.mjs +576 -0
  270. package/foundation/integrations/provider-resolution.test.mjs +369 -0
  271. package/foundation/integrations/theme-descriptor.d.mts +8 -0
  272. package/foundation/integrations/theme-descriptor.mjs +44 -0
  273. package/foundation/integrations/validate-contributions.mjs +104 -10
  274. package/foundation/response/error-codes.d.mts +3 -1
  275. package/foundation/response/error-codes.d.ts +2 -0
  276. package/foundation/response/error-codes.doc.mjs +12 -2
  277. package/foundation/response/error-codes.mjs +7 -1
  278. package/foundation/response/error-codes.test.mjs +55 -11
  279. package/foundation/response/response-types.doc.mjs +8 -8
  280. package/foundation/response/response-types.doc.test.mjs +158 -0
  281. package/foundation/response/response.doc.mjs +1 -1
  282. package/foundation/text/string-utils.mjs +22 -10
  283. package/package.json +10 -9
  284. package/assets/templates/themes/manifest.json +0 -95
@@ -10,24 +10,29 @@
10
10
  * @output Catalog access, the compiler input for a topic, and the compiled
11
11
  * node for it: lowered (overlaid, extensions merged, keys stamped) or linked
12
12
  * (token references resolved too), memoized per catalog.
13
- * @position Sits beside docs.mjs (api/docs/). Loads authored files and hands
14
- * them to foundation/doc-compiler, so no leaf, doctor check or search loads,
15
- * merges, or resolves docs on its own. Discovery itself lives in
13
+ * @position Sits beside docs.mjs (api/docs/). Hands topics to
14
+ * foundation/doc-compiler (which loads their files) and memoizes the nodes
15
+ * per catalog, so no leaf, doctor check or search loads, merges, or resolves
16
+ * docs on its own. Discovery itself lives in
16
17
  * foundation/discovery/docs-discovery, which the catalog comes from.
17
18
  */
18
19
 
19
- import * as fs from 'node:fs';
20
- import * as path from 'node:path';
21
- import {pathToFileURL} from 'node:url';
22
20
  import {Project} from '../../foundation/config/project.mjs';
23
21
  import {DocsCatalog} from '../../foundation/discovery/docs-discovery.mjs';
24
22
  import {
25
23
  linkReferenceTopic,
26
24
  lowerReferenceTopic,
27
25
  } from '../../foundation/doc-compiler/compile.mjs';
26
+ import {
27
+ deepFreeze,
28
+ loadTopicInput,
29
+ OVERLAY_LANGUAGES,
30
+ overlayLanguages,
31
+ } from '../../foundation/doc-compiler/read.mjs';
28
32
  import {AstryxError} from '../error.mjs';
29
33
  import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
30
- import {parseDoc} from '../../authoring/doctypes/parse.mjs';
34
+
35
+ export {OVERLAY_LANGUAGES, overlayLanguages};
31
36
 
32
37
  /**
33
38
  * The project's topics: the built-in ones plus whatever the configured
@@ -51,34 +56,6 @@ export async function loadDocsCatalog(cwd = process.cwd()) {
51
56
  }
52
57
  }
53
58
 
54
- /** The localized overlays a docs read can apply. */
55
- export const OVERLAY_LANGUAGES = ['zh', 'dense'];
56
-
57
- /**
58
- * Where the `lang` overlay of a doc file lives: `{topic}.doc.{lang}.mjs`.
59
- * @param {string} docPath
60
- * @param {string} lang
61
- * @returns {string}
62
- */
63
- function overlayPath(docPath, lang) {
64
- return path.join(
65
- path.dirname(docPath),
66
- `${path.basename(docPath, '.doc.mjs')}.doc.${lang}.mjs`,
67
- );
68
- }
69
-
70
- /**
71
- * The overlay languages a topic ships for its own file or any extension.
72
- * @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
73
- * @returns {string[]}
74
- */
75
- export function overlayLanguages(entry) {
76
- const files = [entry.path, ...entry.extensions.map(ext => ext.path)];
77
- return OVERLAY_LANGUAGES.filter(lang =>
78
- files.some(file => fs.existsSync(overlayPath(file, lang))),
79
- );
80
- }
81
-
82
59
  /**
83
60
  * The overlay a read applies: none for the authored language.
84
61
  * @param {string | null | undefined} lang
@@ -88,61 +65,6 @@ function overlayLanguage(lang) {
88
65
  return lang && lang !== 'en' ? lang : null;
89
66
  }
90
67
 
91
- /**
92
- * Load one authored file and the overlay for `lang`. A failure is recorded on
93
- * the result, not thrown, so the compiler reports it in reading order.
94
- * @param {string} docPath
95
- * @param {string | null} lang
96
- * @returns {Promise<import('../../foundation/doc-compiler/compile.mjs').AuthoredFile>}
97
- */
98
- async function loadAuthoredFile(docPath, lang) {
99
- const file = path.basename(docPath);
100
- let doc;
101
- try {
102
- const mod = await import(pathToFileURL(docPath).href);
103
- doc = parseDoc(mod.docs ?? mod.default, file);
104
- } catch (error) {
105
- return {file, error};
106
- }
107
- if (!lang) return {file, doc};
108
- const translationPath = overlayPath(docPath, lang);
109
- if (!fs.existsSync(translationPath)) return {file, doc};
110
- try {
111
- const translationMod = await import(pathToFileURL(translationPath).href);
112
- return {
113
- file,
114
- doc,
115
- overlay: translationMod.docsZh || translationMod.docsDense || null,
116
- };
117
- } catch (overlayError) {
118
- return {file, doc, overlayError};
119
- }
120
- }
121
-
122
- /**
123
- * Everything the compiler needs for one topic, read from disk.
124
- * @param {import('../../foundation/discovery/docs-discovery.mjs').DocsTopicEntry} entry
125
- * @param {string | null} lang
126
- * @returns {Promise<import('../../foundation/doc-compiler/compile.mjs').ReferenceTopicInput>}
127
- */
128
- async function loadCompilerInput(entry, lang) {
129
- const extensions = [];
130
- for (const extension of entry.extensions) {
131
- extensions.push({
132
- ...(await loadAuthoredFile(extension.path, lang)),
133
- provider: extension.package,
134
- });
135
- }
136
- return {
137
- id: entry.name,
138
- provider: entry.package,
139
- replaces: entry.replaces ?? null,
140
- lang,
141
- base: await loadAuthoredFile(entry.path, lang),
142
- extensions,
143
- };
144
- }
145
-
146
68
  /** @type {WeakMap<DocsCatalog, Map<string, Promise<import('../../foundation/doc-compiler/compile.mjs').CompiledReferenceNode>>>} */
147
69
  const loweredByCatalog = new WeakMap();
148
70
 
@@ -166,7 +88,7 @@ export function lowerTopic(catalog, entry, lang = null) {
166
88
  const key = `${entry.name.toLowerCase()}\u0000${overlay ?? ''}`;
167
89
  let lowered = cache.get(key);
168
90
  if (!lowered) {
169
- lowered = loadCompilerInput(entry, overlay).then(input =>
91
+ lowered = loadTopicInput(entry, overlay).then(input =>
170
92
  deepFreeze(lowerReferenceTopic(input)),
171
93
  );
172
94
  cache.set(key, lowered);
@@ -174,20 +96,6 @@ export function lowerTopic(catalog, entry, lang = null) {
174
96
  return lowered;
175
97
  }
176
98
 
177
- /**
178
- * Freeze a value and everything in it.
179
- * @template T
180
- * @param {T} value
181
- * @returns {T}
182
- */
183
- function deepFreeze(value) {
184
- if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {
185
- Object.freeze(value);
186
- for (const child of Object.values(value)) deepFreeze(child);
187
- }
188
- return value;
189
- }
190
-
191
99
  /**
192
100
  * How a token reference finds its target: the topic it names in `catalog`,
193
101
  * lowered for the same language.
@@ -11,6 +11,7 @@ export const doc = {
11
11
  type: 'function',
12
12
  kind: 'api',
13
13
  name: 'docs',
14
+ namespace: 'cli/api',
14
15
  displayName: 'docs()',
15
16
  summary:
16
17
  'Read the reference docs: list every topic, one topic\'s sections, one section, or a whole topic.',
@@ -14,7 +14,7 @@
14
14
  * @position Leaf under api/docs. Sibling of detail; both share _adapter.mjs.
15
15
  */
16
16
 
17
- import {pathToFileURL} from 'node:url';
17
+ import {loadTopicFile} from '../../../foundation/doc-compiler/read.mjs';
18
18
  import {loadDocsCatalog} from '../_adapter.mjs';
19
19
 
20
20
  /**
@@ -29,12 +29,8 @@ export async function list({cwd} = {}) {
29
29
  for (const entry of catalog.entries()) {
30
30
  let description = entry.description ?? '';
31
31
  if (entry.description == null) {
32
- try {
33
- const mod = await import(pathToFileURL(entry.path).href);
34
- description = (mod.docs ?? mod.default)?.description ?? '';
35
- } catch {
36
- description = '';
37
- }
32
+ const file = await loadTopicFile(entry.path, null);
33
+ description = file.doc?.description ?? '';
38
34
  }
39
35
  /** @type {import('../docs.type.mjs').DocsListEntry} */
40
36
  const listed = {
@@ -100,12 +100,34 @@ export function checkPackageManager(ctx: DoctorContext): DoctorCheck;
100
100
  export function checkProviderIdentity(ctx: DoctorContext): DoctorCheck;
101
101
  /**
102
102
  * Every authoring self-doc is reachable from `astryx docs authoring`, loads,
103
- * and fits in one read. The audit is imported here, inside the try, so a
104
- * malformed self-doc is reported rather than taking Doctor down.
103
+ * and fits in one read, and every type `@astryxdesign/cli/authoring` exports
104
+ * has its doc there: the self-doc beside the module that declares it. The
105
+ * audits are imported here, inside the try, so a malformed self-doc is
106
+ * reported rather than taking Doctor down.
105
107
  * @param {DoctorContext} [_ctx]
108
+ * @param {{root?: string, sources?: string[], topicKeys?: Set<string> | null}} [options]
109
+ * Another authoring tree, list, or topic index to audit (for tests).
106
110
  * @returns {Promise<DoctorCheck>}
107
111
  */
108
- export function checkAuthoringDocs(_ctx?: DoctorContext): Promise<DoctorCheck>;
112
+ export function checkAuthoringDocs(_ctx?: DoctorContext, options?: {
113
+ root?: string;
114
+ sources?: string[];
115
+ topicKeys?: Set<string> | null;
116
+ }): Promise<DoctorCheck>;
117
+ /**
118
+ * Every command, API function, schema, and enum doc the CLI ships declares a
119
+ * namespace, and the topic that namespace names reads it: `astryx docs cli`
120
+ * for `cli/commands` and `cli/api`, `astryx docs authoring` for `authoring`.
121
+ * @param {DoctorContext | Partial<DoctorContext>} _ctx
122
+ * @param {{root?: string, sources?: string[], authoringSources?: string[]}} [options]
123
+ * test seams: the CLI root, the docs to audit, and the authoring topic's list
124
+ * @returns {Promise<DoctorCheck>}
125
+ */
126
+ export function checkCliDocs(_ctx: DoctorContext | Partial<DoctorContext>, options?: {
127
+ root?: string;
128
+ sources?: string[];
129
+ authoringSources?: string[];
130
+ }): Promise<DoctorCheck>;
109
131
  /**
110
132
  * Every topic reads progressively, in every language it ships: it loads, its
111
133
  * section index and each of its sections fit in one read, and no contributed
@@ -11,6 +11,7 @@ export const doc = {
11
11
  type: 'function',
12
12
  kind: 'api',
13
13
  name: 'doctor',
14
+ namespace: 'cli/api',
14
15
  displayName: 'doctor()',
15
16
  summary: 'Read-only project + environment health check.',
16
17
  description:
@@ -34,8 +34,8 @@ import {
34
34
  docsIndexBytes,
35
35
  oversizedDocSections,
36
36
  } from '../../foundation/discovery/docs-output-budget.mjs';
37
- import {compileTopic, overlayLanguages} from '../docs/_adapter.mjs';
38
- import {detailView} from '../../foundation/doc-compiler/lenses.mjs';
37
+ import {compileTopic, lowerTopic, overlayLanguages} from '../docs/_adapter.mjs';
38
+ import {detailView, indexView} from '../../foundation/doc-compiler/lenses.mjs';
39
39
  import {semverCompare, isValidSemver, satisfiesRange} from '../../foundation/env/semver.mjs';
40
40
 
41
41
  /**
@@ -721,38 +721,144 @@ function joinProblems(problems) {
721
721
  : `${problems.length} problems: ${problems.join('; ')}`;
722
722
  }
723
723
 
724
+ /** How the self-doc audit's problems are fixed. */
725
+ const AUTHORING_DOCS_FIX =
726
+ 'List every authoring self-doc in AUTHORING_SELF_DOCS, fix the one that fails to load, and split a section that is too large.';
727
+
728
+ /** How the public-surface audit's problems are fixed. */
729
+ const AUTHORING_SURFACE_FIX =
730
+ 'Put a self-doc beside each module whose types @astryxdesign/cli/authoring exports and list it in AUTHORING_SELF_DOCS; export what each listed self-doc documents, or remove that self-doc.';
731
+
732
+ /** Types one problem names before it counts the rest. */
733
+ const NAMED_TYPES = 40;
734
+
735
+ /**
736
+ * @param {string[]} names
737
+ * @returns {string}
738
+ */
739
+ function nameTypes(names) {
740
+ return names.length <= NAMED_TYPES
741
+ ? names.join(', ')
742
+ : `${names.slice(0, NAMED_TYPES).join(', ')} and ${names.length - NAMED_TYPES} more`;
743
+ }
744
+
745
+ /**
746
+ * The section keys `astryx docs authoring --index` lists, read the way that
747
+ * command reads them.
748
+ * @returns {Promise<{keys: Set<string>} | {keys: null, error: string}>}
749
+ */
750
+ async function authoringTopicKeys() {
751
+ try {
752
+ const catalog = DocsCatalog.fromBuiltins();
753
+ const entry = catalog.resolve('authoring');
754
+ if (!entry) return {keys: null, error: 'it is not a built-in topic'};
755
+ const index = indexView(await lowerTopic(catalog, entry));
756
+ return {keys: new Set(index.sections.map(section => section.id))};
757
+ } catch (err) {
758
+ return {
759
+ keys: null,
760
+ error: err instanceof Error ? err.message : String(err),
761
+ };
762
+ }
763
+ }
764
+
765
+ /**
766
+ * @param {Awaited<ReturnType<typeof import('../../foundation/discovery/authoring-surface.mjs').auditAuthoringSurface>>} surface
767
+ * @returns {string[]}
768
+ */
769
+ function surfaceProblems(surface) {
770
+ /** @type {string[]} */
771
+ const problems = [];
772
+ if (surface.types === 0 && surface.untraced.length === 0) {
773
+ problems.push(
774
+ '@astryxdesign/cli/authoring exports no types, so nothing was compared with `astryx docs authoring`',
775
+ );
776
+ }
777
+ for (const {module, names, reason, source, key} of surface.unreadable) {
778
+ const why =
779
+ reason === 'no-self-doc'
780
+ ? `no self-doc sits beside ${module}`
781
+ : reason === 'unregistered'
782
+ ? `${source} is not listed in AUTHORING_SELF_DOCS`
783
+ : reason === 'failed'
784
+ ? `${source} does not load`
785
+ : `${source} renders section "${key}", which the topic's index does not list`;
786
+ problems.push(
787
+ `${nameTypes(names)} from ${module} ${names.length === 1 ? 'has' : 'have'} no doc in \`astryx docs authoring\`: ${why}`,
788
+ );
789
+ }
790
+ for (const {name, reason} of surface.untraced) {
791
+ problems.push(
792
+ `${name} cannot be traced to the module that declares it: ${reason}`,
793
+ );
794
+ }
795
+ for (const {source, subject} of surface.unmatched) {
796
+ problems.push(
797
+ subject
798
+ ? `${source} documents ${subject}, which @astryxdesign/cli/authoring does not export`
799
+ : `${source} documents no type @astryxdesign/cli/authoring exports`,
800
+ );
801
+ }
802
+ return problems;
803
+ }
804
+
724
805
  /**
725
806
  * Every authoring self-doc is reachable from `astryx docs authoring`, loads,
726
- * and fits in one read. The audit is imported here, inside the try, so a
727
- * malformed self-doc is reported rather than taking Doctor down.
807
+ * and fits in one read, and every type `@astryxdesign/cli/authoring` exports
808
+ * has its doc there: the self-doc beside the module that declares it. The
809
+ * audits are imported here, inside the try, so a malformed self-doc is
810
+ * reported rather than taking Doctor down.
728
811
  * @param {DoctorContext} [_ctx]
812
+ * @param {{root?: string, sources?: string[], topicKeys?: Set<string> | null}} [options]
813
+ * Another authoring tree, list, or topic index to audit (for tests).
729
814
  * @returns {Promise<DoctorCheck>}
730
815
  */
731
- export async function checkAuthoringDocs(_ctx) {
816
+ export async function checkAuthoringDocs(_ctx, options = {}) {
732
817
  const id = 'authoring-docs';
733
818
  const label = 'Authoring docs';
734
819
  try {
735
- const {auditAuthoringSelfDocs} = await import(
736
- '../../foundation/discovery/authoring-self-docs.mjs'
737
- );
738
- const audit = await auditAuthoringSelfDocs();
820
+ const {auditAuthoringSelfDocs} =
821
+ await import('../../foundation/discovery/authoring-self-docs.mjs');
822
+ const {auditAuthoringSurface} =
823
+ await import('../../foundation/discovery/authoring-surface.mjs');
824
+ const {root, sources} = options;
825
+ const audit = await auditAuthoringSelfDocs({root, sources});
739
826
  const problems = [
740
827
  ...audit.unreachable.map(
741
828
  source => `${source} is not in \`astryx docs authoring\``,
742
829
  ),
743
- ...audit.failed.map(({source, error}) => `${source} failed to load: ${error}`),
830
+ ...audit.failed.map(
831
+ ({source, error}) => `${source} failed to load: ${error}`,
832
+ ),
744
833
  ...audit.oversized.map(
745
834
  ({key, bytes}) =>
746
835
  `authoring section "${key}" is ${kilobytes(bytes)}, over the ${kilobytes(DOC_OUTPUT_BUDGET_BYTES)} one read may return`,
747
836
  ),
748
837
  ];
749
- if (problems.length > 0) {
838
+ const topic =
839
+ options.topicKeys === undefined
840
+ ? await authoringTopicKeys()
841
+ : {keys: options.topicKeys};
842
+ const surface = [
843
+ ...('error' in topic
844
+ ? [`\`astryx docs authoring\` could not be read: ${topic.error}`]
845
+ : []),
846
+ ...surfaceProblems(
847
+ await auditAuthoringSurface({root, sources, topicKeys: topic.keys}),
848
+ ),
849
+ ];
850
+ if (problems.length + surface.length > 0) {
750
851
  return {
751
852
  id,
752
853
  label,
753
854
  status: 'fail',
754
- message: joinProblems(problems),
755
- fix: 'List every authoring self-doc in AUTHORING_SELF_DOCS, fix the one that fails to load, and split a section that is too large.',
855
+ message: joinProblems([...problems, ...surface]),
856
+ fix: [
857
+ problems.length > 0 ? AUTHORING_DOCS_FIX : null,
858
+ surface.length > 0 ? AUTHORING_SURFACE_FIX : null,
859
+ ]
860
+ .filter(Boolean)
861
+ .join(' '),
756
862
  };
757
863
  }
758
864
  return {
@@ -772,6 +878,71 @@ export async function checkAuthoringDocs(_ctx) {
772
878
  }
773
879
  }
774
880
 
881
+ /** How the CLI-docs audit's problems are fixed. */
882
+ const CLI_DOCS_FIX =
883
+ "Set `namespace` on each CLI doc to the one that reads it: cli/commands for a command, cli/api for an API function or the output schema, error codes, and response types, and authoring for a file an author writes (and list it in AUTHORING_SELF_DOCS).";
884
+
885
+ /**
886
+ * Every command, API function, schema, and enum doc the CLI ships declares a
887
+ * namespace, and the topic that namespace names reads it: `astryx docs cli`
888
+ * for `cli/commands` and `cli/api`, `astryx docs authoring` for `authoring`.
889
+ * @param {DoctorContext | Partial<DoctorContext>} _ctx
890
+ * @param {{root?: string, sources?: string[], authoringSources?: string[]}} [options]
891
+ * test seams: the CLI root, the docs to audit, and the authoring topic's list
892
+ * @returns {Promise<DoctorCheck>}
893
+ */
894
+ export async function checkCliDocs(_ctx, options = {}) {
895
+ const id = 'cli-docs';
896
+ const label = 'CLI docs';
897
+ try {
898
+ const {auditCliSelfDocs} =
899
+ await import('../../foundation/discovery/cli-self-docs.mjs');
900
+ const audit = await auditCliSelfDocs(options);
901
+ const problems = [
902
+ ...audit.missing.map(
903
+ source =>
904
+ `${source} has no namespace, so no \`astryx docs\` topic reads it`,
905
+ ),
906
+ ...audit.unknown.map(
907
+ ({source, namespace}) =>
908
+ `${source} has namespace "${namespace}", which no \`astryx docs\` topic reads`,
909
+ ),
910
+ ...audit.misfiled.map(({message}) => message),
911
+ ...audit.failed.map(
912
+ ({source, error}) => `${source} failed to load: ${error}`,
913
+ ),
914
+ ...audit.keyProblems.map(problem => `\`astryx docs cli\`: ${problem}`),
915
+ ...audit.oversized.map(
916
+ ({key, bytes}) =>
917
+ `cli section "${key}" is ${kilobytes(bytes)}, over the ${kilobytes(DOC_OUTPUT_BUDGET_BYTES)} one read may return`,
918
+ ),
919
+ ];
920
+ if (problems.length > 0) {
921
+ return {
922
+ id,
923
+ label,
924
+ status: 'fail',
925
+ message: joinProblems(problems),
926
+ fix: CLI_DOCS_FIX,
927
+ };
928
+ }
929
+ return {
930
+ id,
931
+ label,
932
+ status: 'pass',
933
+ message: `All ${audit.docs} CLI docs are readable: ${audit.sections} in \`astryx docs cli\` and ${audit.authoring} in \`astryx docs authoring\`.`,
934
+ };
935
+ } catch (err) {
936
+ return {
937
+ id,
938
+ label,
939
+ status: 'fail',
940
+ message: `The CLI docs could not be audited: ${err instanceof Error ? err.message : String(err)}`,
941
+ fix: 'Reinstall @astryxdesign/cli.',
942
+ };
943
+ }
944
+ }
945
+
775
946
  /**
776
947
  * Every topic reads progressively, in every language it ships: it loads, its
777
948
  * section index and each of its sections fit in one read, and no contributed
@@ -929,6 +1100,7 @@ export async function runChecks(options = {}) {
929
1100
  }
930
1101
  }
931
1102
  checks.push(await checkAuthoringDocs(ctx));
1103
+ checks.push(await checkCliDocs(ctx));
932
1104
  checks.push(await checkDocsProgressiveDisclosure(ctx));
933
1105
 
934
1106
  const summary = {pass: 0, warn: 0, fail: 0, info: 0};