@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
|
@@ -8,6 +8,7 @@ export const docs = {
|
|
|
8
8
|
category: 'guide',
|
|
9
9
|
description:
|
|
10
10
|
'How to set up AI coding tools to generate correct component code.',
|
|
11
|
+
keywords: ['claude', 'cursor', 'codex', 'copilot', 'agents', 'mcp'],
|
|
11
12
|
|
|
12
13
|
sections: [
|
|
13
14
|
{
|
|
@@ -24,7 +25,8 @@ export const docs = {
|
|
|
24
25
|
],
|
|
25
26
|
},
|
|
26
27
|
{
|
|
27
|
-
|
|
28
|
+
id: 'quick-start',
|
|
29
|
+
title: 'Set up agent docs',
|
|
28
30
|
content: [
|
|
29
31
|
{
|
|
30
32
|
type: 'prose',
|
|
@@ -38,7 +40,7 @@ export const docs = {
|
|
|
38
40
|
},
|
|
39
41
|
{
|
|
40
42
|
type: 'prose',
|
|
41
|
-
text: "That's it. The `init --features agents` command generates everything your AI needs (component index, behavioral rules, CLI reference, and package guidance from configured integrations) from the installed project. After a dependency bump, `astryx upgrade
|
|
43
|
+
text: "That's it. The `init --features agents` command generates everything your AI needs (component index, behavioral rules, CLI reference, and package guidance from configured integrations) from the installed project. After a dependency bump, `astryx upgrade --from <old version>` reports a stale block and adding `--apply` refreshes it.",
|
|
42
44
|
},
|
|
43
45
|
{
|
|
44
46
|
type: 'prose',
|
|
@@ -48,10 +50,12 @@ export const docs = {
|
|
|
48
50
|
type: 'code',
|
|
49
51
|
lang: 'bash',
|
|
50
52
|
label: 'Manual options',
|
|
51
|
-
code: `npx @astryxdesign/cli init --features agents --agent claude # .claude/CLAUDE.md
|
|
52
|
-
npx @astryxdesign/cli init --features agents --agent cursor # .cursorrules
|
|
53
|
+
code: `npx @astryxdesign/cli init --features agents --agent claude # CLAUDE.md if present, else .claude/CLAUDE.md
|
|
54
|
+
npx @astryxdesign/cli init --features agents --agent cursor # .cursorrules if present, else AGENTS.md
|
|
53
55
|
npx @astryxdesign/cli init --features agents --agent codex # AGENTS.md (Copilot, Codex, etc.)
|
|
54
|
-
npx @astryxdesign/cli init --features agents --agent
|
|
56
|
+
npx @astryxdesign/cli init --features agents --agent hermes # .hermes.md or HERMES.md if present, else AGENTS.md
|
|
57
|
+
npx @astryxdesign/cli init --features agents --agent muse # AGENTS.md (Muse)
|
|
58
|
+
npx @astryxdesign/cli init --features agents --agent all # every agent file present, else AGENTS.md and .claude/CLAUDE.md`,
|
|
55
59
|
},
|
|
56
60
|
],
|
|
57
61
|
},
|
|
@@ -82,14 +86,17 @@ npx @astryxdesign/cli init --features agents --agent muse # AGENTS.md (Muse
|
|
|
82
86
|
content: [
|
|
83
87
|
{
|
|
84
88
|
type: 'prose',
|
|
85
|
-
text: 'Cursor project rules
|
|
89
|
+
text: 'Cursor reads project rules from `.cursor/rules/`. To keep the Astryx context in a rule of its own, write it there. Give a path relative to the project root, such as `.cursor/rules/astryx.mdc`; an absolute path is refused.',
|
|
86
90
|
},
|
|
87
91
|
{
|
|
88
92
|
type: 'code',
|
|
89
93
|
lang: 'bash',
|
|
90
|
-
label: 'Install as a Cursor
|
|
91
|
-
code: `
|
|
92
|
-
|
|
94
|
+
label: 'Install as a Cursor project rule',
|
|
95
|
+
code: `npx @astryxdesign/cli init --features agents --agent-docs-path .cursor/rules/astryx.mdc`,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
type: 'prose',
|
|
99
|
+
text: 'Rerunning the same command rewrites only the Astryx block, so frontmatter you add above it (such as `alwaysApply: true`) stays.',
|
|
93
100
|
},
|
|
94
101
|
],
|
|
95
102
|
},
|
|
@@ -98,7 +105,7 @@ npx @astryxdesign/cli init --features agents --agent-docs-path ~/.cursor/rules/x
|
|
|
98
105
|
content: [
|
|
99
106
|
{
|
|
100
107
|
type: 'prose',
|
|
101
|
-
text: 'Paste this into your AI before writing any component code.
|
|
108
|
+
text: 'Paste this into your AI before writing any component code. If your AI can\'t answer these questions, it\'ll know to install the agent docs first.',
|
|
102
109
|
},
|
|
103
110
|
{
|
|
104
111
|
type: 'code',
|
|
@@ -107,7 +114,7 @@ npx @astryxdesign/cli init --features agents --agent-docs-path ~/.cursor/rules/x
|
|
|
107
114
|
code: `Before writing any Astryx code, check your knowledge:
|
|
108
115
|
|
|
109
116
|
1. What is the correct import path for Button?
|
|
110
|
-
2. How do you make
|
|
117
|
+
2. How do you make a Dialog non-dismissible?
|
|
111
118
|
3. What prop does Selector use for its items?
|
|
112
119
|
|
|
113
120
|
If you don't know all three, run \`npx @astryxdesign/cli init --features agents\` to generate agent docs, then read the generated file.`,
|
|
@@ -131,33 +138,34 @@ If you don't know all three, run \`npx @astryxdesign/cli init --features agents\
|
|
|
131
138
|
},
|
|
132
139
|
{
|
|
133
140
|
type: 'prose',
|
|
134
|
-
text: 'With this alias, agents
|
|
141
|
+
text: 'With this alias, agents run `npm run astryx -- component --list` instead of guessing the binary path. The `--` separator is standard npm convention for passing flags to scripts.',
|
|
135
142
|
},
|
|
136
143
|
{
|
|
137
144
|
type: 'code',
|
|
138
145
|
lang: 'bash',
|
|
139
146
|
label: 'Reliable CLI invocation',
|
|
140
|
-
code: `astryx component --list
|
|
141
|
-
astryx component Dialog --dense
|
|
142
|
-
astryx docs styling --
|
|
143
|
-
astryx docs tokens --dense`,
|
|
147
|
+
code: `npm run astryx -- component --list
|
|
148
|
+
npm run astryx -- component Dialog --dense
|
|
149
|
+
npm run astryx -- docs styling --full --detail brief
|
|
150
|
+
npm run astryx -- docs tokens --dense`,
|
|
144
151
|
},
|
|
145
152
|
],
|
|
146
153
|
},
|
|
147
154
|
{
|
|
148
|
-
|
|
155
|
+
id: 'the-dense-flag',
|
|
156
|
+
title: 'Shorter output: --detail and --dense',
|
|
149
157
|
content: [
|
|
150
158
|
{
|
|
151
159
|
type: 'prose',
|
|
152
|
-
text: '
|
|
160
|
+
text: 'For a shorter read, add `--detail brief` (one line per section) or `--detail compact`. `--dense` swaps in a shorter text where a doc ships one. Use them when pasting CLI output into a web-based AI tool like ChatGPT or Claude.',
|
|
153
161
|
},
|
|
154
162
|
{
|
|
155
163
|
type: 'code',
|
|
156
164
|
lang: 'bash',
|
|
157
|
-
label: '
|
|
158
|
-
code: `astryx
|
|
159
|
-
astryx
|
|
160
|
-
astryx docs
|
|
165
|
+
label: 'Short output for pasting into AI conversations',
|
|
166
|
+
code: `astryx docs styling --full --detail brief
|
|
167
|
+
astryx component Dialog --detail compact
|
|
168
|
+
astryx docs principles --dense`,
|
|
161
169
|
},
|
|
162
170
|
],
|
|
163
171
|
},
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import {useState} from 'react';
|
|
6
6
|
import {InternationalizationProvider} from '@astryxdesign/core/i18n';
|
|
7
|
-
import frFR from '@astryxdesign/core/locales/fr-FR.
|
|
7
|
+
import frFR from '@astryxdesign/core/locales/fr-FR.generated.js';
|
|
8
8
|
import {Stack} from '@astryxdesign/core/Layout';
|
|
9
9
|
import {
|
|
10
10
|
SegmentedControl,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
export const doc = {
|
|
11
11
|
type: 'schema',
|
|
12
12
|
name: 'config',
|
|
13
|
-
displayName: '
|
|
13
|
+
displayName: 'astryx.config',
|
|
14
14
|
namespace: 'authoring',
|
|
15
15
|
description:
|
|
16
16
|
'The optional astryx.config.* file at your project root. Declares which ' +
|
|
@@ -60,6 +60,14 @@ export const doc = {
|
|
|
60
60
|
example:
|
|
61
61
|
"{ audience: 'internal', async handle(report, {signal}) { return sendGap(report, {signal}); } }",
|
|
62
62
|
},
|
|
63
|
+
{
|
|
64
|
+
name: 'discover',
|
|
65
|
+
type: 'DiscoverSource',
|
|
66
|
+
description:
|
|
67
|
+
'Tell `astryx discover` which integrations this project could add: an async function that returns a catalog. An integration can provide one too, as a `discover` named export from its manifest. Discover calls every source, yours first, and one that fails never hides the others. Discover only reads; your package manager installs.',
|
|
68
|
+
example:
|
|
69
|
+
"async ({signal, package: name, version}) => fetchCatalog({signal, name, version})",
|
|
70
|
+
},
|
|
63
71
|
{
|
|
64
72
|
name: 'experimental',
|
|
65
73
|
type: '{ xle?: { components?: Record<string, XleComponent> } }',
|
|
@@ -30,6 +30,7 @@ export type XleComponent = import("./type.js").XleComponent;
|
|
|
30
30
|
export type DebugConfig = import("./type.js").DebugConfig;
|
|
31
31
|
export type DebugEventHandler = import("../debug/type.js").DebugEventHandler;
|
|
32
32
|
export type GapReportHandler = import("../gap-report/type.js").GapReportHandler;
|
|
33
|
+
export type DiscoverSource = import("../discover/type.js").DiscoverSource;
|
|
33
34
|
import { z } from 'zod';
|
|
34
35
|
declare const configSchema: z.ZodObject<{
|
|
35
36
|
integrations: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
@@ -48,6 +49,7 @@ declare const configSchema: z.ZodObject<{
|
|
|
48
49
|
}, z.core.$strict>>;
|
|
49
50
|
debug: z.ZodOptional<z.ZodType<import("../debug/type.js").DebugEventHandler, any, z.core.$ZodTypeInternals<import("../debug/type.js").DebugEventHandler, any>>>;
|
|
50
51
|
gapReport: z.ZodOptional<z.ZodType<import("../gap-report/type.js").GapReportHandler, any, z.core.$ZodTypeInternals<import("../gap-report/type.js").GapReportHandler, any>>>;
|
|
52
|
+
discover: z.ZodOptional<z.ZodType<import("../discover/type.js").DiscoverSource, any, z.core.$ZodTypeInternals<import("../discover/type.js").DiscoverSource, any>>>;
|
|
51
53
|
experimental: z.ZodOptional<z.ZodObject<{
|
|
52
54
|
xle: z.ZodOptional<z.ZodObject<{
|
|
53
55
|
components: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import {z} from 'zod';
|
|
13
13
|
import {formatZodError} from '../_shared/errors.mjs';
|
|
14
14
|
import {parseGapReportHandler} from '../gap-report/parse.mjs';
|
|
15
|
+
import {parseDiscoverSource} from '../discover/parse.mjs';
|
|
15
16
|
|
|
16
17
|
/** @typedef {import('./type.js').AstryxConfig} AstryxConfig */
|
|
17
18
|
/** @typedef {import('./type.js').PostCodemodHook} PostCodemodHook */
|
|
@@ -19,6 +20,7 @@ import {parseGapReportHandler} from '../gap-report/parse.mjs';
|
|
|
19
20
|
/** @typedef {import('./type.js').DebugConfig} DebugConfig */
|
|
20
21
|
/** @typedef {import('../debug/type.js').DebugEventHandler} DebugEventHandler */
|
|
21
22
|
/** @typedef {import('../gap-report/type.js').GapReportHandler} GapReportHandler */
|
|
23
|
+
/** @typedef {import('../discover/type.js').DiscoverSource} DiscoverSource */
|
|
22
24
|
|
|
23
25
|
// Typed `z.custom` so `z.infer` reproduces the real function type (not `unknown`).
|
|
24
26
|
const buildCommand = /** @type {z.ZodType<PostCodemodHook['buildCommand']>} */ (
|
|
@@ -66,6 +68,22 @@ const gapReportHandlerSchema = /** @type {z.ZodType<GapReportHandler>} */ (
|
|
|
66
68
|
)
|
|
67
69
|
);
|
|
68
70
|
|
|
71
|
+
// The same check an integration's `discover` named export passes. Typed
|
|
72
|
+
// z.custom preserves the public function type.
|
|
73
|
+
const discoverSourceSchema = /** @type {z.ZodType<DiscoverSource>} */ (
|
|
74
|
+
z.custom(
|
|
75
|
+
value => {
|
|
76
|
+
try {
|
|
77
|
+
parseDiscoverSource(value, 'discover');
|
|
78
|
+
return true;
|
|
79
|
+
} catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
{message: 'Expected a discover source function'},
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
|
|
69
87
|
const configSchema = z
|
|
70
88
|
.object({
|
|
71
89
|
integrations: z.array(z.string()).optional(),
|
|
@@ -76,6 +94,7 @@ const configSchema = z
|
|
|
76
94
|
.optional(),
|
|
77
95
|
debug: debugSchema.optional(),
|
|
78
96
|
gapReport: gapReportHandlerSchema.optional(),
|
|
97
|
+
discover: discoverSourceSchema.optional(),
|
|
79
98
|
experimental: z
|
|
80
99
|
.object({
|
|
81
100
|
xle: z
|
|
@@ -63,6 +63,14 @@ describe('parseConfig (load boundary)', () => {
|
|
|
63
63
|
).toEqual({audience: 'internal', handle});
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
+
it('accepts a discover source function and refuses anything else', () => {
|
|
67
|
+
const discover = async () => ({});
|
|
68
|
+
expect(parseConfig({discover}).discover).toBe(discover);
|
|
69
|
+
expect(reason({discover: 'https://example.com/catalog.json'})).toContain(
|
|
70
|
+
'discover',
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
66
74
|
it('rejects obsolete or extended gap-report handler shapes', () => {
|
|
67
75
|
expect(reason({gapReport: {command: './report.mjs'}})).toContain(
|
|
68
76
|
'gapReport',
|
package/authoring/config/type.ts
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
import type {DebugEventHandler} from '../debug/type.js';
|
|
13
13
|
import type {GapReportHandler} from '../gap-report/type.js';
|
|
14
|
+
import type {DiscoverSource} from '../discover/type.js';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* A command to run as part of a post-codemod hook. Returned by a hook's
|
|
@@ -96,6 +97,16 @@ export interface AstryxConfig {
|
|
|
96
97
|
debug?: DebugConfig;
|
|
97
98
|
/** Route gap reports through a project-owned handler. See {@link GapReportHandler}. */
|
|
98
99
|
gapReport?: GapReportHandler;
|
|
100
|
+
/**
|
|
101
|
+
* Tell `astryx discover` about integrations this project could add. See
|
|
102
|
+
* {@link DiscoverSource}.
|
|
103
|
+
*
|
|
104
|
+
* An integration can provide a source too, as a `discover` named export from
|
|
105
|
+
* its `astryx.integration.*` module. Discover calls every source: this one
|
|
106
|
+
* first, then each integration's in load order, and one that fails never
|
|
107
|
+
* hides the others.
|
|
108
|
+
*/
|
|
109
|
+
discover?: DiscoverSource;
|
|
99
110
|
/**
|
|
100
111
|
* EXPERIMENTAL — shape may change and is not part of the stable config
|
|
101
112
|
* contract. Provisional home for features still being proven out.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// @generated by scripts/sync-api-types.mjs from the JSDoc in authoring/**/*.mjs.
|
|
2
|
+
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @file SchemaDoc for DiscoverSource, the function `astryx discover` calls to
|
|
6
|
+
* learn which integrations a project could add.
|
|
7
|
+
* @input The DiscoverSource type and the catalog types beside it (`type.ts`),
|
|
8
|
+
* which `parse.mjs` validates.
|
|
9
|
+
* @output The `discover-source` section of `astryx docs authoring`.
|
|
10
|
+
* @position packages/cli/authoring/discover — schema documentation
|
|
11
|
+
*/
|
|
12
|
+
/** @type {import('@astryxdesign/cli/authoring').SchemaDoc} */
|
|
13
|
+
export const doc: import("@astryxdesign/cli/authoring").SchemaDoc;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file SchemaDoc for DiscoverSource, the function `astryx discover` calls to
|
|
5
|
+
* learn which integrations a project could add.
|
|
6
|
+
* @input The DiscoverSource type and the catalog types beside it (`type.ts`),
|
|
7
|
+
* which `parse.mjs` validates.
|
|
8
|
+
* @output The `discover-source` section of `astryx docs authoring`.
|
|
9
|
+
* @position packages/cli/authoring/discover — schema documentation
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/** @type {import('@astryxdesign/cli/authoring').SchemaDoc} */
|
|
13
|
+
export const doc = {
|
|
14
|
+
type: 'schema',
|
|
15
|
+
name: 'discover-source',
|
|
16
|
+
displayName: 'DiscoverSource',
|
|
17
|
+
namespace: 'authoring',
|
|
18
|
+
description:
|
|
19
|
+
'A source for `astryx discover`: an async function that returns a catalog of packages a project could add, their versions, and what each version adds. Set it as `discover` in astryx.config, or export it as `discover` from an integration manifest. Discover calls every source, the project one first, and one that throws, runs past 30 seconds, or returns an invalid catalog never hides the others; discover then uses the last good answer it saved for that source. Discover only reads: it prints the command that adds a package and never runs it.',
|
|
20
|
+
appliesTo:
|
|
21
|
+
'`discover` in astryx.config.*, or the `discover` named export of astryx.integration.*',
|
|
22
|
+
fields: [
|
|
23
|
+
{
|
|
24
|
+
name: 'context',
|
|
25
|
+
type: 'DiscoverSourceContext',
|
|
26
|
+
description: 'The one argument the source is called with.',
|
|
27
|
+
required: true,
|
|
28
|
+
fields: [
|
|
29
|
+
{
|
|
30
|
+
name: 'context.signal',
|
|
31
|
+
type: 'AbortSignal',
|
|
32
|
+
description: 'Aborted when the source runs past 30 seconds.',
|
|
33
|
+
required: true,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: 'context.package',
|
|
37
|
+
type: 'string',
|
|
38
|
+
description:
|
|
39
|
+
'Set when discover shows one package: return that package with every version.',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'context.version',
|
|
43
|
+
type: 'string',
|
|
44
|
+
description:
|
|
45
|
+
"With `package`: return that version's contributions. Without it, the latest release's.",
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'returns',
|
|
51
|
+
type: 'Promise<DiscoverCatalog>',
|
|
52
|
+
description:
|
|
53
|
+
'The catalog. Discover checks it, ignores fields and item kinds it does not know, and refuses any schemaVersion but 1.',
|
|
54
|
+
required: true,
|
|
55
|
+
fields: [
|
|
56
|
+
{
|
|
57
|
+
name: 'schemaVersion',
|
|
58
|
+
type: '1',
|
|
59
|
+
description: 'Version of the catalog shape.',
|
|
60
|
+
required: true,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'source',
|
|
64
|
+
type: '{name: string, generatedAt: string, complete: boolean}',
|
|
65
|
+
description:
|
|
66
|
+
'Who answered, when the data was produced (ISO 8601), and false when the source knows its list is partial.',
|
|
67
|
+
required: true,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'packages',
|
|
71
|
+
type: 'DiscoverPackage[]',
|
|
72
|
+
description:
|
|
73
|
+
'One entry per npm package. When two sources list the same package, the earlier source wins.',
|
|
74
|
+
required: true,
|
|
75
|
+
fields: [
|
|
76
|
+
{
|
|
77
|
+
name: 'packages[].package',
|
|
78
|
+
type: 'string',
|
|
79
|
+
description: 'The npm name.',
|
|
80
|
+
required: true,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'packages[].integration',
|
|
84
|
+
type: 'string',
|
|
85
|
+
description:
|
|
86
|
+
'Shared by every npm name that publishes the same integration. Discover lists an integration once.',
|
|
87
|
+
required: true,
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: 'packages[].aliases',
|
|
91
|
+
type: 'string[]',
|
|
92
|
+
description:
|
|
93
|
+
"The integration's other npm names. Discover never offers a package the project has under another name.",
|
|
94
|
+
required: true,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: 'packages[].description',
|
|
98
|
+
type: 'string',
|
|
99
|
+
description: 'One line, for the list and search.',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: 'packages[].latest',
|
|
103
|
+
type: 'string | null',
|
|
104
|
+
description: 'The latest release. Null when there are only prereleases.',
|
|
105
|
+
required: true,
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: 'packages[].versions',
|
|
109
|
+
type: 'DiscoverVersion[]',
|
|
110
|
+
description:
|
|
111
|
+
'Every version, newest first: `{version, publishedAt, prerelease, status}`, where status is `ok` or why the version could not be read.',
|
|
112
|
+
required: true,
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: 'packages[].contributions',
|
|
116
|
+
type: 'DiscoverContribution[]',
|
|
117
|
+
description:
|
|
118
|
+
"What the requested (else latest) version adds: `{kind, name, title?, summary?, keywords?}`, where kind is `component`, `template`, `doc`, `theme`, `codemod`, or `agent-doc` (a DiscoverKind) and name is the name the CLI uses for it.",
|
|
119
|
+
required: true,
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
examples: [
|
|
127
|
+
{
|
|
128
|
+
label: 'A project source in astryx.config',
|
|
129
|
+
code:
|
|
130
|
+
'export default {\n' +
|
|
131
|
+
' async discover({signal, package: name, version}) {\n' +
|
|
132
|
+
' const res = await fetch(catalogUrl(name, version), {signal});\n' +
|
|
133
|
+
' return res.json();\n' +
|
|
134
|
+
' },\n' +
|
|
135
|
+
'};',
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// @generated by scripts/sync-api-types.mjs from the JSDoc in authoring/**/*.mjs.
|
|
2
|
+
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Check a catalog a discover source returned. Throws an Error naming the first
|
|
6
|
+
* problem. Items of a kind this CLI does not know are dropped, and versions are
|
|
7
|
+
* put newest first whatever order the source used.
|
|
8
|
+
*
|
|
9
|
+
* @param {unknown} value
|
|
10
|
+
* @param {string} [label]
|
|
11
|
+
* @returns {import('./type.js').DiscoverCatalog}
|
|
12
|
+
*/
|
|
13
|
+
export function parseDiscoverCatalog(value: unknown, label?: string): import("./type.js").DiscoverCatalog;
|
|
14
|
+
/**
|
|
15
|
+
* Check a discover source itself: an async function, like `debug`, that takes
|
|
16
|
+
* `{signal, package?, version?}` and resolves to a catalog.
|
|
17
|
+
*
|
|
18
|
+
* @param {unknown} value
|
|
19
|
+
* @param {string} label
|
|
20
|
+
* @returns {import('./type.js').DiscoverSource}
|
|
21
|
+
*/
|
|
22
|
+
export function parseDiscoverSource(value: unknown, label: string): import("./type.js").DiscoverSource;
|
|
23
|
+
/** Item kinds a catalog may list, in display order. */
|
|
24
|
+
export const DISCOVER_KINDS: readonly ["component", "template", "doc", "theme", "codemod", "agent-doc"];
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Runtime checks for discover sources and the catalogs they return.
|
|
5
|
+
*
|
|
6
|
+
* The catalog schema is deliberately not strict: a source may add fields this
|
|
7
|
+
* CLI does not know, and they are dropped. An unknown `schemaVersion` is
|
|
8
|
+
* refused, and an item of a kind this CLI does not know is skipped, so a newer
|
|
9
|
+
* source never breaks an older CLI.
|
|
10
|
+
*
|
|
11
|
+
* @position packages/cli/authoring/discover — parse + validate, no I/O.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import {z} from 'zod';
|
|
15
|
+
|
|
16
|
+
/** Item kinds a catalog may list, in display order. */
|
|
17
|
+
export const DISCOVER_KINDS = /** @type {const} */ ([
|
|
18
|
+
'component',
|
|
19
|
+
'template',
|
|
20
|
+
'doc',
|
|
21
|
+
'theme',
|
|
22
|
+
'codemod',
|
|
23
|
+
'agent-doc',
|
|
24
|
+
]);
|
|
25
|
+
|
|
26
|
+
const text = (/** @type {number} */ max) => z.string().min(1).max(max);
|
|
27
|
+
|
|
28
|
+
const contributionSchema = z.object({
|
|
29
|
+
kind: text(32),
|
|
30
|
+
name: text(512),
|
|
31
|
+
title: z.string().max(512).optional(),
|
|
32
|
+
summary: z.string().max(4096).optional(),
|
|
33
|
+
keywords: z.array(z.string().max(128)).max(64).optional(),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const versionSchema = z.object({
|
|
37
|
+
version: text(256),
|
|
38
|
+
publishedAt: z.string().max(64).nullable(),
|
|
39
|
+
prerelease: z.boolean(),
|
|
40
|
+
status: text(64),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const packageSchema = z.object({
|
|
44
|
+
package: text(214),
|
|
45
|
+
integration: text(214),
|
|
46
|
+
aliases: z.array(text(214)).max(64),
|
|
47
|
+
description: z.string().max(1024).optional(),
|
|
48
|
+
latest: text(256).nullable(),
|
|
49
|
+
versions: z.array(versionSchema).max(50_000),
|
|
50
|
+
contributions: z.array(contributionSchema).max(50_000),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const catalogSchema = z.object({
|
|
54
|
+
schemaVersion: z.literal(1),
|
|
55
|
+
source: z.object({
|
|
56
|
+
name: text(256),
|
|
57
|
+
generatedAt: text(64),
|
|
58
|
+
complete: z.boolean(),
|
|
59
|
+
}),
|
|
60
|
+
packages: z.array(packageSchema).max(20_000),
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Newest first by publish time. A version with no known publish time goes
|
|
65
|
+
* last, and ties fall back to the version number.
|
|
66
|
+
* @param {{version: string, publishedAt: string | null}} a
|
|
67
|
+
* @param {{version: string, publishedAt: string | null}} b
|
|
68
|
+
*/
|
|
69
|
+
function newestFirst(a, b) {
|
|
70
|
+
const at = Date.parse(a.publishedAt ?? '');
|
|
71
|
+
const bt = Date.parse(b.publishedAt ?? '');
|
|
72
|
+
if (Number.isNaN(at) !== Number.isNaN(bt)) return Number.isNaN(at) ? 1 : -1;
|
|
73
|
+
if (!Number.isNaN(at) && at !== bt) return bt - at;
|
|
74
|
+
return b.version.localeCompare(a.version, 'en', {numeric: true});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Check a catalog a discover source returned. Throws an Error naming the first
|
|
79
|
+
* problem. Items of a kind this CLI does not know are dropped, and versions are
|
|
80
|
+
* put newest first whatever order the source used.
|
|
81
|
+
*
|
|
82
|
+
* @param {unknown} value
|
|
83
|
+
* @param {string} [label]
|
|
84
|
+
* @returns {import('./type.js').DiscoverCatalog}
|
|
85
|
+
*/
|
|
86
|
+
export function parseDiscoverCatalog(value, label = 'discover source') {
|
|
87
|
+
const version =
|
|
88
|
+
value != null && typeof value === 'object'
|
|
89
|
+
? /** @type {{schemaVersion?: unknown}} */ (value).schemaVersion
|
|
90
|
+
: undefined;
|
|
91
|
+
if (version !== undefined && version !== 1) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`${label} returned schemaVersion ${String(version)}; this CLI reads schemaVersion 1`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
const parsed = catalogSchema.safeParse(value);
|
|
97
|
+
if (!parsed.success) {
|
|
98
|
+
const issue = parsed.error.issues[0];
|
|
99
|
+
const where = issue?.path.length ? ` at ${issue.path.join('.')}` : '';
|
|
100
|
+
throw new Error(
|
|
101
|
+
`${label} returned an invalid catalog${where}: ${issue?.message}`,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
const known = /** @type {readonly string[]} */ (DISCOVER_KINDS);
|
|
105
|
+
return /** @type {import('./type.js').DiscoverCatalog} */ ({
|
|
106
|
+
...parsed.data,
|
|
107
|
+
packages: parsed.data.packages.map(pkg => ({
|
|
108
|
+
...pkg,
|
|
109
|
+
versions: [...pkg.versions].sort(newestFirst),
|
|
110
|
+
contributions: pkg.contributions.filter(c => known.includes(c.kind)),
|
|
111
|
+
})),
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Check a discover source itself: an async function, like `debug`, that takes
|
|
117
|
+
* `{signal, package?, version?}` and resolves to a catalog.
|
|
118
|
+
*
|
|
119
|
+
* @param {unknown} value
|
|
120
|
+
* @param {string} label
|
|
121
|
+
* @returns {import('./type.js').DiscoverSource}
|
|
122
|
+
*/
|
|
123
|
+
export function parseDiscoverSource(value, label) {
|
|
124
|
+
if (typeof value !== 'function') {
|
|
125
|
+
throw new Error(`${label} must be a function`);
|
|
126
|
+
}
|
|
127
|
+
return /** @type {import('./type.js').DiscoverSource} */ (value);
|
|
128
|
+
}
|