@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
|
@@ -18,21 +18,22 @@ export const doc = {
|
|
|
18
18
|
'Non-interactive project setup (no prompts, so it behaves the same for humans, ' +
|
|
19
19
|
'agents, and CI). By default it installs the AGENTS.md/CLAUDE.md agent-docs, ' +
|
|
20
20
|
'including guidance from configured integrations, and prints getting-started ' +
|
|
21
|
-
|
|
22
|
-
'
|
|
21
|
+
"steps. --features and --all print only the chosen features' guidance (no " +
|
|
22
|
+
'getting-started steps); the theme feature also writes an annotated theme template.',
|
|
23
23
|
fn: 'init',
|
|
24
24
|
options: [
|
|
25
25
|
{
|
|
26
26
|
flag: '--features <list>',
|
|
27
27
|
param: 'options.features',
|
|
28
28
|
description:
|
|
29
|
-
'Comma-separated features
|
|
30
|
-
'Ignored with --all or --remove-agents',
|
|
29
|
+
'Comma-separated features: agents (agent docs), theme (writes theme.template.ts), template (prints the page-building commands; writes no file). ' +
|
|
30
|
+
'An unknown feature exits 1 with ERR_UNKNOWN_FEATURE. Ignored with --all or --remove-agents',
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
flag: '--all',
|
|
34
34
|
param: 'options.all',
|
|
35
|
-
description:
|
|
35
|
+
description:
|
|
36
|
+
'Install all features (agents, theme, template); overrides --features. Prints their guidance instead of the getting-started steps',
|
|
36
37
|
},
|
|
37
38
|
{
|
|
38
39
|
flag: '--remove-agents',
|
|
@@ -47,7 +48,9 @@ export const doc = {
|
|
|
47
48
|
param: 'options.agent',
|
|
48
49
|
choices: ['claude', 'cursor', 'codex', 'hermes', 'muse', 'all'],
|
|
49
50
|
description:
|
|
50
|
-
'Target AI tool for agent docs: claude
|
|
51
|
+
'Target AI tool for agent docs: claude (CLAUDE.md or .claude/CLAUDE.md, else creates .claude/CLAUDE.md), cursor (.cursorrules if present, else AGENTS.md), ' +
|
|
52
|
+
'codex and muse (AGENTS.md), hermes (.hermes.md or HERMES.md if present, else AGENTS.md), all (every existing agent doc, else AGENTS.md and .claude/CLAUDE.md). ' +
|
|
53
|
+
'An unknown tool exits 1 with ERR_UNKNOWN_AGENT. ' +
|
|
51
54
|
'Used only when agent docs are installed (the default, --all, or --features agents); --agent-docs-path takes precedence',
|
|
52
55
|
},
|
|
53
56
|
{
|
|
@@ -8,7 +8,7 @@ export const doc = {
|
|
|
8
8
|
namespace: 'cli/commands',
|
|
9
9
|
summary: 'Add one working contribution to an integration package',
|
|
10
10
|
description:
|
|
11
|
-
'Writes the
|
|
11
|
+
'Writes the files one contribution needs, creates the integration manifest on first use, and declares a root only after a contribution the CLI can read exists behind it. A component or template import also needs an `exports` entry: add writes one only when package.json already has an `exports` map, so start a new package with `"exports": {}`. See {@link generic:quick-start}.',
|
|
12
12
|
fn: 'integrationAdd',
|
|
13
13
|
args: [
|
|
14
14
|
{
|
|
@@ -60,10 +60,14 @@ export const doc = {
|
|
|
60
60
|
flag: '--to <version>',
|
|
61
61
|
param: 'options.to',
|
|
62
62
|
description:
|
|
63
|
-
'Exact semver the
|
|
63
|
+
'Exact semver of the @astryxdesign/core version whose upgrade runs the codemod (e.g. 0.7.0); required for codemod and only valid there',
|
|
64
64
|
},
|
|
65
65
|
],
|
|
66
66
|
examples: [
|
|
67
|
+
{
|
|
68
|
+
label: 'Preview',
|
|
69
|
+
cli: 'astryx integration add component AcmeWidget --dry-run --json',
|
|
70
|
+
},
|
|
67
71
|
{
|
|
68
72
|
label: 'Add a component',
|
|
69
73
|
cli: 'astryx integration add component AcmeWidget',
|
|
@@ -71,7 +75,7 @@ export const doc = {
|
|
|
71
75
|
{label: 'Add a doc topic', cli: 'astryx integration add doc deploying'},
|
|
72
76
|
{
|
|
73
77
|
label: 'Add a page template',
|
|
74
|
-
cli: 'astryx integration add template dashboard',
|
|
78
|
+
cli: 'astryx integration add template acme-dashboard',
|
|
75
79
|
},
|
|
76
80
|
{
|
|
77
81
|
label: 'Add a block template',
|
|
@@ -87,7 +91,7 @@ export const doc = {
|
|
|
87
91
|
},
|
|
88
92
|
{
|
|
89
93
|
label: 'Add a guide to the package\'s own docs section',
|
|
90
|
-
cli: 'astryx integration add doc
|
|
94
|
+
cli: 'astryx integration add doc releasing --parent acme',
|
|
91
95
|
},
|
|
92
96
|
{
|
|
93
97
|
label: 'Add a codemod',
|
|
@@ -98,10 +102,6 @@ export const doc = {
|
|
|
98
102
|
cli: "astryx integration add agent-doc 'Run acme verify before finishing.'",
|
|
99
103
|
},
|
|
100
104
|
{label: 'Add a source theme', cli: 'astryx integration add theme ocean'},
|
|
101
|
-
{
|
|
102
|
-
label: 'Preview',
|
|
103
|
-
cli: 'astryx integration add component AcmeWidget --dry-run --json',
|
|
104
|
-
},
|
|
105
105
|
],
|
|
106
106
|
exitCodes: [
|
|
107
107
|
{code: 0, when: 'the contribution is written or the dry run succeeds'},
|
|
@@ -110,5 +110,5 @@ export const doc = {
|
|
|
110
110
|
when: 'the kind, name, options, package, or target files are invalid or conflict',
|
|
111
111
|
},
|
|
112
112
|
],
|
|
113
|
-
related: ['integration
|
|
113
|
+
related: ['integration verify', 'doctor integration validate', 'theme add'],
|
|
114
114
|
};
|
|
@@ -127,10 +127,7 @@ describe('integration authoring CLI', () => {
|
|
|
127
127
|
);
|
|
128
128
|
expect(added.status).toBe(0);
|
|
129
129
|
|
|
130
|
-
const checked = await runCli(
|
|
131
|
-
['integration', 'pack', '--check', '--json'],
|
|
132
|
-
tmpDir,
|
|
133
|
-
);
|
|
130
|
+
const checked = await runCli(['integration', 'verify', '--json'], tmpDir);
|
|
134
131
|
// Without an exports map, the extensionless import cannot resolve —
|
|
135
132
|
// pack-check must fail, not false-green.
|
|
136
133
|
expect(checked.status).not.toBe(0);
|
|
@@ -150,13 +147,67 @@ describe('integration authoring CLI', () => {
|
|
|
150
147
|
);
|
|
151
148
|
});
|
|
152
149
|
|
|
153
|
-
it('
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
150
|
+
it('keeps `integration pack --check` as a deprecated alias of `integration verify`', async () => {
|
|
151
|
+
// The old spelling runs the same check: the same JSON, the same exit code.
|
|
152
|
+
const verify = await runCli(['integration', 'verify', '--json'], tmpDir);
|
|
153
|
+
const old = await runCli(
|
|
154
|
+
['integration', 'pack', '--check', '--json'],
|
|
155
|
+
tmpDir,
|
|
156
|
+
);
|
|
157
|
+
expect(old.status).toBe(verify.status);
|
|
158
|
+
const verifyEnvelope = parseEnvelope(verify.stdout);
|
|
159
|
+
const oldEnvelope = parseEnvelope(old.stdout);
|
|
160
|
+
expect(oldEnvelope.type).toBe('integration.pack-check');
|
|
161
|
+
expect(oldEnvelope.type).toBe(verifyEnvelope.type);
|
|
162
|
+
expect(oldEnvelope.data.packable).toBe(verifyEnvelope.data.packable);
|
|
163
|
+
expect(oldEnvelope.data.issues).toEqual(verifyEnvelope.data.issues);
|
|
164
|
+
// The global flag may come first, as agents usually write it.
|
|
165
|
+
const lead = await runCli(
|
|
166
|
+
['--json', 'integration', 'pack', '--check'],
|
|
167
|
+
tmpDir,
|
|
168
|
+
);
|
|
169
|
+
expect(parseEnvelope(lead.stdout).type).toBe('integration.pack-check');
|
|
170
|
+
// In text, it says to use the new name, on stderr, so stdout is the same.
|
|
171
|
+
const text = await runCli(['integration', 'pack', '--check'], tmpDir);
|
|
172
|
+
const verifyText = await runCli(['integration', 'verify'], tmpDir);
|
|
173
|
+
expect(text.status).toBe(verifyText.status);
|
|
174
|
+
expect(text.stdout).toBe(verifyText.stdout);
|
|
175
|
+
expect(text.stderr).toContain('`integration pack --check` is deprecated');
|
|
176
|
+
expect(text.stderr).toContain('astryx integration verify');
|
|
177
|
+
// Without --check it fails, as it did, and names both spellings.
|
|
178
|
+
const bare = await runCli(['integration', 'pack'], tmpDir);
|
|
179
|
+
expect(bare.status).not.toBe(0);
|
|
180
|
+
expect(bare.stderr).toContain('--check');
|
|
181
|
+
expect(bare.stderr).toContain('astryx integration verify');
|
|
182
|
+
// Help lists it, marked deprecated: nothing is hidden.
|
|
183
|
+
const help = await runCli(['integration', '--help'], tmpDir);
|
|
184
|
+
expect(help.stdout).toMatch(
|
|
185
|
+
/pack .*Deprecated: the old name of `integration verify`/,
|
|
186
|
+
);
|
|
187
|
+
// `verify` itself takes no --check.
|
|
188
|
+
const flag = await runCli(['integration', 'verify', '--check'], tmpDir);
|
|
189
|
+
expect(flag.status).not.toBe(0);
|
|
190
|
+
expect(flag.stderr).toContain("unknown option '--check'");
|
|
191
|
+
// An unknown subcommand with a flag names the subcommand, in text and JSON.
|
|
192
|
+
const unknown = await runCli(['integration', 'bogus', '--check'], tmpDir);
|
|
193
|
+
expect(unknown.status).not.toBe(0);
|
|
194
|
+
expect(unknown.stderr).toContain("unknown subcommand 'integration bogus'");
|
|
195
|
+
expect(unknown.stderr).toMatch(/verify\s+\(available subcommand\)/);
|
|
196
|
+
const unknownJson = await runCli(
|
|
197
|
+
['integration', 'bogus', '--check', '--json'],
|
|
198
|
+
tmpDir,
|
|
199
|
+
);
|
|
200
|
+
expect(parseEnvelope(unknownJson.stdout)).toMatchObject({
|
|
201
|
+
code: 'ERR_UNKNOWN_SUBCOMMAND',
|
|
202
|
+
error: "unknown subcommand 'integration bogus'",
|
|
203
|
+
suggestions: expect.arrayContaining([
|
|
204
|
+
expect.objectContaining({name: 'verify'}),
|
|
205
|
+
]),
|
|
159
206
|
});
|
|
207
|
+
// A flag alone is an unknown option, not an unknown subcommand.
|
|
208
|
+
const flagOnly = await runCli(['integration', '--bogus'], tmpDir);
|
|
209
|
+
expect(flagOnly.status).not.toBe(0);
|
|
210
|
+
expect(flagOnly.stderr).toContain("unknown option '--bogus'");
|
|
160
211
|
});
|
|
161
212
|
|
|
162
213
|
it('refuses kind-specific options on another kind', async () => {
|
|
@@ -6,22 +6,18 @@ export const doc = {
|
|
|
6
6
|
name: 'integration pack',
|
|
7
7
|
displayName: 'astryx integration pack',
|
|
8
8
|
namespace: 'cli/commands',
|
|
9
|
-
summary: '
|
|
9
|
+
summary: 'Deprecated: the old name of `integration verify`',
|
|
10
10
|
description:
|
|
11
|
-
'
|
|
11
|
+
'`astryx integration pack --check` is the name this check had before {@link command:integration verify}. It still runs the same check, with the same output, JSON, and exit codes, and prints a note that names `integration verify`. It will be removed in a later release.',
|
|
12
12
|
fn: 'integrationPackCheck',
|
|
13
13
|
options: [
|
|
14
14
|
{
|
|
15
15
|
flag: '--check',
|
|
16
|
-
description: 'Run the
|
|
16
|
+
description: 'Run the check. Required, as before.',
|
|
17
17
|
},
|
|
18
18
|
],
|
|
19
19
|
examples: [
|
|
20
|
-
{label: '
|
|
21
|
-
{
|
|
22
|
-
label: 'Machine-readable result',
|
|
23
|
-
cli: 'astryx integration pack --check --json',
|
|
24
|
-
},
|
|
20
|
+
{label: 'The old spelling', cli: 'astryx integration pack --check'},
|
|
25
21
|
],
|
|
26
22
|
exitCodes: [
|
|
27
23
|
{code: 0, when: 'the packed package exposes the same valid contributions'},
|
|
@@ -30,5 +26,5 @@ export const doc = {
|
|
|
30
26
|
when: '--check is omitted or the tarball is incomplete or invalid',
|
|
31
27
|
},
|
|
32
28
|
],
|
|
33
|
-
related: ['integration
|
|
29
|
+
related: ['integration verify'],
|
|
34
30
|
};
|
|
@@ -214,7 +214,7 @@ export const oceanTheme = defineTheme({
|
|
|
214
214
|
]);
|
|
215
215
|
|
|
216
216
|
const checked = await runCli(
|
|
217
|
-
['integration', '
|
|
217
|
+
['integration', 'verify', '--json'],
|
|
218
218
|
providerDir,
|
|
219
219
|
);
|
|
220
220
|
expect(checked.status, checked.stderr).toBe(0);
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/** @type {import('@astryxdesign/cli/authoring').CommandDoc} */
|
|
4
|
+
export const doc = {
|
|
5
|
+
type: 'command',
|
|
6
|
+
name: 'integration verify',
|
|
7
|
+
displayName: 'astryx integration verify',
|
|
8
|
+
namespace: 'cli/commands',
|
|
9
|
+
summary: 'Check the package the way npm will publish it, before you publish',
|
|
10
|
+
description:
|
|
11
|
+
'Packs the package with npm, unpacks the tarball into a temporary app without installing its dependencies, and checks that the app sees the same components, templates, themes, docs, and codemods as the package, that every public import resolves, and that the package declares a CLI new enough to read it. It publishes nothing and leaves no tarball behind. It runs the package\'s own pack lifecycle scripts, as `npm pack` does.',
|
|
12
|
+
fn: 'integrationPackCheck',
|
|
13
|
+
examples: [
|
|
14
|
+
{label: 'Check before publishing', cli: 'astryx integration verify'},
|
|
15
|
+
{label: 'Machine-readable result', cli: 'astryx integration verify --json'},
|
|
16
|
+
],
|
|
17
|
+
exitCodes: [
|
|
18
|
+
{code: 0, when: 'the packed package exposes the same valid contributions'},
|
|
19
|
+
{code: 1, when: 'the tarball is incomplete or invalid'},
|
|
20
|
+
],
|
|
21
|
+
related: ['integration add', 'doctor integration validate'],
|
|
22
|
+
};
|
|
@@ -8,16 +8,16 @@ export const doc = {
|
|
|
8
8
|
namespace: 'cli/commands',
|
|
9
9
|
summary: 'Author and verify an Astryx integration package',
|
|
10
10
|
description:
|
|
11
|
-
'Add contributions
|
|
12
|
-
subcommands: ['add', 'pack'],
|
|
11
|
+
'Add contributions to your package, then check the packed package the way an app receives it. The guides start at {@link namespace:integrations}.',
|
|
12
|
+
subcommands: ['add', 'verify', 'pack'],
|
|
13
13
|
examples: [
|
|
14
14
|
{
|
|
15
15
|
label: 'Add a component',
|
|
16
16
|
cli: 'astryx integration add component AcmeWidget',
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
label: 'Check the package
|
|
20
|
-
cli: 'astryx integration
|
|
19
|
+
label: 'Check the package before publishing',
|
|
20
|
+
cli: 'astryx integration verify',
|
|
21
21
|
},
|
|
22
22
|
],
|
|
23
23
|
exitCodes: [
|
|
@@ -12,6 +12,7 @@ import {cliError} from '../lib/cli-error.mjs';
|
|
|
12
12
|
import {defineCommand} from '../lib/define-command.mjs';
|
|
13
13
|
import {doc as integrationGroup} from './integration.doc.mjs';
|
|
14
14
|
import {doc as integrationAddCommand} from './integration-add.doc.mjs';
|
|
15
|
+
import {doc as integrationVerifyCommand} from './integration-verify.doc.mjs';
|
|
15
16
|
import {doc as integrationPackCommand} from './integration-pack.doc.mjs';
|
|
16
17
|
import {doc as integrationAddFn} from '../../../api/integration/integrationAdd.doc.mjs';
|
|
17
18
|
import {doc as integrationPackCheckFn} from '../../../api/integration/integrationPackCheck.doc.mjs';
|
|
@@ -24,8 +25,16 @@ import {doc as integrationPackCheckFn} from '../../../api/integration/integratio
|
|
|
24
25
|
*/
|
|
25
26
|
function showGroupOrUnknown(command, label, options, invoked) {
|
|
26
27
|
const extras = invoked?.args ?? [];
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
// allowUnknownOption keeps an unknown flag among the args: a word there is
|
|
29
|
+
// an unknown subcommand, and a flag alone is an unknown option.
|
|
30
|
+
const word = extras.find(arg => !String(arg).startsWith('-'));
|
|
31
|
+
if (word == null && extras.length > 0) {
|
|
32
|
+
return cliError(`unknown option '${String(extras[0])}'`, {
|
|
33
|
+
code: ERROR_CODES.ERR_INVALID_OPTION,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
if (word != null) {
|
|
37
|
+
return cliError(`unknown subcommand '${label} ${String(word)}'`, {
|
|
29
38
|
suggestions: (command.commands ?? []).map(child => ({
|
|
30
39
|
name: child.name(),
|
|
31
40
|
reason: 'available subcommand',
|
|
@@ -37,6 +46,48 @@ function showGroupOrUnknown(command, label, options, invoked) {
|
|
|
37
46
|
return NO_RESULT_SET;
|
|
38
47
|
}
|
|
39
48
|
|
|
49
|
+
/**
|
|
50
|
+
* Run `integration verify` and print its result, as text or JSON.
|
|
51
|
+
* @param {import('commander').Command} program
|
|
52
|
+
*/
|
|
53
|
+
async function verifyPackage(program) {
|
|
54
|
+
const result = await integrationPackCheck({cwd: process.cwd()});
|
|
55
|
+
if (program.opts().json) {
|
|
56
|
+
jsonOut(result);
|
|
57
|
+
} else {
|
|
58
|
+
const {name, version, packable, tarball, inventory, issues} = result.data;
|
|
59
|
+
const identity = [name, version].filter(Boolean).join('@');
|
|
60
|
+
const blocks = [
|
|
61
|
+
section(
|
|
62
|
+
packable
|
|
63
|
+
? 'Integration package ready'
|
|
64
|
+
: 'Integration package check failed',
|
|
65
|
+
),
|
|
66
|
+
text(`${packable ? '[ok]' : '[fail]'} ${identity || 'local package'}`),
|
|
67
|
+
];
|
|
68
|
+
if (tarball != null) {
|
|
69
|
+
blocks.push(
|
|
70
|
+
text(
|
|
71
|
+
`${tarball.fileCount} packed files; ${inventory.packedFiles}/${inventory.expectedFiles} required files present.`,
|
|
72
|
+
),
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
if (issues.length > 0) {
|
|
76
|
+
blocks.push(
|
|
77
|
+
list(
|
|
78
|
+
issues.map(
|
|
79
|
+
issue =>
|
|
80
|
+
`[${issue.severity === 'error' ? 'fail' : 'warn'}] ${issue.message}`,
|
|
81
|
+
),
|
|
82
|
+
),
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
emit(...blocks);
|
|
86
|
+
}
|
|
87
|
+
if (!result.data.packable) process.exitCode = 1;
|
|
88
|
+
return NO_RESULT_SET;
|
|
89
|
+
}
|
|
90
|
+
|
|
40
91
|
/** @param {import('commander').Command} program */
|
|
41
92
|
export function registerIntegration(program) {
|
|
42
93
|
/** @type {import('commander').Command} */
|
|
@@ -45,6 +96,10 @@ export function registerIntegration(program) {
|
|
|
45
96
|
action: (options, command) =>
|
|
46
97
|
showGroupOrUnknown(integration, 'integration', options, command),
|
|
47
98
|
});
|
|
99
|
+
// An unknown subcommand given with a flag reports the unknown subcommand
|
|
100
|
+
// and lists the ones the group has, not the unknown option. Each subcommand
|
|
101
|
+
// still parses its own options.
|
|
102
|
+
integration.allowUnknownOption(true);
|
|
48
103
|
|
|
49
104
|
defineCommand(integration, integrationAddCommand, {
|
|
50
105
|
fn: integrationAddFn,
|
|
@@ -102,53 +157,29 @@ export function registerIntegration(program) {
|
|
|
102
157
|
},
|
|
103
158
|
});
|
|
104
159
|
|
|
160
|
+
defineCommand(integration, integrationVerifyCommand, {
|
|
161
|
+
fn: integrationPackCheckFn,
|
|
162
|
+
action: async () => verifyPackage(program),
|
|
163
|
+
});
|
|
164
|
+
// The name this check had before `integration verify`. It stays as a
|
|
165
|
+
// deprecated alias, listed as one in help, so scripts that call it keep
|
|
166
|
+
// working; it runs the same check with the same output and exit codes.
|
|
105
167
|
defineCommand(integration, integrationPackCommand, {
|
|
106
168
|
fn: integrationPackCheckFn,
|
|
107
169
|
action: async options => {
|
|
108
170
|
if (!options.check) {
|
|
109
|
-
return cliError(
|
|
110
|
-
|
|
111
|
-
|
|
171
|
+
return cliError(
|
|
172
|
+
'Pass --check to verify the integration tarball, or run `astryx integration verify`.',
|
|
173
|
+
{code: ERROR_CODES.ERR_INVALID_ARGUMENT},
|
|
174
|
+
);
|
|
112
175
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const {name, version, packable, tarball, inventory, issues} =
|
|
119
|
-
result.data;
|
|
120
|
-
const identity = [name, version].filter(Boolean).join('@');
|
|
121
|
-
const blocks = [
|
|
122
|
-
section(
|
|
123
|
-
packable
|
|
124
|
-
? 'Integration package ready'
|
|
125
|
-
: 'Integration package check failed',
|
|
126
|
-
),
|
|
127
|
-
text(
|
|
128
|
-
`${packable ? '[ok]' : '[fail]'} ${identity || 'local package'}`,
|
|
129
|
-
),
|
|
130
|
-
];
|
|
131
|
-
if (tarball != null) {
|
|
132
|
-
blocks.push(
|
|
133
|
-
text(
|
|
134
|
-
`${tarball.fileCount} packed files; ${inventory.packedFiles}/${inventory.expectedFiles} required files present.`,
|
|
135
|
-
),
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
if (issues.length > 0) {
|
|
139
|
-
blocks.push(
|
|
140
|
-
list(
|
|
141
|
-
issues.map(
|
|
142
|
-
issue =>
|
|
143
|
-
`[${issue.severity === 'error' ? 'fail' : 'warn'}] ${issue.message}`,
|
|
144
|
-
),
|
|
145
|
-
),
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
emit(...blocks);
|
|
176
|
+
// stderr, and only in text: JSON callers get the same envelope as verify.
|
|
177
|
+
if (!program.opts().json) {
|
|
178
|
+
console.error(
|
|
179
|
+
'Note: `integration pack --check` is deprecated. Run `astryx integration verify`: it runs the same check.',
|
|
180
|
+
);
|
|
149
181
|
}
|
|
150
|
-
|
|
151
|
-
return NO_RESULT_SET;
|
|
182
|
+
return verifyPackage(program);
|
|
152
183
|
},
|
|
153
184
|
});
|
|
154
185
|
}
|
|
@@ -20,7 +20,7 @@ export const doc = {
|
|
|
20
20
|
'tooling to introspect. Intended to be run with --json.',
|
|
21
21
|
examples: [
|
|
22
22
|
{label: 'Full manifest', cli: 'astryx manifest --json'},
|
|
23
|
-
{label: '
|
|
23
|
+
{label: 'The same manifest, under data.manifest (type "help")', cli: 'astryx --json'},
|
|
24
24
|
],
|
|
25
25
|
exitCodes: [
|
|
26
26
|
{code: 0, when: 'success'},
|
|
@@ -16,9 +16,12 @@ export const doc = {
|
|
|
16
16
|
summary: 'Search components, hooks, docs, and templates in one ranked list',
|
|
17
17
|
description:
|
|
18
18
|
'Terminal front-end to search(): prints one ranked, greppable list across ' +
|
|
19
|
-
'every content domain, each row carrying a follow-up command to act on it.'
|
|
19
|
+
'every content domain, each row carrying a follow-up command to act on it. ' +
|
|
20
|
+
'Outside an app, where @astryxdesign/core is not installed, it searches the docs.',
|
|
20
21
|
fn: 'search',
|
|
21
|
-
|
|
22
|
+
// Every word after `search` is the query: `astryx search dark mode` searches
|
|
23
|
+
// for "dark mode", with no quotes needed.
|
|
24
|
+
args: [{name: 'query', param: 'query', required: true, variadic: true}],
|
|
22
25
|
options: [
|
|
23
26
|
{
|
|
24
27
|
flag: '--type <domain>',
|
|
@@ -38,6 +41,10 @@ export const doc = {
|
|
|
38
41
|
],
|
|
39
42
|
examples: [
|
|
40
43
|
{label: 'Ranked results', cli: 'astryx search button'},
|
|
44
|
+
{
|
|
45
|
+
label: 'Several words, no quotes',
|
|
46
|
+
cli: 'astryx search dark mode --type doc',
|
|
47
|
+
},
|
|
41
48
|
{
|
|
42
49
|
label: 'Filter + JSON',
|
|
43
50
|
cli: 'astryx search "data table" --type template --json',
|
|
@@ -47,7 +54,7 @@ export const doc = {
|
|
|
47
54
|
{code: 0, when: 'success (including zero matches)'},
|
|
48
55
|
{
|
|
49
56
|
code: 1,
|
|
50
|
-
when: 'invalid --type, a --limit that is not a positive integer, or @astryxdesign/core cannot be found',
|
|
57
|
+
when: 'invalid --type, a --limit that is not a positive integer, or --type component, hook, or template where @astryxdesign/core cannot be found',
|
|
51
58
|
},
|
|
52
59
|
],
|
|
53
60
|
related: ['component', 'hook', 'docs', 'template', 'build'],
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* Usage:
|
|
16
16
|
* astryx search button Ranked results across all domains
|
|
17
|
+
* astryx search dark mode Every word is part of the query
|
|
17
18
|
* astryx search modal --type component Filter to a single domain
|
|
18
19
|
* astryx search forms --limit 5 Cap the result count
|
|
19
20
|
* astryx search button --verbose Also print score / reason
|
|
@@ -31,6 +32,7 @@ import {cliError} from '../lib/cli-error.mjs';
|
|
|
31
32
|
import {defineCommand} from '../lib/define-command.mjs';
|
|
32
33
|
import {search as searchApi} from '../../../api/search/search.mjs';
|
|
33
34
|
import {Project} from '../../../foundation/config/project.mjs';
|
|
35
|
+
import {findCoreDir} from '../../../foundation/fs/paths.mjs';
|
|
34
36
|
import {warnOnIntegrationIssues} from '../../../foundation/integrations/integration-warnings.mjs';
|
|
35
37
|
import {doc as searchCommand} from './search.doc.mjs';
|
|
36
38
|
import {doc as searchFn} from '../../../api/search/search.doc.mjs';
|
|
@@ -42,10 +44,13 @@ export function registerSearch(program) {
|
|
|
42
44
|
defineCommand(program, searchCommand, {
|
|
43
45
|
fn: searchFn,
|
|
44
46
|
action: async (
|
|
45
|
-
/** @type {string} */
|
|
47
|
+
/** @type {string[] | string} */ words,
|
|
46
48
|
/** @type {{type?: import('../../../api/search/search.type.mjs').SearchDomain, limit?: string, verbose?: boolean}} */ options,
|
|
47
49
|
) => {
|
|
48
50
|
const json = program.opts().json || false;
|
|
51
|
+
// The query is variadic: `astryx search dark mode` is one query, "dark
|
|
52
|
+
// mode". Taking only the first word dropped the rest without a word.
|
|
53
|
+
const query = Array.isArray(words) ? words.join(' ') : words;
|
|
49
54
|
|
|
50
55
|
try {
|
|
51
56
|
const project = await Project.load(process.cwd());
|
|
@@ -99,12 +104,25 @@ export function registerSearch(program) {
|
|
|
99
104
|
// ── Text output ──────────────────────────────────────────────
|
|
100
105
|
const run = getCliInvocation();
|
|
101
106
|
const {query: q, matchCount, results} = result.data;
|
|
107
|
+
// Outside an app an open search covers the docs alone. Say so, so a
|
|
108
|
+
// docs-only list does not read as "Astryx has no such component".
|
|
109
|
+
const note =
|
|
110
|
+
!options.type && !findCoreDir(process.cwd())
|
|
111
|
+
? [
|
|
112
|
+
text(
|
|
113
|
+
'@astryxdesign/core is not installed here, so only the docs were searched.',
|
|
114
|
+
),
|
|
115
|
+
]
|
|
116
|
+
: [];
|
|
102
117
|
|
|
103
118
|
// No matches is a valid, successful outcome — clean message, exit 0.
|
|
104
119
|
if (results.length === 0) {
|
|
105
120
|
emit(
|
|
106
121
|
text(`No results for "${q}".`),
|
|
107
|
-
|
|
122
|
+
...note,
|
|
123
|
+
text(
|
|
124
|
+
`Try a broader term, or browse: ${run} ${note.length > 0 ? 'docs' : 'component --list'}`,
|
|
125
|
+
),
|
|
108
126
|
);
|
|
109
127
|
return answered;
|
|
110
128
|
}
|
|
@@ -155,6 +173,7 @@ export function registerSearch(program) {
|
|
|
155
173
|
fields,
|
|
156
174
|
format: {command: formatCliCommand, parent: formatCliCommand},
|
|
157
175
|
}),
|
|
176
|
+
...note,
|
|
158
177
|
);
|
|
159
178
|
return answered;
|
|
160
179
|
},
|
|
@@ -191,6 +191,18 @@ describe('search CLI — exit codes + JSON contract', () => {
|
|
|
191
191
|
expect(r.stdout).toContain('No results');
|
|
192
192
|
});
|
|
193
193
|
|
|
194
|
+
it('takes every word after `search` as one query', async () => {
|
|
195
|
+
// Commander took only the first word, so `search dark mode` searched for
|
|
196
|
+
// "dark" and dropped "mode" without a word.
|
|
197
|
+
const json = await runCli(['--json', 'search', 'dark', 'mode', '--type', 'doc'], REPO_ROOT);
|
|
198
|
+
expect(json.status).toBe(0);
|
|
199
|
+
const env = JSON.parse(json.stdout);
|
|
200
|
+
expect(env.data.query).toBe('dark mode');
|
|
201
|
+
expect(env.data.results[0]).toMatchObject({name: 'theme', section: 'light-dark-mode'});
|
|
202
|
+
const text = await runCli(['search', 'dark', 'mode', '--type', 'doc'], REPO_ROOT);
|
|
203
|
+
expect(text.stdout).toContain('Results for "dark mode"');
|
|
204
|
+
}, SCAN_TIMEOUT);
|
|
205
|
+
|
|
194
206
|
it('exits 1 for an invalid --type', async () => {
|
|
195
207
|
const r = await runCli(['search', 'x', '--type', 'bogus'], REPO_ROOT);
|
|
196
208
|
expect(r.status).toBe(1);
|
|
@@ -299,14 +311,19 @@ describe('search CLI — exit codes + JSON contract', () => {
|
|
|
299
311
|
expect(r.stdout).toContain('reason:');
|
|
300
312
|
});
|
|
301
313
|
|
|
302
|
-
it('
|
|
314
|
+
it('searches the docs when no @astryxdesign/core is reachable, and exits 1 for --type component', async () => {
|
|
303
315
|
const empty = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-search-cli-no-core-'));
|
|
304
316
|
try {
|
|
305
|
-
const
|
|
317
|
+
const open = await runCli(['--json', 'search', 'make', 'an', 'integration'], empty);
|
|
318
|
+
expect(open.status).toBe(0);
|
|
319
|
+
expect(JSON.parse(open.stdout).data.results[0]).toMatchObject({domain: 'doc'});
|
|
320
|
+
// The text says the search covered the docs alone.
|
|
321
|
+
const text = await runCli(['search', 'button'], empty);
|
|
322
|
+
expect(text.status).toBe(0);
|
|
323
|
+
expect(text.stdout).toContain('only the docs were searched');
|
|
324
|
+
const json = await runCli(['--json', 'search', 'button', '--type', 'component'], empty);
|
|
306
325
|
expect(json.status).toBe(1);
|
|
307
326
|
expect(JSON.parse(json.stdout)).toMatchObject({code: 'ERR_CORE_NOT_FOUND'});
|
|
308
|
-
const text = await runCli(['search', 'button'], empty);
|
|
309
|
-
expect(text.status).toBe(1);
|
|
310
327
|
} finally {
|
|
311
328
|
fs.rmSync(empty, {recursive: true, force: true});
|
|
312
329
|
}
|
|
@@ -46,7 +46,7 @@ export const doc = {
|
|
|
46
46
|
],
|
|
47
47
|
examples: [
|
|
48
48
|
{label: 'List swizzlable components', cli: 'astryx swizzle --list'},
|
|
49
|
-
{label: 'Eject a component', cli: 'astryx swizzle
|
|
49
|
+
{label: 'Eject a component', cli: 'astryx swizzle Button'},
|
|
50
50
|
],
|
|
51
51
|
exitCodes: [
|
|
52
52
|
{code: 0, when: 'success'},
|
|
@@ -14,7 +14,7 @@ export const doc = {
|
|
|
14
14
|
name: 'template',
|
|
15
15
|
displayName: 'astryx template',
|
|
16
16
|
namespace: 'cli/commands',
|
|
17
|
-
summary: '
|
|
17
|
+
summary: 'List, show, or scaffold page and block templates',
|
|
18
18
|
description:
|
|
19
19
|
'One entry point for the template family: with no name it lists the discovered ' +
|
|
20
20
|
'templates; with a name it shows the source or a layout skeleton, or scaffolds it ' +
|
|
@@ -372,9 +372,15 @@ const CASES = [
|
|
|
372
372
|
skipFieldChecks: true,
|
|
373
373
|
},
|
|
374
374
|
{
|
|
375
|
+
name: 'integration verify',
|
|
376
|
+
args: ['integration', 'verify'],
|
|
377
|
+
// Needs a packable project; pack itself may exit differently.
|
|
378
|
+
skipFieldChecks: true,
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
// The deprecated alias of `integration verify`.
|
|
375
382
|
name: 'integration pack',
|
|
376
383
|
args: ['integration', 'pack', '--check'],
|
|
377
|
-
// Needs a packable project; pack itself may exit differently.
|
|
378
384
|
skipFieldChecks: true,
|
|
379
385
|
},
|
|
380
386
|
// ── Layout command: remove these cases when the layout command is deleted ──
|
|
@@ -41,7 +41,7 @@ export const doc = {
|
|
|
41
41
|
examples: [
|
|
42
42
|
{label: 'Scaffold a theme', cli: 'astryx theme add matcha'},
|
|
43
43
|
{
|
|
44
|
-
label: '
|
|
44
|
+
label: 'Pick the owner when two packages ship the same slug',
|
|
45
45
|
cli: 'astryx theme add ocean --package @acme/themes',
|
|
46
46
|
},
|
|
47
47
|
],
|