@astryxdesign/cli 0.6.4 → 0.6.5-canary.031021b
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +56 -0
- package/README.md +97 -90
- package/api/build/build.doc.mjs +6 -1
- package/api/build/build.test.mjs +22 -0
- package/api/build/kit/kit.mjs +44 -5
- package/api/component/_adapter.d.mts +25 -0
- package/api/component/_adapter.mjs +59 -5
- package/api/component/component.d.mts +6 -3
- package/api/component/component.doc.mjs +37 -17
- package/api/component/component.mjs +249 -9
- package/api/component/component.type.d.mts +25 -0
- package/api/component/component.type.mjs +44 -0
- package/api/discover/_adapter.d.mts +114 -6
- package/api/discover/_adapter.mjs +372 -17
- package/api/discover/_adapter.test.mjs +215 -0
- package/api/discover/_catalog-view.d.mts +115 -0
- package/api/discover/_catalog-view.mjs +203 -0
- package/api/discover/_catalog-view.test.mjs +128 -0
- package/api/discover/detail/detail.d.mts +18 -6
- package/api/discover/detail/detail.mjs +67 -13
- package/api/discover/detail/detail.test.mjs +85 -0
- package/api/discover/detail/item/item.d.mts +26 -0
- package/api/discover/detail/item/item.mjs +78 -0
- package/api/discover/detail/item/item.test.mjs +73 -0
- package/api/discover/discover.d.mts +3 -9
- package/api/discover/discover.doc.mjs +61 -18
- package/api/discover/discover.mjs +220 -36
- package/api/discover/discover.test.mjs +11 -2
- package/api/discover/discover.type.d.mts +147 -8
- package/api/discover/discover.type.mjs +102 -12
- package/api/discover/list/list.d.mts +20 -6
- package/api/discover/list/list.mjs +45 -12
- package/api/discover/list/list.test.mjs +46 -0
- package/api/discover/search/search.d.mts +18 -16
- package/api/discover/search/search.mjs +102 -56
- package/api/discover/search/search.test.mjs +144 -10
- package/api/docs/_adapter.d.mts +8 -3
- package/api/docs/_adapter.mjs +14 -6
- package/api/docs/docOverlays.test.mjs +27 -1
- package/api/docs/docs.doc.mjs +2 -2
- package/api/doctor/doctor.d.mts +8 -3
- package/api/doctor/doctor.doc.mjs +17 -8
- package/api/doctor/doctor.mjs +90 -9
- package/api/doctor/doctor.test.mjs +122 -10
- package/api/doctor/doctor.type.d.mts +1 -1
- package/api/doctor/doctor.type.mjs +1 -1
- package/api/gap-report/gap-report.doc.mjs +19 -10
- package/api/hook/hook.doc.mjs +6 -3
- package/api/index.d.mts +1 -0
- package/api/index.mjs +5 -3
- package/api/init/init.doc.mjs +17 -12
- package/api/integration/add-helpers.d.mts +5 -2
- package/api/integration/add-helpers.mjs +36 -9
- package/api/integration/add-theme.mjs +22 -1
- package/api/integration/add-theme.test.mjs +34 -0
- package/api/integration/authoring-checks.mjs +2 -2
- package/api/integration/integrationPackCheck.doc.mjs +3 -3
- package/api/integration/pack-check.lifecycle-output.test.mjs +107 -0
- package/api/integration/pack-check.mjs +82 -9
- package/api/integration/pack-check.test.mjs +90 -0
- package/api/integration/pack-check.type.mjs +1 -1
- package/api/json/assertResponse.doc.mjs +1 -1
- package/api/json/isError.doc.mjs +1 -1
- package/api/search/search.d.mts +27 -1
- package/api/search/search.doc.mjs +2 -2
- package/api/search/search.mjs +228 -16
- package/api/swizzle/swizzle.doc.mjs +7 -5
- package/api/template/copy/copy.mjs +1 -1
- package/api/template/copy/copy.test.mjs +9 -0
- package/api/template/template.doc.mjs +2 -1
- package/api/theme/add/add.mjs +17 -25
- package/api/theme/add/add.rollback.test.mjs +158 -0
- package/api/theme/add/add.staging.test.mjs +40 -23
- package/api/theme/build/build.family.test.mjs +7 -12
- package/api/theme/build/build.mjs +8 -18
- package/api/theme/build/build.rollback.test.mjs +148 -0
- package/api/theme/generateTonalPalette.doc.mjs +1 -2
- package/api/theme/listThemes.doc.mjs +1 -1
- package/api/theme/themeAdd.doc.mjs +9 -10
- package/api/theme/themeBuild.doc.mjs +13 -13
- package/api/theme/themeList.doc.mjs +1 -1
- package/api/theme/themeListAvailable.doc.mjs +2 -1
- package/api/theme/themePaletteGenerate.doc.mjs +15 -8
- package/api/theme/themeTargets.doc.mjs +3 -2
- package/api/theme/themeTemplate.doc.mjs +2 -1
- package/api/upgrade/run/files-changed.test.mjs +111 -0
- package/api/upgrade/run/run.mjs +5 -3
- package/api/upgrade/upgrade.doc.mjs +24 -22
- package/api/upgrade/upgrade.type.mjs +2 -2
- package/assets/codemods/__tests__/runner.test.mjs +3 -1
- package/assets/codemods/file-count.test.mjs +163 -0
- package/assets/codemods/integration-runner.mjs +3 -3
- package/assets/codemods/runner.mjs +5 -4
- package/assets/docs/README.md +4 -2
- package/assets/docs/browser-support.doc.mjs +11 -11
- package/assets/docs/color.doc.mjs +8 -2
- package/assets/docs/elevation.doc.mjs +6 -4
- package/assets/docs/getting-started.doc.mjs +5 -16
- package/assets/docs/icons.doc.mjs +2 -21
- package/assets/docs/illustrations.doc.mjs +7 -15
- package/assets/docs/internationalization.doc.mjs +7 -5
- package/assets/docs/layout.doc.dense.mjs +130 -82
- package/assets/docs/layout.doc.mjs +133 -77
- package/assets/docs/migration.doc.mjs +19 -21
- package/assets/docs/motion.doc.mjs +16 -3
- package/assets/docs/principles.doc.dense.mjs +5 -5
- package/assets/docs/principles.doc.mjs +8 -0
- package/assets/docs/principles.doc.zh.mjs +6 -6
- package/assets/docs/shape.doc.mjs +8 -3
- package/assets/docs/spacing.doc.mjs +7 -2
- package/assets/docs/styling-libraries.doc.mjs +6 -2
- package/assets/docs/styling.doc.mjs +19 -23
- package/assets/docs/theme.doc.dense.mjs +58 -18
- package/assets/docs/theme.doc.mjs +57 -47
- package/assets/docs/theme.doc.zh.mjs +9 -8
- package/assets/docs/tokens.doc.dense.mjs +2 -2
- package/assets/docs/tokens.doc.mjs +389 -8
- package/assets/docs/tokens.doc.zh.mjs +2 -2
- package/assets/docs/tree/add-a-component.doc.mjs +75 -0
- package/assets/docs/tree/add-a-theme.doc.mjs +85 -0
- package/assets/docs/tree/add-a-topic.doc.mjs +144 -0
- package/assets/docs/tree/agent-guidance.doc.mjs +138 -0
- package/assets/docs/tree/block-template.doc.mjs +130 -0
- package/assets/docs/tree/build-the-template.doc.mjs +28 -0
- package/assets/docs/tree/building-blocks.doc.mjs +46 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +137 -0
- package/assets/docs/tree/checks.doc.mjs +119 -0
- package/assets/docs/tree/codemods.doc.mjs +147 -0
- package/assets/docs/tree/component-family.doc.mjs +113 -0
- package/assets/docs/tree/component-imports.doc.mjs +69 -0
- package/assets/docs/tree/component-lookups.doc.mjs +149 -0
- package/assets/docs/tree/components.doc.mjs +23 -0
- package/assets/docs/tree/configuration.doc.mjs +23 -0
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +182 -0
- package/assets/docs/tree/define-the-theme.doc.mjs +118 -0
- package/assets/docs/tree/describe-the-component.doc.mjs +57 -0
- package/assets/docs/tree/docs.doc.mjs +21 -0
- package/assets/docs/tree/document-the-template.doc.mjs +28 -0
- package/assets/docs/tree/document-the-theme.doc.mjs +68 -0
- package/assets/docs/tree/export-template-assets.doc.mjs +147 -0
- package/assets/docs/tree/extend-or-replace.doc.mjs +103 -0
- package/assets/docs/tree/fonts-and-assets.doc.mjs +106 -0
- package/assets/docs/tree/generate-a-palette.doc.mjs +66 -0
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +105 -0
- package/assets/docs/tree/help.doc.mjs +16 -0
- package/assets/docs/tree/integrations.doc.mjs +25 -451
- package/assets/docs/tree/links.doc.mjs +98 -0
- package/assets/docs/tree/package-and-test.doc.mjs +32 -0
- package/assets/docs/tree/page-template.doc.mjs +71 -0
- package/assets/docs/tree/publishing.doc.mjs +111 -0
- package/assets/docs/tree/quick-start.doc.mjs +272 -0
- package/assets/docs/tree/replace-a-core-component.doc.mjs +104 -0
- package/assets/docs/tree/replace-a-core-template.doc.mjs +172 -0
- package/assets/docs/tree/sections-and-placement.doc.mjs +108 -0
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +59 -0
- package/assets/docs/tree/ship.doc.mjs +16 -0
- package/assets/docs/tree/short-and-findable.doc.mjs +108 -0
- package/assets/docs/tree/single-component.doc.mjs +165 -0
- package/assets/docs/tree/start-a-template.doc.mjs +143 -0
- package/assets/docs/tree/subcomponent.doc.mjs +115 -0
- package/assets/docs/tree/template-assets.doc.mjs +64 -0
- package/assets/docs/tree/template-doc-overview.doc.mjs +109 -0
- package/assets/docs/tree/template-fonts.doc.mjs +102 -0
- package/assets/docs/tree/template-grading-rubric.doc.mjs +452 -0
- package/assets/docs/tree/template-icons.doc.mjs +97 -0
- package/assets/docs/tree/template-images-media.doc.mjs +127 -0
- package/assets/docs/tree/template-styles.doc.mjs +93 -0
- package/assets/docs/tree/templates.doc.mjs +34 -0
- package/assets/docs/tree/test-in-an-app.doc.mjs +115 -0
- package/assets/docs/tree/test-template-in-app.doc.mjs +128 -0
- package/assets/docs/tree/themes.doc.mjs +39 -0
- package/assets/docs/tree/troubleshooting.doc.mjs +149 -0
- package/assets/docs/tree/upgrading.doc.mjs +103 -0
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +51 -0
- package/assets/docs/tree/verify-packed-template.doc.mjs +77 -0
- package/assets/docs/tree/versioning.doc.mjs +161 -0
- package/assets/docs/tree/write-good-templates.doc.mjs +64 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +154 -0
- package/assets/docs/typography.doc.mjs +24 -4
- package/assets/docs/working-with-ai.doc.mjs +30 -22
- package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
- package/authoring/config/config.doc.mjs +9 -1
- package/authoring/config/parse.d.mts +2 -0
- package/authoring/config/parse.mjs +19 -0
- package/authoring/config/parse.test.mjs +8 -0
- package/authoring/config/type.ts +11 -0
- package/authoring/discover/discover.doc.d.mts +13 -0
- package/authoring/discover/discover.doc.mjs +138 -0
- package/authoring/discover/parse.d.mts +24 -0
- package/authoring/discover/parse.mjs +128 -0
- package/authoring/discover/parse.test.mjs +124 -0
- package/authoring/discover/type.ts +87 -0
- package/authoring/doctypes/_schema.d.mts +3 -2
- package/authoring/doctypes/_schema.mjs +6 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
- package/authoring/doctypes/base/type.ts +4 -2
- package/authoring/doctypes/component/component.doc.mjs +6 -0
- package/authoring/doctypes/component/type.ts +8 -0
- package/authoring/doctypes/reference/reference.doc.mjs +7 -0
- package/authoring/doctypes/reference/type.ts +5 -0
- package/authoring/doctypes/schema/schema.doc.mjs +2 -2
- package/authoring/doctypes/template/template.doc.mjs +1 -1
- package/authoring/doctypes/template/type.ts +2 -2
- package/authoring/index.d.mts +1 -0
- package/authoring/index.d.ts +10 -0
- package/authoring/index.mjs +1 -0
- package/authoring/integration/integration.doc.mjs +12 -10
- package/clients/cli/commands/component/index.mjs +152 -55
- package/clients/cli/commands/component-batch.test.mjs +341 -0
- package/clients/cli/commands/component-ownership.test.mjs +89 -0
- package/clients/cli/commands/component.doc.mjs +27 -9
- package/clients/cli/commands/discover.doc.mjs +53 -9
- package/clients/cli/commands/discover.mjs +393 -118
- package/clients/cli/commands/discover.sources.test.mjs +267 -0
- package/clients/cli/commands/docs.doc.mjs +1 -1
- package/clients/cli/commands/docs.mjs +60 -17
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +3 -2
- package/clients/cli/commands/doctor-integration.test.mjs +53 -0
- package/clients/cli/commands/doctor.doc.mjs +3 -1
- package/clients/cli/commands/doctor.mjs +49 -5
- package/clients/cli/commands/gap-report.doc.mjs +10 -9
- package/clients/cli/commands/init.doc.mjs +9 -6
- package/clients/cli/commands/integration-add.doc.mjs +9 -9
- package/clients/cli/commands/integration-authoring.test.mjs +61 -10
- package/clients/cli/commands/integration-pack.doc.mjs +5 -9
- package/clients/cli/commands/integration-real-world.test.mjs +1 -1
- package/clients/cli/commands/integration-verify.doc.mjs +22 -0
- package/clients/cli/commands/integration.doc.mjs +4 -4
- package/clients/cli/commands/integration.mjs +74 -43
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/search.doc.mjs +10 -3
- package/clients/cli/commands/search.mjs +21 -2
- package/clients/cli/commands/search.test.mjs +21 -4
- 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 +7 -1
- package/clients/cli/commands/theme-add.doc.mjs +1 -1
- package/clients/cli/commands/theme-palette-generate.doc.mjs +3 -2
- package/clients/cli/commands/theme-palette.doc.mjs +1 -2
- package/clients/cli/commands/theme-targets.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +2 -1
- package/clients/cli/commands/upgrade.doc.mjs +62 -3
- package/clients/cli/index.mjs +28 -6
- package/clients/cli/lib/define-command.mjs +28 -4
- package/clients/cli/lib/define-command.test.mjs +54 -0
- package/clients/cli/lib/exit-codes.test.mjs +17 -1
- package/clients/cli/lib/json-shim.mjs +24 -14
- package/clients/cli/lib/manifest.mjs +18 -5
- package/clients/cli/lib/manifest.test.mjs +5 -2
- package/clients/cli/lib/parse-error-format.test.mjs +81 -0
- package/foundation/agent-docs/agent-docs.mjs +1 -1
- package/foundation/discovery/authoring-self-docs.mjs +1 -0
- package/foundation/discovery/authoring-self-docs.test.mjs +6 -2
- package/foundation/discovery/cli-self-docs.mjs +16 -2
- package/foundation/discovery/cli-self-docs.test.mjs +20 -0
- package/foundation/discovery/docs-discovery.mjs +5 -1
- package/foundation/discovery/docs-discovery.test.mjs +21 -0
- package/foundation/discovery/docs-section-key.d.mts +1 -1
- package/foundation/discovery/docs-section-key.mjs +1 -1
- package/foundation/doc-compiler/doc-loads.test.mjs +3 -2
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/doc-compiler/tree.d.mts +4 -0
- package/foundation/doc-compiler/tree.mjs +6 -1
- package/foundation/integrations/cli-requirement.d.mts +26 -6
- package/foundation/integrations/cli-requirement.mjs +46 -11
- package/foundation/integrations/cli-requirement.test.mjs +7 -2
- package/foundation/integrations/contribution-inventory.mjs +1 -1
- package/foundation/integrations/integrations.d.mts +14 -1
- package/foundation/integrations/integrations.mjs +41 -1
- package/foundation/integrations/integrations.test.mjs +31 -0
- package/foundation/response/batch.type.d.mts +33 -0
- package/foundation/response/batch.type.mjs +34 -0
- package/foundation/response/error-codes.doc.mjs +6 -8
- package/foundation/response/error-codes.test.mjs +30 -5
- package/foundation/response/response-types.doc.d.mts +4 -3
- package/foundation/response/response-types.doc.mjs +40 -10
- package/foundation/response/response-types.doc.test.mjs +23 -0
- package/foundation/response/response.doc.mjs +11 -10
- package/package.json +9 -9
- package/api/docs/docs.test.mjs +0 -243
- package/api/docs/integration-tree.test.mjs +0 -555
- package/api/docs/integrationDocs.test.mjs +0 -314
- package/api/search/search.test.mjs +0 -512
- package/assets/docs/tree/integrations.test.mjs +0 -62
- package/assets/docs/tree/writing-docs.doc.mjs +0 -286
- package/clients/cli/commands/docs.test.mjs +0 -294
- package/foundation/agent-docs/agent-docs.test.mjs +0 -1159
- package/foundation/doc-compiler/tree.test.mjs +0 -598
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Shared published types for complete multi-selector lookup receipts.
|
|
5
|
+
* Adopting API subjects specialize these types with their single-result and
|
|
6
|
+
* ambiguity-candidate types instead of defining command-specific row shapes.
|
|
7
|
+
*
|
|
8
|
+
* @input One exact selector, its single-result response, and its candidate shape.
|
|
9
|
+
* @output BatchRow and BatchResponse for every AST-053 lookup adopter.
|
|
10
|
+
* @position packages/cli/foundation/response — shared JSON response types
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* One complete row for an accepted selector.
|
|
15
|
+
* @template TResult
|
|
16
|
+
* @template TCandidate
|
|
17
|
+
* @typedef {(
|
|
18
|
+
* | {selector: string; status: 'found'; result: TResult}
|
|
19
|
+
* | {selector: string; status: 'ambiguous'; code: string; error: string; candidates: TCandidate[]}
|
|
20
|
+
* | {selector: string; status: 'not_found' | 'error'; code: string; error: string; suggestions?: import('./base').Suggestion[]}
|
|
21
|
+
* )} BatchRow
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* One ordered batch receipt inside the shared `{type, data}` success envelope.
|
|
26
|
+
* @template {string} TType
|
|
27
|
+
* @template TResult
|
|
28
|
+
* @template TCandidate
|
|
29
|
+
* @typedef {object} BatchResponse
|
|
30
|
+
* @property {TType} type
|
|
31
|
+
* @property {{count: number; results: BatchRow<TResult, TCandidate>[]}} data
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
export {};
|
|
@@ -36,17 +36,16 @@ export const doc = {
|
|
|
36
36
|
{
|
|
37
37
|
value: 'ERR_INVALID_OPTION',
|
|
38
38
|
description:
|
|
39
|
-
'An unknown
|
|
39
|
+
'An unknown option was passed, --json was given to a command without JSON output, or layout --form got a value other than compact, outline, or auto.',
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
value: 'ERR_INVALID_ARGUMENT',
|
|
43
43
|
description:
|
|
44
|
-
|
|
44
|
+
'An argument or option value is invalid: wrong type, out of range, an unknown choice, an extra argument, or a conflicting combination.',
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
value: 'ERR_MISSING_ARGUMENT',
|
|
48
|
-
description:
|
|
49
|
-
'A required positional argument was omitted (Commander `missingArgument`).',
|
|
48
|
+
description: 'A required argument or option value was omitted.',
|
|
50
49
|
},
|
|
51
50
|
{
|
|
52
51
|
value: 'ERR_INVALID_LANG',
|
|
@@ -134,12 +133,11 @@ export const doc = {
|
|
|
134
133
|
},
|
|
135
134
|
{
|
|
136
135
|
value: 'ERR_UNKNOWN_PACKAGE',
|
|
137
|
-
description: 'No package matched the requested name
|
|
136
|
+
description: 'No package matched the requested name.',
|
|
138
137
|
},
|
|
139
138
|
{
|
|
140
139
|
value: 'ERR_UNKNOWN_AGENT',
|
|
141
|
-
description:
|
|
142
|
-
'An unrecognized `--agent` value was passed to agent-docs/init.',
|
|
140
|
+
description: 'An unrecognized `--agent` value was passed to init.',
|
|
143
141
|
},
|
|
144
142
|
{
|
|
145
143
|
value: 'ERR_UNKNOWN_FEATURE',
|
|
@@ -272,7 +270,7 @@ export const doc = {
|
|
|
272
270
|
{
|
|
273
271
|
value: 'ERR_UNCLASSIFIED_EXIT',
|
|
274
272
|
description:
|
|
275
|
-
'Recorded in the debug log, never printed: a command exited non-zero without
|
|
273
|
+
'Recorded in the debug log, never printed: a command exited non-zero without reporting an error code.',
|
|
276
274
|
},
|
|
277
275
|
{
|
|
278
276
|
value: 'ERR_SIGNAL_TERMINATED',
|
|
@@ -195,9 +195,16 @@ describe('error codes: end-to-end JSON envelopes', () => {
|
|
|
195
195
|
// is rejected at the preAction gate with a stable invalid-option code.
|
|
196
196
|
{
|
|
197
197
|
name: 'json not supported',
|
|
198
|
-
args: ['theme', '
|
|
198
|
+
args: ['theme', '--json'],
|
|
199
199
|
code: 'ERR_INVALID_OPTION',
|
|
200
200
|
},
|
|
201
|
+
// A group given a word it does not have names the unknown subcommand,
|
|
202
|
+
// in JSON as in text.
|
|
203
|
+
{
|
|
204
|
+
name: 'unknown subcommand of a group',
|
|
205
|
+
args: ['theme', 'bogus-sub', '--json'],
|
|
206
|
+
code: 'ERR_UNKNOWN_SUBCOMMAND',
|
|
207
|
+
},
|
|
201
208
|
];
|
|
202
209
|
|
|
203
210
|
for (const {name, args, code} of cases) {
|
|
@@ -249,13 +256,31 @@ describe('error codes: human mode stays clean', () => {
|
|
|
249
256
|
expect(stdout).not.toContain('ERR_UNKNOWN_COMPONENT');
|
|
250
257
|
});
|
|
251
258
|
|
|
252
|
-
it('unknown subcommand exits 1 in
|
|
253
|
-
//
|
|
254
|
-
//
|
|
255
|
-
// ERR_UNKNOWN_SUBCOMMAND code rides along on the cliError call.
|
|
259
|
+
it('unknown subcommand exits 1, with the code in JSON and not in text', async () => {
|
|
260
|
+
// A group that is not JSON-capable itself still answers an unknown
|
|
261
|
+
// subcommand in JSON, so a JSON caller learns the subcommands it has.
|
|
256
262
|
const {status, stderr} = await runCli(['theme', 'bogus-sub']);
|
|
257
263
|
expect(status).toBe(1);
|
|
258
264
|
expect(stderr).toContain("unknown subcommand 'theme bogus-sub'");
|
|
259
265
|
expect(stderr).not.toContain('ERR_UNKNOWN_SUBCOMMAND');
|
|
266
|
+
for (const args of [
|
|
267
|
+
['--json', 'theme', 'bogus-sub'],
|
|
268
|
+
['theme', 'bogus-sub', '--json'],
|
|
269
|
+
['--json', 'doctor', 'integration', 'bogus-sub'],
|
|
270
|
+
]) {
|
|
271
|
+
const json = await runCli(args);
|
|
272
|
+
expect(json.status, args.join(' ')).toBe(1);
|
|
273
|
+
expect(JSON.parse(json.stdout), args.join(' ')).toMatchObject({
|
|
274
|
+
code: 'ERR_UNKNOWN_SUBCOMMAND',
|
|
275
|
+
suggestions: expect.arrayContaining([expect.objectContaining({reason: 'available subcommand'})]),
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
// Text and JSON agree for a group that shows help when run bare.
|
|
279
|
+
const text = await runCli(['doctor', 'integration', 'bogus-sub']);
|
|
280
|
+
expect(text.status).toBe(1);
|
|
281
|
+
expect(text.stderr).toContain("unknown subcommand 'doctor integration bogus-sub'");
|
|
282
|
+
const doctor = await runCli(['doctor', 'integrations']);
|
|
283
|
+
expect(doctor.status).toBe(1);
|
|
284
|
+
expect(doctor.stderr).toContain("unknown subcommand 'doctor integrations'");
|
|
260
285
|
});
|
|
261
286
|
});
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
/**
|
|
5
5
|
* @file EnumDoc for the `type` discriminant carried on every --json success
|
|
6
6
|
* envelope. The vocabulary mirrors the RESPONSE_TYPES map (each command's
|
|
7
|
-
* `jsonOut(...)` call sites)
|
|
8
|
-
* switches on `type` to narrow the
|
|
9
|
-
*
|
|
7
|
+
* `jsonOut(...)` call sites) plus ROOT_RESPONSE_TYPES (help, version) in
|
|
8
|
+
* `clients/cli/lib/manifest.mjs`; a consumer switches on `type` to narrow the
|
|
9
|
+
* `data` payload. Descriptions follow the currently published response
|
|
10
|
+
* projection, not a future package-version boundary.
|
|
10
11
|
*
|
|
11
12
|
* @input Public response discriminants and their currently released payloads.
|
|
12
13
|
* @output Generated consumer reference for every typed JSON success response.
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* @file EnumDoc for the `type` discriminant carried on every --json success
|
|
5
5
|
* envelope. The vocabulary mirrors the RESPONSE_TYPES map (each command's
|
|
6
|
-
* `jsonOut(...)` call sites)
|
|
7
|
-
* switches on `type` to narrow the
|
|
8
|
-
*
|
|
6
|
+
* `jsonOut(...)` call sites) plus ROOT_RESPONSE_TYPES (help, version) in
|
|
7
|
+
* `clients/cli/lib/manifest.mjs`; a consumer switches on `type` to narrow the
|
|
8
|
+
* `data` payload. Descriptions follow the currently published response
|
|
9
|
+
* projection, not a future package-version boundary.
|
|
9
10
|
*
|
|
10
11
|
* @input Public response discriminants and their currently released payloads.
|
|
11
12
|
* @output Generated consumer reference for every typed JSON success response.
|
|
@@ -35,7 +36,12 @@ export const doc = {
|
|
|
35
36
|
{
|
|
36
37
|
value: 'component.list',
|
|
37
38
|
description:
|
|
38
|
-
|
|
39
|
+
"The component catalog grouped by component group (each component's group field): `detail` (the level: names | compact | full) and `components`, the grouped map of names entries ({name, package, and optional canonical import for integrations}), brief entries, or a full ComponentDoc per entry.",
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
value: 'component.batch',
|
|
43
|
+
description:
|
|
44
|
+
'The component specialization of the shared `BatchResponse` and `BatchRow` types. An explicit programmatic selector array, or two or more CLI selectors, returns one ordered receipt: `count` plus `results`, one row per selector including duplicates. Every row carries `selector` and `status` (found | not_found | ambiguous | error). A found row carries `result`, the same {type, data} response as one selector. An ambiguous row carries `code`, `error`, and `candidates` ({package, component, kind, installed}). Other failed rows carry `code`, `error`, and optional `suggestions` ({name, reason}).',
|
|
39
45
|
},
|
|
40
46
|
{
|
|
41
47
|
value: 'component.detail',
|
|
@@ -104,21 +110,27 @@ export const doc = {
|
|
|
104
110
|
{
|
|
105
111
|
value: 'discover.list',
|
|
106
112
|
description:
|
|
107
|
-
'The
|
|
113
|
+
'The integrations the project loads (name, category, components, version, a list per other kind they add, and latest when a source knows it); with a discover source, meta.available lists what the project could add and meta.sources reports each source; when empty it carries meta.configured to tell "nothing configured" from "nothing discovered".',
|
|
108
114
|
},
|
|
109
115
|
{
|
|
110
116
|
value: 'discover.detail',
|
|
111
|
-
description:
|
|
117
|
+
description:
|
|
118
|
+
'One package, for an @scope/name or @scope/name@version query: what the shown version adds, whether the project has it, and, when a source knows the package, its versions, latest release, and the command that adds it.',
|
|
112
119
|
},
|
|
113
120
|
{
|
|
114
121
|
value: 'discover.detail.doc',
|
|
115
122
|
description:
|
|
116
|
-
'The validated ComponentDoc for one
|
|
123
|
+
'The validated ComponentDoc for one installed component, for an @scope/name/Component query.',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
value: 'discover.item',
|
|
127
|
+
description:
|
|
128
|
+
'One item that is not an installed component, for an @scope/name/<item> query: its kind, name, package, version, and whether the project has the package.',
|
|
117
129
|
},
|
|
118
130
|
{
|
|
119
131
|
value: 'discover.search',
|
|
120
132
|
description:
|
|
121
|
-
'The echoed query plus
|
|
133
|
+
'The echoed query plus every matching item and package across all packages, each with its kind and whether the project has it, even when only one matches; total is set when --limit cut the list.',
|
|
122
134
|
},
|
|
123
135
|
|
|
124
136
|
// search
|
|
@@ -149,7 +161,7 @@ export const doc = {
|
|
|
149
161
|
{
|
|
150
162
|
value: 'swizzle.copy',
|
|
151
163
|
description:
|
|
152
|
-
'An eject receipt: component name, owning package, output directory, files-copied count, the written file names, whether any file uses StyleX, and an
|
|
164
|
+
'An eject receipt: component name, owning package, output directory, files-copied count, the written file names, whether any file uses StyleX, and, when the owner has an issues URL, feedback ({issuesUrl, ghCommand?}): where to report the gap that led to swizzling.',
|
|
153
165
|
},
|
|
154
166
|
|
|
155
167
|
// gap reports
|
|
@@ -251,6 +263,11 @@ export const doc = {
|
|
|
251
263
|
description:
|
|
252
264
|
'Every available codemod, oldest→newest, as {name, title, version, optional}; returned for --list without running anything.',
|
|
253
265
|
},
|
|
266
|
+
{
|
|
267
|
+
value: 'upgrade.registry',
|
|
268
|
+
description:
|
|
269
|
+
'The copied-composition receipt for --registry: applied, ok, the counts (found, current, wouldUpdate, updated, wouldMerge, merged, wouldRefreshReceipt, receiptsRefreshed, conflicts, missing, invalid, failed), and items.',
|
|
270
|
+
},
|
|
254
271
|
{
|
|
255
272
|
value: 'upgrade.status',
|
|
256
273
|
description:
|
|
@@ -269,11 +286,24 @@ export const doc = {
|
|
|
269
286
|
'The CLI capability manifest: name, version, apiVersion, description, globalOptions, commands (each name, description, arguments, options, json, aliases?, responseTypes?, examples?, exitCodes? as [{code, when}], subcommands?), jsonSupported, and the flat responseTypes index.',
|
|
270
287
|
},
|
|
271
288
|
|
|
289
|
+
// help and version, which no single command owns
|
|
290
|
+
{
|
|
291
|
+
value: 'help',
|
|
292
|
+
description:
|
|
293
|
+
'Help, in one of two shapes. A bare `astryx --json` returns the root manifest: name, version, commands (the command names), jsonSupported, and manifest (the full payload `astryx manifest --json` returns). ' +
|
|
294
|
+
"`--help --json` on any command, or `astryx help [command] --json`, returns that command's help: command, description, usage, options (each flags, description, and defaultValue and choices when set), and subcommands (each name and description). " +
|
|
295
|
+
'data.manifest marks the first shape; data.usage marks the second.',
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
value: 'version',
|
|
299
|
+
description: 'The CLI version, for `astryx --version --json`: {version}.',
|
|
300
|
+
},
|
|
301
|
+
|
|
272
302
|
// doctor
|
|
273
303
|
{
|
|
274
304
|
value: 'doctor',
|
|
275
305
|
description:
|
|
276
|
-
'The health-check report: `checks` (each with id, label, status: pass | warn | fail | info, a message, and
|
|
306
|
+
'The health-check report: `checks` (each with id, label, status: pass | warn | fail | info, a message, and an optional fix, always present on warn and fail) plus a `summary` of counts per status.',
|
|
277
307
|
},
|
|
278
308
|
|
|
279
309
|
// integration authoring
|
|
@@ -53,6 +53,29 @@ function expectNamed(type, fields) {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
describe('response-types EnumDoc names every field', () => {
|
|
56
|
+
it('component.batch names every row field and state', async () => {
|
|
57
|
+
const res = await data(['component', 'Button', 'Badge']);
|
|
58
|
+
expect(res.type).toBe('component.batch');
|
|
59
|
+
expect(describedAs('component.batch')).toMatch(/BatchResponse.*BatchRow/);
|
|
60
|
+
expectNamed('component.batch', [
|
|
61
|
+
'count',
|
|
62
|
+
'results',
|
|
63
|
+
'selector',
|
|
64
|
+
'status',
|
|
65
|
+
'result',
|
|
66
|
+
'code',
|
|
67
|
+
'error',
|
|
68
|
+
'candidates',
|
|
69
|
+
'package',
|
|
70
|
+
'component',
|
|
71
|
+
'kind',
|
|
72
|
+
'installed',
|
|
73
|
+
'suggestions',
|
|
74
|
+
'name',
|
|
75
|
+
'reason',
|
|
76
|
+
]);
|
|
77
|
+
});
|
|
78
|
+
|
|
56
79
|
it('component.detail: the ownership fields and parentDoc', async () => {
|
|
57
80
|
const res = await data(['component', 'HStack']);
|
|
58
81
|
expect(res.type).toBe('component.detail');
|
|
@@ -39,16 +39,13 @@ export const doc = {
|
|
|
39
39
|
name: 'type',
|
|
40
40
|
type: 'string',
|
|
41
41
|
description:
|
|
42
|
-
'
|
|
43
|
-
'its own `type` at its return; there is no central union.',
|
|
42
|
+
'Names the payload shape. Every value is listed in the response-types enum.',
|
|
44
43
|
required: true,
|
|
45
44
|
},
|
|
46
45
|
{
|
|
47
46
|
name: 'data',
|
|
48
47
|
type: 'unknown',
|
|
49
|
-
description:
|
|
50
|
-
"The command's payload. Structural by design, narrowed by the " +
|
|
51
|
-
'per-command return type, not by a map in the serializer.',
|
|
48
|
+
description: "The command's payload; its shape depends on `type`.",
|
|
52
49
|
required: true,
|
|
53
50
|
},
|
|
54
51
|
{
|
|
@@ -64,7 +61,7 @@ export const doc = {
|
|
|
64
61
|
type: '{ apiVersion: number; error: string; code: ErrorCode; suggestions?: Suggestion[] }',
|
|
65
62
|
description:
|
|
66
63
|
'Emitted for every failure in --json mode, including uncaught throws ' +
|
|
67
|
-
'and
|
|
64
|
+
'and command-line parse errors, which are converted to this shape.',
|
|
68
65
|
fields: [
|
|
69
66
|
{
|
|
70
67
|
name: 'apiVersion',
|
|
@@ -121,7 +118,7 @@ export const doc = {
|
|
|
121
118
|
label: 'Success',
|
|
122
119
|
code: `{
|
|
123
120
|
"apiVersion": 1,
|
|
124
|
-
"type": "component",
|
|
121
|
+
"type": "component.detail",
|
|
125
122
|
"data": { "name": "Button" }
|
|
126
123
|
}`,
|
|
127
124
|
},
|
|
@@ -153,9 +150,13 @@ export const doc = {
|
|
|
153
150
|
{
|
|
154
151
|
type: 'prose',
|
|
155
152
|
text:
|
|
156
|
-
'The process exit code is part of the contract too
|
|
157
|
-
'
|
|
158
|
-
'(
|
|
153
|
+
'The process exit code is part of the contract too. Exit 0 means success, ' +
|
|
154
|
+
'and every error envelope exits 1. Some commands also exit 1 with a success ' +
|
|
155
|
+
'envelope when what they report failed: a failed check (layout check, doctor ' +
|
|
156
|
+
'and its integration subcommands, integration verify, theme build ' +
|
|
157
|
+
'--check), a gap report that was not delivered, an upgrade left incomplete, ' +
|
|
158
|
+
'or init agent docs refused for a path outside the project. Read the ' +
|
|
159
|
+
'envelope, not the exit code, to tell them apart.',
|
|
159
160
|
},
|
|
160
161
|
],
|
|
161
162
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/cli",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5-canary.031021b",
|
|
4
4
|
"displayName": "CLI",
|
|
5
5
|
"description": "Scaffold projects, browse templates, generate themes, and get agent-ready docs from the command line.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -101,10 +101,10 @@
|
|
|
101
101
|
"zod": "^4.4.3"
|
|
102
102
|
},
|
|
103
103
|
"peerDependencies": {
|
|
104
|
-
"@astryxdesign/charts": "
|
|
105
|
-
"@astryxdesign/core": "
|
|
106
|
-
"@astryxdesign/lab": "
|
|
107
|
-
"@astryxdesign/theme-neutral": "
|
|
104
|
+
"@astryxdesign/charts": "0.6.5-canary.031021b",
|
|
105
|
+
"@astryxdesign/core": "0.6.5-canary.031021b",
|
|
106
|
+
"@astryxdesign/lab": "0.6.5-canary.031021b",
|
|
107
|
+
"@astryxdesign/theme-neutral": "0.6.5-canary.031021b"
|
|
108
108
|
},
|
|
109
109
|
"peerDependenciesMeta": {
|
|
110
110
|
"@astryxdesign/charts": {
|
|
@@ -121,10 +121,10 @@
|
|
|
121
121
|
}
|
|
122
122
|
},
|
|
123
123
|
"devDependencies": {
|
|
124
|
-
"@astryxdesign/charts": "
|
|
125
|
-
"@astryxdesign/core": "
|
|
126
|
-
"@astryxdesign/lab": "
|
|
127
|
-
"@astryxdesign/theme-neutral": "
|
|
124
|
+
"@astryxdesign/charts": "0.6.5-canary.031021b",
|
|
125
|
+
"@astryxdesign/core": "0.6.5-canary.031021b",
|
|
126
|
+
"@astryxdesign/lab": "0.6.5-canary.031021b",
|
|
127
|
+
"@astryxdesign/theme-neutral": "0.6.5-canary.031021b",
|
|
128
128
|
"@heroicons/react": "^2.2.0",
|
|
129
129
|
"@stylexjs/stylex": "^0.19.0",
|
|
130
130
|
"@types/babel__core": "^7.20.5",
|
package/api/docs/docs.test.mjs
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file Dispatcher-level tests for docs() — the argument-shape routing that
|
|
5
|
-
* sits above the list/detail/section leaves. The leaves have their own tests;
|
|
6
|
-
* this pins the router: docs() -> list, docs(topic) -> detail,
|
|
7
|
-
* docs(topic, section) -> section, plus the unknown-topic/section error codes.
|
|
8
|
-
* Runs against the real CLI-bundled docs (no cwd/project needed).
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import {describe, it, expect} from 'vitest';
|
|
12
|
-
import {docs} from './docs.mjs';
|
|
13
|
-
import {AstryxError} from '../error.mjs';
|
|
14
|
-
|
|
15
|
-
const SLOW = 30_000;
|
|
16
|
-
|
|
17
|
-
describe('docs() dispatcher routing', () => {
|
|
18
|
-
it('no topic -> docs.list', async () => {
|
|
19
|
-
const r = await docs();
|
|
20
|
-
expect(r.type).toBe('docs.list');
|
|
21
|
-
expect(Array.isArray(r.data)).toBe(true);
|
|
22
|
-
expect(r.data.length).toBeGreaterThan(0);
|
|
23
|
-
}, SLOW);
|
|
24
|
-
|
|
25
|
-
it('empty topic -> docs.list (falsy topic routes to list)', async () => {
|
|
26
|
-
expect((await docs('')).type).toBe('docs.list');
|
|
27
|
-
}, SLOW);
|
|
28
|
-
|
|
29
|
-
it('topic only -> docs.detail, the whole doc', async () => {
|
|
30
|
-
const {data} = await docs();
|
|
31
|
-
expect((await docs(data[0].topic)).type).toBe('docs.detail');
|
|
32
|
-
}, SLOW);
|
|
33
|
-
|
|
34
|
-
it('topic + index -> docs.index', async () => {
|
|
35
|
-
const {data} = await docs();
|
|
36
|
-
const r = await docs(data[0].topic, undefined, {index: true});
|
|
37
|
-
expect(r.type).toBe('docs.index');
|
|
38
|
-
}, SLOW);
|
|
39
|
-
|
|
40
|
-
it('topic + section -> docs.detail.section', async () => {
|
|
41
|
-
const {data} = await docs();
|
|
42
|
-
let routed = null;
|
|
43
|
-
for (const {topic} of data) {
|
|
44
|
-
const detail = await docs(topic);
|
|
45
|
-
const sections = detail.data.sections;
|
|
46
|
-
if (Array.isArray(sections) && sections.length > 0) {
|
|
47
|
-
routed = await docs(topic, sections[0].title);
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
expect(routed).not.toBeNull();
|
|
52
|
-
expect(routed.type).toBe('docs.detail.section');
|
|
53
|
-
}, SLOW);
|
|
54
|
-
|
|
55
|
-
it('unknown topic -> ERR_UNKNOWN_TOPIC', async () => {
|
|
56
|
-
await expect(docs('zzz-not-a-real-topic')).rejects.toBeInstanceOf(AstryxError);
|
|
57
|
-
await expect(docs('zzz-not-a-real-topic')).rejects.toMatchObject({
|
|
58
|
-
code: 'ERR_UNKNOWN_TOPIC',
|
|
59
|
-
});
|
|
60
|
-
}, SLOW);
|
|
61
|
-
|
|
62
|
-
it('known topic + unknown section -> ERR_UNKNOWN_SECTION', async () => {
|
|
63
|
-
const {data} = await docs();
|
|
64
|
-
const topic = data[0].topic;
|
|
65
|
-
await expect(docs(topic, 'zzz-not-a-real-section')).rejects.toMatchObject({
|
|
66
|
-
code: 'ERR_UNKNOWN_SECTION',
|
|
67
|
-
});
|
|
68
|
-
}, SLOW);
|
|
69
|
-
|
|
70
|
-
it("lists the docs tree's namespaces in meta, so every data entry reads as a topic", async () => {
|
|
71
|
-
const res = await docs();
|
|
72
|
-
expect(res.meta.namespaces.map(entry => entry.topic)).toEqual(['cli', 'unorganized']);
|
|
73
|
-
for (const entry of res.data) {
|
|
74
|
-
expect((await docs(entry.topic)).type).toBe('docs.detail');
|
|
75
|
-
}
|
|
76
|
-
}, SLOW);
|
|
77
|
-
|
|
78
|
-
it('opens a route typed in another case', async () => {
|
|
79
|
-
const r = await docs('CLI/API');
|
|
80
|
-
expect(r.type).toBe('docs.node');
|
|
81
|
-
expect(r.data).toMatchObject({route: 'cli/api', links: {up: 'astryx docs cli'}});
|
|
82
|
-
}, SLOW);
|
|
83
|
-
|
|
84
|
-
it('a section of a typed doc -> ERR_UNKNOWN_SECTION, suggesting the doc itself', async () => {
|
|
85
|
-
const err = await docs('cli/api/functions/search', 'x').catch(e => e);
|
|
86
|
-
expect(err.code).toBe('ERR_UNKNOWN_SECTION');
|
|
87
|
-
expect(err.message).toContain('astryx docs cli/api/functions/search');
|
|
88
|
-
expect(err.suggestions.map(s => s.name)).toEqual(['cli/api/functions/search']);
|
|
89
|
-
}, SLOW);
|
|
90
|
-
|
|
91
|
-
it('a namespace route -> docs.node, one level of children', async () => {
|
|
92
|
-
const r = await docs('cli/api');
|
|
93
|
-
expect(r.type).toBe('docs.node');
|
|
94
|
-
expect(r.data).toMatchObject({
|
|
95
|
-
id: 'astryx:artifact:v1/%40astryxdesign%2Fcli/namespace/api',
|
|
96
|
-
route: 'cli/api',
|
|
97
|
-
kind: 'namespace',
|
|
98
|
-
package: '@astryxdesign/cli',
|
|
99
|
-
breadcrumb: [{route: 'cli', title: 'Astryx CLI'}],
|
|
100
|
-
content: [],
|
|
101
|
-
});
|
|
102
|
-
expect(r.data.slots.flatMap(slot => slot.children.map(c => c.route))).toEqual([
|
|
103
|
-
'cli/api/functions',
|
|
104
|
-
'cli/api/schemas',
|
|
105
|
-
'cli/api/enums',
|
|
106
|
-
]);
|
|
107
|
-
}, SLOW);
|
|
108
|
-
|
|
109
|
-
it('a typed doc route -> docs.node with its content', async () => {
|
|
110
|
-
const r = await docs('cli/api/functions/search');
|
|
111
|
-
expect(r.type).toBe('docs.node');
|
|
112
|
-
expect(r.data).toMatchObject({
|
|
113
|
-
id: 'astryx:artifact:v1/%40astryxdesign%2Fcli/function/search',
|
|
114
|
-
kind: 'function',
|
|
115
|
-
title: 'search()',
|
|
116
|
-
slots: [],
|
|
117
|
-
});
|
|
118
|
-
expect(r.data.breadcrumb.map(link => link.route)).toEqual([
|
|
119
|
-
'cli',
|
|
120
|
-
'cli/api',
|
|
121
|
-
'cli/api/functions',
|
|
122
|
-
]);
|
|
123
|
-
expect(JSON.stringify(r.data.content)).toContain(
|
|
124
|
-
'`astryx search` runs it. Read it with `astryx docs cli/commands/search`.',
|
|
125
|
-
);
|
|
126
|
-
}, SLOW);
|
|
127
|
-
|
|
128
|
-
it('a guide the tree places reads like a topic: the whole doc, its index, a section', async () => {
|
|
129
|
-
expect((await docs('cli/integrations')).type).toBe('docs.detail');
|
|
130
|
-
const index = await docs('cli/integrations', undefined, {index: true});
|
|
131
|
-
expect(index).toMatchObject({type: 'docs.index', data: {name: 'cli/integrations'}});
|
|
132
|
-
expect(index.data.sections.length).toBeGreaterThan(1);
|
|
133
|
-
expect((await docs('cli/integrations', 'components')).type).toBe(
|
|
134
|
-
'docs.detail.section',
|
|
135
|
-
);
|
|
136
|
-
}, SLOW);
|
|
137
|
-
|
|
138
|
-
it('every read carries its moves (spec:AST-047)', async () => {
|
|
139
|
-
const root = (await docs('cli')).data;
|
|
140
|
-
expect(root.links).toEqual({up: 'astryx docs'});
|
|
141
|
-
const leaf = (await docs('cli/api/functions/search')).data;
|
|
142
|
-
expect(leaf.links.up).toBe('astryx docs cli/api/functions');
|
|
143
|
-
expect(leaf.links.previous).toMatch(/^astryx docs cli\/api\/functions\/[a-z-]+$/);
|
|
144
|
-
expect(leaf.links.next).toMatch(/^astryx docs cli\/api\/functions\/[a-z-]+$/);
|
|
145
|
-
const index = await docs('cli/integrations', undefined, {index: true});
|
|
146
|
-
// A guide moves across its namespace's slot, as any tree node does.
|
|
147
|
-
expect(index.data.links).toEqual({
|
|
148
|
-
up: 'astryx docs cli',
|
|
149
|
-
next: 'astryx docs cli/writing-docs',
|
|
150
|
-
});
|
|
151
|
-
const first = (await docs('cli/integrations', index.data.sections[0].id)).data;
|
|
152
|
-
expect(first.links).toEqual({
|
|
153
|
-
up: 'astryx docs cli/integrations --index',
|
|
154
|
-
next: `astryx docs cli/integrations ${index.data.sections[1].id}`,
|
|
155
|
-
});
|
|
156
|
-
const last = index.data.sections.at(-1).id;
|
|
157
|
-
const end = (await docs('cli/integrations', last)).data;
|
|
158
|
-
expect(end.links.next).toBeUndefined();
|
|
159
|
-
expect(end.links.previous).toBe(
|
|
160
|
-
`astryx docs cli/integrations ${index.data.sections.at(-2).id}`,
|
|
161
|
-
);
|
|
162
|
-
// A flat topic's home is the Unorganized level, and it moves across it.
|
|
163
|
-
const flat = (await docs('principles')).data.links;
|
|
164
|
-
expect(flat.up).toBe('astryx docs unorganized');
|
|
165
|
-
expect(flat.previous).toMatch(/^astryx docs [a-z-]+$/);
|
|
166
|
-
expect(flat.next).toMatch(/^astryx docs [a-z-]+$/);
|
|
167
|
-
const home = (await docs('unorganized')).data;
|
|
168
|
-
expect(home).toMatchObject({id: null, kind: 'namespace', links: {up: 'astryx docs'}});
|
|
169
|
-
expect(home.slots[0].children.map(child => child.route)).toEqual(
|
|
170
|
-
(await docs()).data.map(entry => entry.topic),
|
|
171
|
-
);
|
|
172
|
-
}, SLOW);
|
|
173
|
-
|
|
174
|
-
it('names a node by its doc identity; a generated level has id null', async () => {
|
|
175
|
-
const level = (await docs('cli/api/functions')).data;
|
|
176
|
-
expect(level).toHaveProperty('id', null);
|
|
177
|
-
expect(level.route).toBe('cli/api/functions');
|
|
178
|
-
}, SLOW);
|
|
179
|
-
|
|
180
|
-
it("offers a typed doc's related docs as moves", async () => {
|
|
181
|
-
const fn = (await docs('cli/api/functions/search')).data;
|
|
182
|
-
expect(fn.links.related).toContain('astryx docs cli/commands/search');
|
|
183
|
-
const cmd = (await docs('cli/commands/search')).data;
|
|
184
|
-
expect(cmd.links.related).toContain('astryx docs cli/api/functions/search');
|
|
185
|
-
}, SLOW);
|
|
186
|
-
|
|
187
|
-
it('a topic read returns the whole doc; index returns its sections', async () => {
|
|
188
|
-
expect((await docs('principles')).type).toBe('docs.detail');
|
|
189
|
-
const index = await docs('principles', undefined, {index: true});
|
|
190
|
-
expect(index.type).toBe('docs.index');
|
|
191
|
-
expect(index.data.sections.length).toBeGreaterThan(1);
|
|
192
|
-
expect((await docs('principles', undefined, {dense: true})).type).toBe(
|
|
193
|
-
'docs.detail',
|
|
194
|
-
);
|
|
195
|
-
}, SLOW);
|
|
196
|
-
|
|
197
|
-
it("the guide's old flat name is gone, and its error names the new route", async () => {
|
|
198
|
-
await expect(docs('cli-integrations')).rejects.toMatchObject({
|
|
199
|
-
code: 'ERR_UNKNOWN_TOPIC',
|
|
200
|
-
suggestions: [expect.objectContaining({name: 'cli/integrations'})],
|
|
201
|
-
});
|
|
202
|
-
expect((await docs()).data.map(entry => entry.topic)).not.toContain(
|
|
203
|
-
'cli-integrations',
|
|
204
|
-
);
|
|
205
|
-
}, SLOW);
|
|
206
|
-
|
|
207
|
-
it('a section of a namespace -> ERR_UNKNOWN_SECTION, naming its children', async () => {
|
|
208
|
-
const err = await docs('cli', 'commands').catch(e => e);
|
|
209
|
-
expect(err).toBeInstanceOf(AstryxError);
|
|
210
|
-
expect(err.code).toBe('ERR_UNKNOWN_SECTION');
|
|
211
|
-
expect(err.suggestions.map(s => s.name)).toEqual([
|
|
212
|
-
'cli/integrations',
|
|
213
|
-
'cli/writing-docs',
|
|
214
|
-
'cli/commands',
|
|
215
|
-
'cli/api',
|
|
216
|
-
]);
|
|
217
|
-
}, SLOW);
|
|
218
|
-
|
|
219
|
-
it('an unknown route suggests the children of the deepest namespace it reaches', async () => {
|
|
220
|
-
const err = await docs('cli/api/functions/serch').catch(e => e);
|
|
221
|
-
expect(err.code).toBe('ERR_UNKNOWN_TOPIC');
|
|
222
|
-
expect(err.suggestions.map(s => s.name)).toContain('cli/api/functions/search');
|
|
223
|
-
expect(err.suggestions.every(s => s.name.startsWith('cli/api/functions/'))).toBe(true);
|
|
224
|
-
}, SLOW);
|
|
225
|
-
|
|
226
|
-
it('non-string topic -> ERR_UNKNOWN_TOPIC (not a raw TypeError)', async () => {
|
|
227
|
-
for (const bad of [123, {}, ['tokens'], true]) {
|
|
228
|
-
const err = await docs(/** @type {any} */ (bad)).catch(e => e);
|
|
229
|
-
expect(err).toBeInstanceOf(AstryxError);
|
|
230
|
-
expect(err.code).toBe('ERR_UNKNOWN_TOPIC');
|
|
231
|
-
}
|
|
232
|
-
}, SLOW);
|
|
233
|
-
|
|
234
|
-
it('non-string section -> ERR_UNKNOWN_SECTION (not a raw TypeError)', async () => {
|
|
235
|
-
const {data} = await docs();
|
|
236
|
-
const topic = data[0].topic;
|
|
237
|
-
for (const bad of [456, {}, ['x']]) {
|
|
238
|
-
const err = await docs(topic, /** @type {any} */ (bad)).catch(e => e);
|
|
239
|
-
expect(err).toBeInstanceOf(AstryxError);
|
|
240
|
-
expect(err.code).toBe('ERR_UNKNOWN_SECTION');
|
|
241
|
-
}
|
|
242
|
-
}, SLOW);
|
|
243
|
-
});
|