@astryxdesign/cli 0.6.3-canary.db4e378 → 0.6.3-canary.db7b338
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.
- package/README.md +22 -1
- package/api/blog/blog.doc.mjs +1 -0
- package/api/build/build.doc.mjs +1 -0
- package/api/component/component.doc.mjs +1 -0
- package/api/discover/discover.doc.mjs +1 -0
- package/api/docs/_adapter.d.mts +3 -8
- package/api/docs/_adapter.mjs +13 -105
- package/api/docs/detail/section/section.mjs +9 -15
- package/api/docs/detail/section/section.test.mjs +15 -6
- package/api/docs/docs.doc.mjs +1 -0
- package/api/docs/list/list.mjs +3 -7
- package/api/doctor/doctor.d.mts +25 -3
- package/api/doctor/doctor.doc.mjs +1 -0
- package/api/doctor/doctor.mjs +186 -14
- package/api/doctor/doctor.test.mjs +332 -7
- package/api/gap-report/gap-report.doc.mjs +1 -0
- package/api/hook/_adapter.mjs +19 -5
- package/api/hook/hook.doc.mjs +1 -0
- package/api/hook/list/list.d.mts +1 -1
- package/api/hook/list/list.mjs +69 -17
- package/api/init/init.doc.mjs +1 -0
- package/api/integration/add-contribution.mjs +7 -7
- package/api/integration/add-contribution.test.mjs +37 -3
- package/api/integration/add-theme.mjs +34 -64
- package/api/integration/add-theme.test.mjs +105 -21
- package/api/integration/authoring-checks.test.mjs +8 -4
- package/api/integration/integration-block-exports.test.mjs +10 -6
- package/api/integration/integrationAdd.doc.mjs +1 -0
- package/api/integration/integrationAddAgentDoc.doc.mjs +1 -0
- package/api/integration/integrationAddCodemod.doc.mjs +1 -0
- package/api/integration/integrationAddComponent.doc.mjs +1 -0
- package/api/integration/integrationAddDoc.doc.mjs +1 -0
- package/api/integration/integrationAddTemplate.doc.mjs +1 -0
- package/api/integration/integrationAddTheme.doc.mjs +6 -5
- package/api/integration/integrationComponentConflicts.doc.mjs +1 -0
- package/api/integration/integrationDocConflicts.doc.mjs +1 -0
- package/api/integration/integrationPackCheck.doc.mjs +1 -0
- package/api/integration/integrationTemplateConflicts.doc.mjs +1 -0
- package/api/integration/pack-check.test.mjs +17 -47
- package/api/integration/summarizeIssues.doc.mjs +1 -0
- package/api/integration/validate-integration-fixes.test.mjs +1389 -0
- package/api/integration/validate-integration.mjs +50 -102
- package/api/integration/validate-integration.test.mjs +85 -23
- package/api/integration/validate-unread-theme-folders.test.mjs +110 -0
- package/api/integration/validateIntegration.doc.mjs +1 -0
- package/api/json/assertResponse.doc.mjs +1 -0
- package/api/json/isError.doc.mjs +1 -0
- package/api/json/parseResponse.doc.mjs +1 -0
- package/api/layout/layoutCheck.doc.mjs +1 -0
- package/api/layout/layoutExpand.doc.mjs +1 -0
- package/api/layout/layoutGrammar.doc.mjs +1 -0
- package/api/search/search.doc.mjs +1 -0
- package/api/search/search.mjs +16 -6
- package/api/swizzle/swizzle.doc.mjs +1 -0
- package/api/template/template-suffix.test.mjs +41 -21
- package/api/template/template.doc.mjs +1 -0
- package/api/theme/_adapter.d.mts +2 -3
- package/api/theme/_adapter.mjs +4 -5
- package/api/theme/add/add.binary.test.mjs +10 -17
- package/api/theme/add/add.test.mjs +14 -1
- package/api/theme/generateTonalPalette.doc.mjs +1 -0
- package/api/theme/integration-themes.test.mjs +39 -28
- package/api/theme/list/list.test.mjs +19 -20
- package/api/theme/listThemes.doc.mjs +6 -5
- package/api/theme/themeAdd.doc.mjs +4 -3
- package/api/theme/themeBuild.doc.mjs +1 -0
- package/api/theme/themeList.doc.mjs +6 -3
- package/api/theme/themeListAvailable.doc.mjs +5 -3
- package/api/theme/themePaletteGenerate.doc.mjs +1 -0
- package/api/theme/themeTargets.doc.mjs +1 -0
- package/api/theme/themeTemplate.doc.mjs +1 -0
- package/api/upgrade/_adapter.d.mts +32 -5
- package/api/upgrade/_adapter.mjs +97 -69
- package/api/upgrade/provider-agreement.test.mjs +152 -0
- package/api/upgrade/run/run.mjs +356 -59
- package/api/upgrade/upgrade.doc.mjs +6 -1
- package/api/upgrade/upgrade.type.d.mts +34 -0
- package/api/upgrade/upgrade.type.mjs +15 -0
- package/assets/codemods/__tests__/runner.test.mjs +330 -8
- package/assets/codemods/integration-discovery.mjs +8 -2
- package/assets/codemods/integration-discovery.test.mjs +15 -0
- package/assets/codemods/integration-runner.mjs +56 -4
- package/assets/codemods/integration-runner.protection.test.mjs +153 -0
- package/assets/codemods/run-codemod.mjs +177 -34
- package/assets/codemods/runner.mjs +350 -102
- package/assets/codemods/transforms/next/__tests__/migrate-native-picker-to-presentation.test.mjs +63 -0
- package/assets/codemods/transforms/next/__tests__/migrate-theme-catalog-to-descriptors.test.mjs +220 -0
- package/assets/codemods/transforms/next/index.mjs +19 -1
- package/assets/codemods/transforms/next/migrate-native-picker-to-presentation.mjs +148 -0
- package/assets/codemods/transforms/next/migrate-theme-catalog-to-descriptors.mjs +141 -0
- package/assets/docs/cli-integrations.doc.mjs +30 -30
- package/assets/docs/cli.doc.mjs +15 -0
- package/assets/docs/theme.doc.mjs +1 -1
- package/assets/templates/blocks/components/DateInput/DateInputDateRange.tsx +1 -1
- package/assets/templates/blocks/components/Item/ItemDocumentTabs.doc.mjs +14 -0
- package/assets/templates/blocks/components/Item/ItemDocumentTabs.tsx +100 -0
- package/assets/templates/blocks/components/TimeInput/TimeInputConstrained.tsx +1 -0
- package/assets/templates/themes/butter/butterTheme.doc.mjs +11 -0
- package/assets/templates/themes/chocolate/chocolateTheme.doc.mjs +11 -0
- package/assets/templates/themes/gothic/gothicTheme.doc.mjs +11 -0
- package/assets/templates/themes/matcha/matchaTheme.doc.mjs +11 -0
- package/assets/templates/themes/neutral/neutralTheme.doc.mjs +11 -0
- package/assets/templates/themes/stone/stoneTheme.doc.mjs +11 -0
- package/assets/templates/themes/y2k/y2kTheme.doc.mjs +11 -0
- package/authoring/codemod/codemod.doc.mjs +1 -1
- package/authoring/codemod/type.ts +12 -0
- package/authoring/config/config.doc.mjs +1 -1
- package/authoring/debug/debug.doc.d.mts +11 -0
- package/authoring/debug/debug.doc.mjs +182 -0
- package/authoring/doctypes/_schema.d.mts +71 -141
- package/authoring/doctypes/_schema.mjs +29 -2
- package/authoring/doctypes/base/graph-fields.doc.mjs +1 -1
- package/authoring/doctypes/command/command.doc.mjs +1 -1
- package/authoring/doctypes/command/type.ts +1 -1
- package/authoring/doctypes/component/type.ts +2 -2
- package/authoring/doctypes/doctypes-new.test.mjs +48 -6
- package/authoring/doctypes/enum/enum.doc.mjs +1 -1
- package/authoring/doctypes/enum/type.ts +1 -1
- package/authoring/doctypes/function/function.doc.mjs +1 -1
- package/authoring/doctypes/function/type.ts +1 -1
- package/authoring/doctypes/hook/type.ts +2 -2
- package/authoring/doctypes/load-contract.test.mjs +3 -2
- package/authoring/doctypes/namespace/namespace.doc.mjs +2 -2
- package/authoring/doctypes/namespace/parse.test.mjs +23 -25
- package/authoring/doctypes/namespace/type.ts +5 -2
- package/authoring/doctypes/parse.d.mts +4 -2
- package/authoring/doctypes/parse.mjs +10 -5
- package/authoring/doctypes/reference/reference.doc.mjs +6 -4
- package/authoring/doctypes/reference/type.ts +9 -10
- package/authoring/doctypes/schema/schema.doc.mjs +1 -1
- package/authoring/doctypes/schema/type.ts +1 -2
- package/authoring/doctypes/template/template.doc.mjs +3 -3
- package/authoring/doctypes/theme/parse.d.mts +35 -0
- package/authoring/doctypes/theme/parse.mjs +76 -0
- package/authoring/doctypes/theme/theme.doc.d.mts +9 -0
- package/authoring/doctypes/theme/theme.doc.mjs +79 -0
- package/authoring/doctypes/theme/type.ts +42 -0
- package/authoring/doctypes/types.ts +2 -1
- package/authoring/gap-report/gap-report.doc.d.mts +12 -0
- package/authoring/gap-report/gap-report.doc.mjs +183 -0
- package/authoring/index.d.mts +1 -0
- package/authoring/index.d.ts +7 -4
- package/authoring/index.mjs +2 -1
- package/authoring/integration/integration.doc.mjs +2 -2
- package/authoring/integration/type.ts +3 -9
- package/clients/cli/__tests__/cliManifest.test.ts +27 -29
- package/clients/cli/commands/blog.doc.mjs +1 -1
- package/clients/cli/commands/build-theme.adaptations.test.mjs +100 -1
- package/clients/cli/commands/build-theme.mjs +10 -44
- package/clients/cli/commands/build.doc.mjs +1 -1
- package/clients/cli/commands/component.doc.mjs +1 -1
- package/clients/cli/commands/discover.doc.mjs +1 -1
- package/clients/cli/commands/docs.doc.mjs +1 -1
- package/clients/cli/commands/docs.mjs +15 -58
- package/clients/cli/commands/docs.test.mjs +11 -14
- package/clients/cli/commands/doctor-integration-components.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration.doc.mjs +1 -1
- package/clients/cli/commands/doctor-integration.test.mjs +15 -7
- package/clients/cli/commands/doctor.doc.mjs +1 -1
- package/clients/cli/commands/gap-report.doc.mjs +1 -1
- package/clients/cli/commands/hook.doc.mjs +1 -1
- package/clients/cli/commands/init.doc.mjs +1 -1
- package/clients/cli/commands/integration-add.controls.test.mjs +1 -1
- package/clients/cli/commands/integration-add.doc.mjs +1 -1
- package/clients/cli/commands/integration-pack.doc.mjs +1 -1
- package/clients/cli/commands/integration-real-world.test.mjs +3 -9
- package/clients/cli/commands/integration.doc.mjs +1 -1
- package/clients/cli/commands/layout-check.doc.mjs +1 -1
- package/clients/cli/commands/layout-expand.doc.mjs +1 -1
- package/clients/cli/commands/layout-grammar.doc.mjs +1 -1
- package/clients/cli/commands/layout.doc.mjs +1 -1
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/search.doc.mjs +1 -1
- package/clients/cli/commands/swizzle.doc.mjs +1 -1
- package/clients/cli/commands/template.doc.mjs +1 -1
- package/clients/cli/commands/text-json-parity.test.mjs +718 -0
- package/clients/cli/commands/theme-add.doc.mjs +2 -2
- package/clients/cli/commands/theme-build.doc.mjs +1 -1
- package/clients/cli/commands/theme-list.doc.mjs +2 -2
- package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -3
- package/clients/cli/commands/theme-palette.doc.mjs +1 -1
- package/clients/cli/commands/theme-targets.behavior.test.mjs +4 -3
- package/clients/cli/commands/theme-targets.doc.mjs +1 -1
- package/clients/cli/commands/theme-template.doc.mjs +1 -1
- package/clients/cli/commands/theme.doc.mjs +1 -1
- package/clients/cli/commands/upgrade.doc.mjs +3 -2
- package/clients/cli/commands/upgrade.file-protection.test.mjs +228 -0
- package/clients/cli/commands/upgrade.mjs +29 -7
- package/clients/cli/formatters/index.mjs +2 -0
- package/clients/cli/formatters/index.test.mjs +6 -0
- package/clients/cli/lib/hook-format.mjs +14 -5
- package/foundation/config/project-themes.test.mjs +11 -19
- package/foundation/config/project.d.mts +8 -0
- package/foundation/config/project.mjs +50 -21
- package/foundation/config/project.test.mjs +3 -16
- package/foundation/discovery/authoring-self-docs.d.mts +6 -0
- package/foundation/discovery/authoring-self-docs.mjs +17 -7
- package/foundation/discovery/authoring-self-docs.test.mjs +3 -2
- package/foundation/discovery/authoring-surface.d.mts +74 -0
- package/foundation/discovery/authoring-surface.mjs +525 -0
- package/foundation/discovery/authoring-surface.test.mjs +392 -0
- package/foundation/discovery/cli-self-docs.d.mts +113 -0
- package/foundation/discovery/cli-self-docs.mjs +514 -0
- package/foundation/discovery/cli-self-docs.test.mjs +437 -0
- package/foundation/discovery/component-loader.d.mts +35 -38
- package/foundation/discovery/component-loader.mjs +53 -222
- package/foundation/discovery/docs-discovery.d.mts +3 -2
- package/foundation/discovery/docs-discovery.mjs +14 -17
- package/foundation/discovery/docs-discovery.test.mjs +15 -15
- package/foundation/discovery/docs-section-key.d.mts +19 -8
- package/foundation/discovery/docs-section-key.mjs +119 -32
- package/foundation/discovery/docs-section-key.test.mjs +41 -19
- package/foundation/discovery/template-adapter.d.mts +7 -0
- package/foundation/discovery/template-adapter.mjs +27 -40
- package/foundation/discovery/template-adapter.test.mjs +15 -0
- package/foundation/discovery/theme-discovery.d.mts +67 -7
- package/foundation/discovery/theme-discovery.mjs +916 -186
- package/foundation/discovery/theme-discovery.test.mjs +613 -219
- package/foundation/doc-compiler/bundle.d.mts +47 -0
- package/foundation/doc-compiler/bundle.mjs +218 -0
- package/foundation/doc-compiler/bundle.test.mjs +255 -0
- package/foundation/doc-compiler/compile.d.mts +200 -0
- package/foundation/doc-compiler/compile.mjs +259 -9
- package/foundation/doc-compiler/diagnostics.d.mts +126 -0
- package/foundation/doc-compiler/diagnostics.mjs +277 -0
- package/foundation/doc-compiler/doc-compiler.test.mjs +28 -1
- package/foundation/doc-compiler/doc-loads.test.mjs +1642 -0
- package/foundation/doc-compiler/import.d.mts +24 -0
- package/foundation/doc-compiler/import.mjs +59 -0
- package/foundation/doc-compiler/inputs.d.mts +102 -0
- package/foundation/doc-compiler/inputs.mjs +286 -0
- package/foundation/doc-compiler/inputs.test.mjs +299 -0
- package/foundation/doc-compiler/ir.d.mts +13 -0
- package/foundation/doc-compiler/ir.mjs +189 -12
- package/foundation/doc-compiler/lower-doc.test.mjs +492 -0
- package/foundation/doc-compiler/overlays.d.mts +37 -0
- package/foundation/doc-compiler/overlays.mjs +206 -0
- package/foundation/doc-compiler/parse-readable.d.mts +9 -0
- package/foundation/doc-compiler/parse-readable.mjs +29 -0
- package/foundation/doc-compiler/read.d.mts +126 -0
- package/foundation/doc-compiler/read.mjs +320 -0
- package/foundation/doc-compiler/read.test.mjs +313 -0
- package/foundation/doc-compiler/source.d.mts +33 -0
- package/foundation/doc-compiler/source.mjs +128 -0
- package/foundation/fs/file-protection.d.mts +33 -0
- package/foundation/fs/file-protection.mjs +825 -0
- package/foundation/fs/file-protection.test.mjs +250 -0
- package/foundation/integrations/autolink.d.mts +58 -1
- package/foundation/integrations/autolink.mjs +143 -57
- package/foundation/integrations/contribution-fixes.d.mts +145 -0
- package/foundation/integrations/contribution-fixes.mjs +1284 -0
- package/foundation/integrations/contribution-inventory.d.mts +1 -1
- package/foundation/integrations/contribution-inventory.mjs +17 -20
- package/foundation/integrations/contribution-inventory.test.mjs +67 -27
- package/foundation/integrations/integrations.d.mts +3 -0
- package/foundation/integrations/integrations.mjs +11 -97
- package/foundation/integrations/provider-ledger.test.mjs +275 -0
- package/foundation/integrations/provider-resolution.d.mts +152 -0
- package/foundation/integrations/provider-resolution.mjs +576 -0
- package/foundation/integrations/provider-resolution.test.mjs +369 -0
- package/foundation/integrations/theme-descriptor.d.mts +8 -0
- package/foundation/integrations/theme-descriptor.mjs +44 -0
- package/foundation/integrations/validate-contributions.mjs +104 -10
- package/foundation/response/error-codes.d.mts +3 -1
- package/foundation/response/error-codes.d.ts +2 -0
- package/foundation/response/error-codes.doc.mjs +12 -2
- package/foundation/response/error-codes.mjs +7 -1
- package/foundation/response/error-codes.test.mjs +55 -11
- package/foundation/response/response-types.doc.mjs +1 -1
- package/foundation/response/response.doc.mjs +1 -1
- package/foundation/text/string-utils.mjs +22 -10
- package/package.json +10 -9
- package/assets/templates/themes/manifest.json +0 -95
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file The CLI's own docs, read by their `namespace`: every command, API
|
|
5
|
+
* function, schema, and enum doc the CLI ships says which `astryx docs` topic
|
|
6
|
+
* reads it, and the `cli` topic is built from the ones that name it.
|
|
7
|
+
*
|
|
8
|
+
* @input The command, function, schema, and enum docs under
|
|
9
|
+
* clients/cli/commands, api, authoring, and foundation.
|
|
10
|
+
* @output {@link buildCliTopic} for `astryx docs cli`, and
|
|
11
|
+
* {@link auditCliSelfDocs}, which `astryx doctor` runs.
|
|
12
|
+
* @position foundation/discovery — the reader for docs whose namespace starts
|
|
13
|
+
* with `cli/`. The authoring topic reads the `authoring` namespace from its
|
|
14
|
+
* own list (authoring-self-docs.mjs).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import * as fs from 'node:fs';
|
|
18
|
+
import * as path from 'node:path';
|
|
19
|
+
import {CLI_ROOT} from '../fs/paths.mjs';
|
|
20
|
+
import {readDocView} from '../doc-compiler/read.mjs';
|
|
21
|
+
import {AUTHORING_SELF_DOCS, selfDocSection} from './authoring-self-docs.mjs';
|
|
22
|
+
import {
|
|
23
|
+
DOC_OUTPUT_BUDGET_BYTES,
|
|
24
|
+
oversizedDocSections,
|
|
25
|
+
} from './docs-output-budget.mjs';
|
|
26
|
+
import {sectionKeyProblems} from './docs-section-key.mjs';
|
|
27
|
+
|
|
28
|
+
/** The directories, relative to the CLI root, that hold the CLI's own docs. */
|
|
29
|
+
export const CLI_SELF_DOC_DIRS = [
|
|
30
|
+
'clients/cli/commands',
|
|
31
|
+
'api',
|
|
32
|
+
'authoring',
|
|
33
|
+
'foundation',
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
/** The doc kinds that declare a namespace. */
|
|
37
|
+
const NAMESPACED_KINDS = new Set(['command', 'function', 'schema', 'enum']);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Every namespace a CLI doc may declare, and the topic that reads it. A doc in
|
|
41
|
+
* a `cli/` namespace is the section `<key prefix>-<name>` of `astryx docs cli`;
|
|
42
|
+
* a doc in `authoring` is a section of `astryx docs authoring`.
|
|
43
|
+
* @type {Record<string, {topic: string, keyPrefix?: string}>}
|
|
44
|
+
*/
|
|
45
|
+
export const CLI_DOC_NAMESPACES = {
|
|
46
|
+
'cli/commands': {topic: 'cli', keyPrefix: 'commands'},
|
|
47
|
+
'cli/api': {topic: 'cli', keyPrefix: 'api'},
|
|
48
|
+
authoring: {topic: 'authoring'},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** Blocks a doc's notes may carry that a topic section can render. */
|
|
52
|
+
const TOPIC_BLOCKS = new Set(['prose', 'list', 'code', 'heading', 'table']);
|
|
53
|
+
|
|
54
|
+
/** Section order within the `cli` topic: commands, then the API by kind. */
|
|
55
|
+
const KIND_ORDER = ['command', 'function', 'schema', 'enum'];
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Every `*.doc.mjs` under the CLI's doc directories, relative to `root` and
|
|
59
|
+
* sorted. Fixture, test, and dependency directories are skipped.
|
|
60
|
+
* @param {string} [root]
|
|
61
|
+
* @returns {string[]}
|
|
62
|
+
*/
|
|
63
|
+
export function discoverCliSelfDocSources(root = CLI_ROOT) {
|
|
64
|
+
/** @type {string[]} */
|
|
65
|
+
const found = [];
|
|
66
|
+
/** @param {string} dir */
|
|
67
|
+
const walk = dir => {
|
|
68
|
+
if (!fs.existsSync(dir)) return;
|
|
69
|
+
for (const entry of fs.readdirSync(dir, {withFileTypes: true})) {
|
|
70
|
+
if (
|
|
71
|
+
entry.name === 'node_modules' ||
|
|
72
|
+
entry.name.startsWith('__') ||
|
|
73
|
+
entry.name.startsWith('.')
|
|
74
|
+
) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const full = path.join(dir, entry.name);
|
|
78
|
+
if (entry.isDirectory()) walk(full);
|
|
79
|
+
else if (entry.name.endsWith('.doc.mjs')) {
|
|
80
|
+
found.push(path.relative(root, full).split(path.sep).join('/'));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
for (const dir of CLI_SELF_DOC_DIRS) walk(path.join(root, dir));
|
|
85
|
+
return found.sort();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Read each doc through the compiler and keep the kinds that declare a
|
|
90
|
+
* namespace. One that fails is reported, never thrown, so one bad file cannot
|
|
91
|
+
* take the rest of the topic down with it.
|
|
92
|
+
* @param {string[]} [sources]
|
|
93
|
+
* @param {string} [root]
|
|
94
|
+
* @returns {Promise<{loaded: {source: string, doc: any}[], failed: {source: string, error: string}[]}>}
|
|
95
|
+
*/
|
|
96
|
+
export async function loadCliSelfDocs(
|
|
97
|
+
sources = discoverCliSelfDocSources(),
|
|
98
|
+
root = CLI_ROOT,
|
|
99
|
+
) {
|
|
100
|
+
const loaded = [];
|
|
101
|
+
const failed = [];
|
|
102
|
+
for (const source of sources) {
|
|
103
|
+
try {
|
|
104
|
+
const doc = await readDocView(path.join(root, source), {
|
|
105
|
+
root: 'self-docs',
|
|
106
|
+
loader: 'native',
|
|
107
|
+
});
|
|
108
|
+
if (!NAMESPACED_KINDS.has(doc?.type)) continue;
|
|
109
|
+
if (typeof doc.name !== 'string' || doc.name === '') {
|
|
110
|
+
throw new Error('exports no doc with a name');
|
|
111
|
+
}
|
|
112
|
+
loaded.push({source, doc});
|
|
113
|
+
} catch (error) {
|
|
114
|
+
failed.push({
|
|
115
|
+
source,
|
|
116
|
+
error: error instanceof Error ? error.message : String(error),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return {loaded, failed};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* A name as a section-key segment: lowercase words joined by hyphens.
|
|
125
|
+
* `integrationPackCheck` and `integration pack` both read naturally.
|
|
126
|
+
* @param {string} name
|
|
127
|
+
* @returns {string}
|
|
128
|
+
*/
|
|
129
|
+
export function keySegment(name) {
|
|
130
|
+
return name
|
|
131
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
132
|
+
.toLowerCase()
|
|
133
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
134
|
+
.replace(/^-+|-+$/g, '');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* The section key a doc is read by in `astryx docs cli`, or null when its
|
|
139
|
+
* namespace is not one of the topic's.
|
|
140
|
+
* @param {any} doc
|
|
141
|
+
* @returns {string | null}
|
|
142
|
+
*/
|
|
143
|
+
export function cliSectionKey(doc) {
|
|
144
|
+
const prefix = CLI_DOC_NAMESPACES[doc?.namespace]?.keyPrefix;
|
|
145
|
+
if (prefix == null) return null;
|
|
146
|
+
return `${prefix}-${keySegment(String(doc.name))}`;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** @param {unknown} value */
|
|
150
|
+
function defaultText(value) {
|
|
151
|
+
if (value === undefined || value === false || value === '') return null;
|
|
152
|
+
if (Array.isArray(value)) return value.length > 0 ? value.join(' ') : null;
|
|
153
|
+
return String(value);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* @param {any} cmd
|
|
158
|
+
* @returns {string}
|
|
159
|
+
*/
|
|
160
|
+
function usage(cmd) {
|
|
161
|
+
const args = (cmd.args ?? []).map((/** @type {any} */ arg) => {
|
|
162
|
+
const name = arg.variadic ? `${arg.name}...` : arg.name;
|
|
163
|
+
return arg.required ? `<${name}>` : `[${name}]`;
|
|
164
|
+
});
|
|
165
|
+
return ['astryx', cmd.name, ...args].join(' ');
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* The text for a command option or argument: its own, or else the text of the
|
|
170
|
+
* API parameter it maps to, as `--help` shows.
|
|
171
|
+
* @param {{description?: string, param?: string}} entry
|
|
172
|
+
* @param {any} fn the FunctionDoc the command calls, if any
|
|
173
|
+
* @returns {string}
|
|
174
|
+
*/
|
|
175
|
+
function entryText(entry, fn) {
|
|
176
|
+
if (typeof entry.description === 'string' && entry.description !== '') {
|
|
177
|
+
return entry.description;
|
|
178
|
+
}
|
|
179
|
+
const param = (fn?.params ?? []).find(
|
|
180
|
+
(/** @type {any} */ p) => p.name === entry.param,
|
|
181
|
+
);
|
|
182
|
+
return typeof param?.description === 'string' ? param.description : '';
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* `text`, ending in a full stop when more text follows it in the same cell.
|
|
187
|
+
* @param {string} text
|
|
188
|
+
* @param {boolean} more
|
|
189
|
+
*/
|
|
190
|
+
function sentence(text, more) {
|
|
191
|
+
return more && text !== '' && !/[.!?:]$/.test(text) ? `${text}.` : text;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** @param {any[]} notes */
|
|
195
|
+
function noteBlocks(notes) {
|
|
196
|
+
return (notes ?? []).filter(note => TOPIC_BLOCKS.has(note?.type));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* One command doc as a section of `astryx docs cli`.
|
|
201
|
+
* @param {any} cmd
|
|
202
|
+
* @param {{functions: Map<string, any>, commands: Set<string>}} index
|
|
203
|
+
*/
|
|
204
|
+
function commandSection(cmd, index) {
|
|
205
|
+
const fn = cmd.fn == null ? undefined : index.functions.get(cmd.fn);
|
|
206
|
+
/** @type {any[]} */
|
|
207
|
+
const content = [{type: 'prose', text: cmd.summary}];
|
|
208
|
+
if (cmd.description) content.push({type: 'prose', text: cmd.description});
|
|
209
|
+
content.push({type: 'code', lang: 'bash', code: usage(cmd)});
|
|
210
|
+
const args = cmd.args ?? [];
|
|
211
|
+
if (args.length > 0) {
|
|
212
|
+
content.push({
|
|
213
|
+
type: 'table',
|
|
214
|
+
headers: ['Argument', 'Description'],
|
|
215
|
+
rows: args.map((/** @type {any} */ arg) => [
|
|
216
|
+
`\`${arg.name}\``,
|
|
217
|
+
entryText(arg, fn),
|
|
218
|
+
]),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
const options = cmd.options ?? [];
|
|
222
|
+
if (options.length > 0) {
|
|
223
|
+
content.push({
|
|
224
|
+
type: 'table',
|
|
225
|
+
headers: ['Option', 'Description'],
|
|
226
|
+
rows: options.map((/** @type {any} */ option) => {
|
|
227
|
+
const extra = [
|
|
228
|
+
option.choices?.length
|
|
229
|
+
? `One of: ${option.choices.map((/** @type {string} */ c) => `\`${c}\``).join(', ')}.`
|
|
230
|
+
: null,
|
|
231
|
+
defaultText(option.default) == null
|
|
232
|
+
? null
|
|
233
|
+
: `Default: \`${defaultText(option.default)}\`.`,
|
|
234
|
+
].filter(Boolean);
|
|
235
|
+
return [
|
|
236
|
+
`\`${option.flag}\``,
|
|
237
|
+
[sentence(entryText(option, fn), extra.length > 0), ...extra]
|
|
238
|
+
.filter(Boolean)
|
|
239
|
+
.join(' '),
|
|
240
|
+
];
|
|
241
|
+
}),
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
const examples = (cmd.examples ?? []).flatMap((/** @type {any} */ e) =>
|
|
245
|
+
e.label ? [`# ${e.label}`, e.cli] : [e.cli],
|
|
246
|
+
);
|
|
247
|
+
if (examples.length > 0) {
|
|
248
|
+
content.push({type: 'code', lang: 'bash', code: examples.join('\n')});
|
|
249
|
+
}
|
|
250
|
+
const exitCodes = cmd.exitCodes ?? [];
|
|
251
|
+
if (exitCodes.length > 0) {
|
|
252
|
+
content.push({
|
|
253
|
+
type: 'table',
|
|
254
|
+
headers: ['Exit code', 'When'],
|
|
255
|
+
rows: exitCodes.map((/** @type {any} */ e) => [String(e.code), e.when]),
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
const subcommands = (cmd.subcommands ?? []).filter(
|
|
259
|
+
(/** @type {string} */ sub) => index.commands.has(`${cmd.name} ${sub}`),
|
|
260
|
+
);
|
|
261
|
+
if (subcommands.length > 0) {
|
|
262
|
+
content.push({
|
|
263
|
+
type: 'list',
|
|
264
|
+
style: 'unordered',
|
|
265
|
+
items: subcommands.map(
|
|
266
|
+
(/** @type {string} */ sub) =>
|
|
267
|
+
`\`astryx ${cmd.name} ${sub}\`: \`astryx docs cli commands-${keySegment(`${cmd.name} ${sub}`)}\``,
|
|
268
|
+
),
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
if (fn != null) {
|
|
272
|
+
content.push({
|
|
273
|
+
type: 'prose',
|
|
274
|
+
text: `It runs \`${fn.name}()\` from \`${fn.importPath}\`. Read it with \`astryx docs cli ${cliSectionKey(fn)}\`.`,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
content.push(...noteBlocks(cmd.notes));
|
|
278
|
+
return {
|
|
279
|
+
id: cliSectionKey(cmd),
|
|
280
|
+
title: cmd.displayName ?? `astryx ${cmd.name}`,
|
|
281
|
+
content,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* One API function doc as a section of `astryx docs cli`.
|
|
287
|
+
* @param {any} fn
|
|
288
|
+
* @param {{functions: Map<string, any>, commands: Set<string>}} index
|
|
289
|
+
*/
|
|
290
|
+
function functionSection(fn, index) {
|
|
291
|
+
/** @type {any[]} */
|
|
292
|
+
const content = [{type: 'prose', text: fn.summary ?? fn.description ?? ''}];
|
|
293
|
+
if (fn.summary && fn.description) {
|
|
294
|
+
content.push({type: 'prose', text: fn.description});
|
|
295
|
+
}
|
|
296
|
+
if (fn.signature) {
|
|
297
|
+
content.push({type: 'code', lang: 'ts', code: fn.signature});
|
|
298
|
+
}
|
|
299
|
+
if (fn.importPath) {
|
|
300
|
+
content.push({type: 'prose', text: `Import it from \`${fn.importPath}\`.`});
|
|
301
|
+
}
|
|
302
|
+
const params = fn.params ?? [];
|
|
303
|
+
if (params.length > 0) {
|
|
304
|
+
content.push({
|
|
305
|
+
type: 'table',
|
|
306
|
+
headers: ['Parameter', 'Type', 'Description'],
|
|
307
|
+
rows: params.map((/** @type {any} */ p) => [
|
|
308
|
+
`\`${p.name}\``,
|
|
309
|
+
`\`${p.type ?? ''}\``,
|
|
310
|
+
p.description ?? '',
|
|
311
|
+
]),
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
const returns = fn.returns ?? [];
|
|
315
|
+
if (returns.length > 0) {
|
|
316
|
+
content.push({
|
|
317
|
+
type: 'table',
|
|
318
|
+
headers: ['Returns', 'Description'],
|
|
319
|
+
rows: returns.map((/** @type {any} */ r) => [
|
|
320
|
+
`\`${r.name ? `${r.name}: ` : ''}${r.type}\``,
|
|
321
|
+
r.description ?? '',
|
|
322
|
+
]),
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
const throws = fn.throws ?? [];
|
|
326
|
+
if (throws.length > 0) {
|
|
327
|
+
content.push({
|
|
328
|
+
type: 'table',
|
|
329
|
+
headers: ['Throws', 'When'],
|
|
330
|
+
rows: throws.map((/** @type {any} */ t) => [`\`${t.code}\``, t.when]),
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
for (const example of fn.examples ?? []) {
|
|
334
|
+
if (typeof example?.code !== 'string' || example.code.trim() === '') {
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
content.push({
|
|
338
|
+
type: 'code',
|
|
339
|
+
lang: 'ts',
|
|
340
|
+
...(example.label ? {label: example.label} : {}),
|
|
341
|
+
code: example.code,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
if (fn.command != null && index.commands.has(fn.command)) {
|
|
345
|
+
content.push({
|
|
346
|
+
type: 'prose',
|
|
347
|
+
text: `\`astryx ${fn.command}\` runs it. Read it with \`astryx docs cli commands-${keySegment(fn.command)}\`.`,
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
id: cliSectionKey(fn),
|
|
352
|
+
title: fn.displayName ?? `${fn.name}()`,
|
|
353
|
+
content,
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* One enum doc as a section of `astryx docs cli`.
|
|
359
|
+
* @param {any} doc
|
|
360
|
+
*/
|
|
361
|
+
function enumSection(doc) {
|
|
362
|
+
return {
|
|
363
|
+
id: cliSectionKey(doc),
|
|
364
|
+
title: doc.displayName ?? doc.name,
|
|
365
|
+
content: [
|
|
366
|
+
{type: 'prose', text: doc.description},
|
|
367
|
+
{
|
|
368
|
+
type: 'table',
|
|
369
|
+
headers: ['Value', 'Meaning'],
|
|
370
|
+
rows: (doc.members ?? []).map((/** @type {any} */ m) => [
|
|
371
|
+
`\`${m.value}\``,
|
|
372
|
+
m.deprecated
|
|
373
|
+
? `${m.description} Deprecated: ${m.deprecated}`
|
|
374
|
+
: m.description,
|
|
375
|
+
]),
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* The docs a `cli/` namespace names, in reading order: commands by name (a
|
|
383
|
+
* group before its subcommands), then API functions, schemas, and enums.
|
|
384
|
+
* @param {any[]} docs
|
|
385
|
+
* @returns {any[]}
|
|
386
|
+
*/
|
|
387
|
+
function cliDocsInOrder(docs) {
|
|
388
|
+
return docs
|
|
389
|
+
.filter(doc => CLI_DOC_NAMESPACES[doc.namespace]?.topic === 'cli')
|
|
390
|
+
.sort(
|
|
391
|
+
(a, b) =>
|
|
392
|
+
KIND_ORDER.indexOf(a.type) - KIND_ORDER.indexOf(b.type) ||
|
|
393
|
+
(a.name < b.name ? -1 : a.name > b.name ? 1 : 0),
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* The `cli` topic: one section per doc whose namespace is `cli/…`.
|
|
399
|
+
* @param {any[]} docs every loaded CLI doc; the ones in other namespaces are
|
|
400
|
+
* left out
|
|
401
|
+
* @returns {import('../../authoring/doctypes/reference/type').ReferenceDoc}
|
|
402
|
+
*/
|
|
403
|
+
export function buildCliReferenceDoc(docs) {
|
|
404
|
+
const ordered = cliDocsInOrder(docs);
|
|
405
|
+
const index = {
|
|
406
|
+
functions: new Map(
|
|
407
|
+
ordered.filter(d => d.type === 'function').map(d => [d.name, d]),
|
|
408
|
+
),
|
|
409
|
+
commands: new Set(
|
|
410
|
+
ordered.filter(d => d.type === 'command').map(d => d.name),
|
|
411
|
+
),
|
|
412
|
+
};
|
|
413
|
+
return /** @type {any} */ ({
|
|
414
|
+
name: 'cli',
|
|
415
|
+
title: 'CLI Reference',
|
|
416
|
+
category: 'guide',
|
|
417
|
+
description:
|
|
418
|
+
'Every command and API function of the CLI, with the JSON output envelope, error codes, and response types, read from the docs the CLI ships.',
|
|
419
|
+
sections: ordered.map(doc =>
|
|
420
|
+
doc.type === 'command'
|
|
421
|
+
? commandSection(doc, index)
|
|
422
|
+
: doc.type === 'function'
|
|
423
|
+
? functionSection(doc, index)
|
|
424
|
+
: doc.type === 'enum'
|
|
425
|
+
? enumSection(doc)
|
|
426
|
+
: {...selfDocSection(doc), id: cliSectionKey(doc)},
|
|
427
|
+
),
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* The `cli` topic from every CLI doc that loads. One that fails is left out
|
|
433
|
+
* here and reported by {@link auditCliSelfDocs}.
|
|
434
|
+
* @returns {Promise<import('../../authoring/doctypes/reference/type').ReferenceDoc>}
|
|
435
|
+
*/
|
|
436
|
+
export async function buildCliTopic() {
|
|
437
|
+
const {loaded} = await loadCliSelfDocs();
|
|
438
|
+
return buildCliReferenceDoc(loaded.map(entry => entry.doc));
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* What stands between a CLI doc and a reader: a missing namespace, one no
|
|
443
|
+
* topic reads, one that disagrees with the authoring topic's list, a doc that
|
|
444
|
+
* fails to load, and a `cli` section that clashes or is too large.
|
|
445
|
+
* @param {{root?: string, sources?: string[], budget?: number, authoringSources?: string[]}} [options]
|
|
446
|
+
* @returns {Promise<{
|
|
447
|
+
* docs: number,
|
|
448
|
+
* sections: number,
|
|
449
|
+
* authoring: number,
|
|
450
|
+
* missing: string[],
|
|
451
|
+
* unknown: {source: string, namespace: string}[],
|
|
452
|
+
* misfiled: {source: string, message: string}[],
|
|
453
|
+
* failed: {source: string, error: string}[],
|
|
454
|
+
* keyProblems: string[],
|
|
455
|
+
* oversized: {key: string, title: string, bytes: number}[],
|
|
456
|
+
* }>}
|
|
457
|
+
*/
|
|
458
|
+
export async function auditCliSelfDocs({
|
|
459
|
+
root = CLI_ROOT,
|
|
460
|
+
sources,
|
|
461
|
+
budget = DOC_OUTPUT_BUDGET_BYTES,
|
|
462
|
+
authoringSources = AUTHORING_SELF_DOCS,
|
|
463
|
+
} = {}) {
|
|
464
|
+
const {loaded, failed} = await loadCliSelfDocs(
|
|
465
|
+
sources ?? discoverCliSelfDocSources(root),
|
|
466
|
+
root,
|
|
467
|
+
);
|
|
468
|
+
const listed = new Set(authoringSources.map(source => `authoring/${source}`));
|
|
469
|
+
/** @type {string[]} */
|
|
470
|
+
const missing = [];
|
|
471
|
+
/** @type {{source: string, namespace: string}[]} */
|
|
472
|
+
const unknown = [];
|
|
473
|
+
/** @type {{source: string, message: string}[]} */
|
|
474
|
+
const misfiled = [];
|
|
475
|
+
let authoring = 0;
|
|
476
|
+
for (const {source, doc} of loaded) {
|
|
477
|
+
const namespace = doc.namespace;
|
|
478
|
+
if (typeof namespace !== 'string' || namespace === '') {
|
|
479
|
+
missing.push(source);
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
if (!Object.hasOwn(CLI_DOC_NAMESPACES, namespace)) {
|
|
483
|
+
unknown.push({source, namespace});
|
|
484
|
+
continue;
|
|
485
|
+
}
|
|
486
|
+
const inAuthoring = listed.has(source);
|
|
487
|
+
if (namespace === 'authoring') {
|
|
488
|
+
if (inAuthoring) authoring++;
|
|
489
|
+
else {
|
|
490
|
+
misfiled.push({
|
|
491
|
+
source,
|
|
492
|
+
message: `${source} has namespace "authoring", but \`astryx docs authoring\` does not list it`,
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
} else if (inAuthoring) {
|
|
496
|
+
misfiled.push({
|
|
497
|
+
source,
|
|
498
|
+
message: `${source} is read in \`astryx docs authoring\`, but its namespace is "${namespace}"`,
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
const topic = buildCliReferenceDoc(loaded.map(entry => entry.doc));
|
|
503
|
+
return {
|
|
504
|
+
docs: loaded.length,
|
|
505
|
+
sections: topic.sections.length,
|
|
506
|
+
authoring,
|
|
507
|
+
missing,
|
|
508
|
+
unknown,
|
|
509
|
+
misfiled,
|
|
510
|
+
failed,
|
|
511
|
+
keyProblems: sectionKeyProblems(topic.sections),
|
|
512
|
+
oversized: oversizedDocSections(topic.sections, budget),
|
|
513
|
+
};
|
|
514
|
+
}
|