@astryxdesign/cli 0.6.4-canary.f0355e3 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -99
- package/api/build/build.doc.mjs +1 -6
- package/api/build/build.test.mjs +0 -22
- package/api/build/kit/kit.mjs +5 -44
- package/api/component/_adapter.d.mts +0 -25
- package/api/component/_adapter.mjs +5 -59
- package/api/component/component.d.mts +3 -6
- package/api/component/component.doc.mjs +17 -37
- package/api/component/component.mjs +9 -249
- package/api/component/component.type.d.mts +0 -25
- package/api/component/component.type.mjs +0 -44
- package/api/discover/_adapter.d.mts +6 -114
- package/api/discover/_adapter.mjs +17 -372
- package/api/discover/detail/detail.d.mts +6 -18
- package/api/discover/detail/detail.mjs +13 -67
- package/api/discover/detail/detail.test.mjs +0 -85
- package/api/discover/discover.d.mts +9 -3
- package/api/discover/discover.doc.mjs +18 -61
- package/api/discover/discover.mjs +36 -220
- package/api/discover/discover.test.mjs +2 -11
- package/api/discover/discover.type.d.mts +8 -147
- package/api/discover/discover.type.mjs +12 -102
- package/api/discover/list/list.d.mts +6 -20
- package/api/discover/list/list.mjs +12 -45
- package/api/discover/list/list.test.mjs +0 -46
- package/api/discover/search/search.d.mts +16 -18
- package/api/discover/search/search.mjs +56 -102
- package/api/discover/search/search.test.mjs +10 -144
- package/api/docs/_adapter.d.mts +3 -8
- package/api/docs/_adapter.mjs +6 -14
- package/api/docs/docOverlays.test.mjs +1 -27
- package/api/docs/docs.doc.mjs +2 -2
- package/api/docs/docs.test.mjs +243 -0
- package/api/docs/integration-tree.test.mjs +555 -0
- package/api/docs/integrationDocs.test.mjs +314 -0
- package/api/doctor/doctor.d.mts +3 -8
- package/api/doctor/doctor.doc.mjs +8 -17
- package/api/doctor/doctor.mjs +9 -90
- package/api/doctor/doctor.test.mjs +10 -122
- 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 +10 -19
- package/api/hook/hook.doc.mjs +3 -6
- package/api/index.d.mts +2 -1
- package/api/index.mjs +5 -5
- package/api/init/init.doc.mjs +12 -17
- package/api/integration/add-helpers.d.mts +2 -5
- package/api/integration/add-helpers.mjs +9 -36
- package/api/integration/add-theme.mjs +1 -22
- package/api/integration/add-theme.test.mjs +0 -34
- package/api/integration/authoring-checks.mjs +2 -2
- package/api/integration/integrationPackCheck.doc.mjs +3 -3
- package/api/integration/pack-check.mjs +9 -82
- package/api/integration/pack-check.test.mjs +0 -90
- package/api/integration/pack-check.type.mjs +1 -1
- package/api/json/assertResponse.doc.mjs +1 -1
- package/api/json/index.ts +1 -0
- package/api/json/isError.doc.mjs +1 -1
- package/api/layout/_adapter.d.mts +34 -0
- package/api/layout/_adapter.mjs +148 -0
- package/api/layout/check/check.d.mts +16 -0
- package/api/layout/check/check.mjs +40 -0
- package/api/layout/expand/expand.d.mts +22 -0
- package/api/layout/expand/expand.mjs +155 -0
- package/api/layout/expand/expand.path-safety.test.mjs +53 -0
- package/api/layout/grammar/grammar.d.mts +13 -0
- package/api/layout/grammar/grammar.mjs +87 -0
- package/api/layout/layout.d.mts +6 -0
- package/api/layout/layout.mjs +17 -0
- package/api/layout/layout.test.mjs +297 -0
- package/api/layout/layout.type.d.mts +89 -0
- package/api/layout/layout.type.mjs +103 -0
- package/api/layout/layoutCheck.doc.d.mts +11 -0
- package/api/layout/layoutCheck.doc.mjs +85 -0
- package/api/layout/layoutExpand.doc.d.mts +11 -0
- package/api/layout/layoutExpand.doc.mjs +107 -0
- package/api/layout/layoutGrammar.doc.d.mts +11 -0
- package/api/layout/layoutGrammar.doc.mjs +57 -0
- package/api/search/search.d.mts +1 -27
- package/api/search/search.doc.mjs +2 -2
- package/api/search/search.mjs +16 -228
- package/api/search/search.test.mjs +512 -0
- package/api/swizzle/swizzle.doc.mjs +5 -7
- package/api/template/copy/copy.mjs +1 -1
- package/api/template/copy/copy.test.mjs +0 -9
- package/api/template/template-integration.test.mjs +65 -1
- package/api/template/template.doc.mjs +1 -2
- package/api/template/template.mjs +1 -1
- package/api/theme/add/add.mjs +25 -17
- package/api/theme/add/add.staging.test.mjs +23 -40
- package/api/theme/build/build.family.test.mjs +12 -7
- package/api/theme/build/build.mjs +18 -8
- package/api/theme/generateTonalPalette.doc.mjs +2 -1
- package/api/theme/listThemes.doc.mjs +1 -1
- package/api/theme/themeAdd.doc.mjs +10 -9
- package/api/theme/themeBuild.doc.mjs +13 -13
- package/api/theme/themeList.doc.mjs +1 -1
- package/api/theme/themeListAvailable.doc.mjs +1 -2
- package/api/theme/themePaletteGenerate.doc.mjs +8 -15
- package/api/theme/themeTargets.doc.mjs +2 -3
- package/api/theme/themeTemplate.doc.mjs +1 -2
- package/api/upgrade/run/run.mjs +4 -6
- package/api/upgrade/upgrade.doc.mjs +22 -24
- package/api/upgrade/upgrade.type.mjs +2 -2
- package/assets/codemods/__tests__/runner.test.mjs +1 -3
- package/assets/codemods/integration-runner.mjs +3 -3
- package/assets/codemods/runner.mjs +4 -5
- package/assets/docs/README.md +2 -4
- package/assets/docs/browser-support.doc.mjs +11 -11
- package/assets/docs/color.doc.mjs +2 -8
- package/assets/docs/elevation.doc.mjs +4 -6
- package/assets/docs/getting-started.doc.mjs +16 -5
- package/assets/docs/icons.doc.mjs +21 -2
- package/assets/docs/illustrations.doc.mjs +15 -7
- package/assets/docs/internationalization.doc.mjs +5 -7
- package/assets/docs/layout.doc.dense.mjs +82 -130
- package/assets/docs/layout.doc.mjs +77 -133
- package/assets/docs/migration.doc.mjs +21 -19
- package/assets/docs/motion.doc.mjs +3 -16
- package/assets/docs/principles.doc.dense.mjs +5 -5
- package/assets/docs/principles.doc.mjs +0 -8
- package/assets/docs/principles.doc.zh.mjs +6 -6
- package/assets/docs/shape.doc.mjs +3 -8
- package/assets/docs/spacing.doc.mjs +2 -7
- package/assets/docs/styling-libraries.doc.mjs +2 -6
- package/assets/docs/styling.doc.mjs +23 -19
- package/assets/docs/theme.doc.dense.mjs +18 -58
- package/assets/docs/theme.doc.mjs +46 -56
- package/assets/docs/theme.doc.zh.mjs +8 -9
- package/assets/docs/tokens.doc.dense.mjs +2 -2
- package/assets/docs/tokens.doc.mjs +8 -389
- package/assets/docs/tokens.doc.zh.mjs +2 -2
- package/assets/docs/tree/integrations.doc.mjs +451 -25
- package/assets/docs/tree/integrations.test.mjs +62 -0
- package/assets/docs/tree/writing-docs.doc.mjs +286 -0
- package/assets/docs/typography.doc.mjs +4 -24
- package/assets/docs/working-with-ai.doc.mjs +22 -30
- package/assets/templates/blocks/components/InternationalizationProvider/InternationalizationProvider01ShippedLocale.tsx +1 -1
- package/authoring/config/config.doc.mjs +2 -10
- package/authoring/config/parse.d.mts +0 -2
- package/authoring/config/parse.mjs +0 -19
- package/authoring/config/parse.test.mjs +0 -8
- package/authoring/config/type.ts +2 -13
- package/authoring/doctypes/_schema.d.mts +2 -3
- package/authoring/doctypes/_schema.mjs +0 -6
- package/authoring/doctypes/base/graph-fields.doc.mjs +3 -3
- package/authoring/doctypes/base/type.ts +2 -4
- package/authoring/doctypes/command/command.doc.mjs +1 -1
- package/authoring/doctypes/command/type.ts +1 -1
- package/authoring/doctypes/component/component.doc.mjs +0 -6
- package/authoring/doctypes/component/type.ts +0 -8
- package/authoring/doctypes/reference/reference.doc.mjs +0 -7
- package/authoring/doctypes/reference/type.ts +0 -5
- 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 +0 -1
- package/authoring/index.d.ts +0 -10
- package/authoring/index.mjs +0 -1
- package/authoring/integration/integration.doc.mjs +10 -12
- package/clients/cli/command-result-coverage.test.mjs +7 -7
- package/clients/cli/commands/component/index.mjs +55 -152
- package/clients/cli/commands/component-ownership.test.mjs +0 -89
- package/clients/cli/commands/component.doc.mjs +9 -27
- package/clients/cli/commands/debug-result-summary.test.mjs +2 -2
- package/clients/cli/commands/discover.doc.mjs +9 -53
- package/clients/cli/commands/discover.mjs +118 -393
- package/clients/cli/commands/docs.doc.mjs +1 -1
- package/clients/cli/commands/docs.mjs +17 -60
- package/clients/cli/commands/docs.test.mjs +294 -0
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +2 -3
- package/clients/cli/commands/doctor-integration.test.mjs +0 -53
- package/clients/cli/commands/doctor.doc.mjs +1 -3
- package/clients/cli/commands/doctor.mjs +5 -49
- package/clients/cli/commands/gap-report.doc.mjs +9 -10
- package/clients/cli/commands/init.doc.mjs +6 -9
- package/clients/cli/commands/integration-add.doc.mjs +9 -9
- package/clients/cli/commands/integration-authoring.test.mjs +10 -61
- package/clients/cli/commands/integration-pack.doc.mjs +9 -5
- package/clients/cli/commands/integration-real-world.test.mjs +1 -1
- package/clients/cli/commands/integration.doc.mjs +4 -4
- package/clients/cli/commands/integration.mjs +43 -74
- package/clients/cli/commands/layout-check.doc.mjs +65 -0
- package/clients/cli/commands/layout-expand.doc.mjs +83 -0
- package/clients/cli/commands/layout-grammar.doc.mjs +30 -0
- package/clients/cli/commands/layout.doc.mjs +34 -0
- package/clients/cli/commands/layout.error-codes.test.mjs +66 -0
- package/clients/cli/commands/layout.exit-parity.test.mjs +41 -0
- package/clients/cli/commands/layout.mjs +275 -0
- package/clients/cli/commands/layout.path-help.test.mjs +33 -0
- package/clients/cli/commands/layout.stdin-cap.test.mjs +47 -0
- package/clients/cli/commands/layout.text-fields.test.mjs +39 -0
- package/clients/cli/commands/manifest.doc.mjs +1 -1
- package/clients/cli/commands/search.doc.mjs +3 -10
- package/clients/cli/commands/search.mjs +2 -21
- package/clients/cli/commands/search.test.mjs +4 -21
- 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 +16 -5
- package/clients/cli/commands/theme-add.doc.mjs +1 -1
- package/clients/cli/commands/theme-palette-generate.doc.mjs +2 -3
- package/clients/cli/commands/theme-palette.doc.mjs +2 -1
- package/clients/cli/commands/theme-targets.doc.mjs +2 -2
- package/clients/cli/commands/theme.doc.mjs +1 -2
- package/clients/cli/commands/upgrade.doc.mjs +3 -62
- package/clients/cli/index.mjs +10 -28
- package/clients/cli/lib/define-command.mjs +4 -28
- package/clients/cli/lib/define-command.test.mjs +0 -54
- package/clients/cli/lib/exit-codes.test.mjs +9 -18
- package/clients/cli/lib/json-shim.mjs +14 -24
- package/clients/cli/lib/json-shim.test.mjs +20 -6
- package/clients/cli/lib/manifest.mjs +13 -18
- package/clients/cli/lib/manifest.test.mjs +2 -5
- package/foundation/agent-docs/agent-docs.mjs +1 -1
- package/foundation/agent-docs/agent-docs.test.mjs +1159 -0
- package/foundation/discovery/authoring-self-docs.mjs +0 -1
- package/foundation/discovery/authoring-self-docs.test.mjs +2 -6
- package/foundation/discovery/cli-self-docs.mjs +2 -16
- package/foundation/discovery/cli-self-docs.test.mjs +0 -20
- package/foundation/discovery/docs-discovery.mjs +1 -5
- package/foundation/discovery/docs-discovery.test.mjs +0 -21
- package/foundation/discovery/docs-section-key.d.mts +1 -1
- package/foundation/discovery/docs-section-key.mjs +1 -1
- package/foundation/discovery/template-adapter.mjs +1 -1
- package/foundation/doc-compiler/doc-loads.test.mjs +14 -3
- package/foundation/doc-compiler/tree.d.mts +0 -4
- package/foundation/doc-compiler/tree.mjs +1 -6
- package/foundation/doc-compiler/tree.test.mjs +598 -0
- package/foundation/integrations/cli-requirement.d.mts +6 -26
- package/foundation/integrations/cli-requirement.mjs +11 -46
- package/foundation/integrations/cli-requirement.test.mjs +2 -7
- package/foundation/integrations/contribution-inventory.mjs +1 -1
- package/foundation/integrations/integrations.d.mts +1 -14
- package/foundation/integrations/integrations.mjs +1 -41
- package/foundation/integrations/integrations.test.mjs +0 -31
- package/foundation/response/error-codes.doc.mjs +8 -6
- package/foundation/response/error-codes.test.mjs +5 -30
- package/foundation/response/response-types.doc.d.mts +3 -4
- package/foundation/response/response-types.doc.mjs +27 -40
- package/foundation/response/response-types.doc.test.mjs +0 -23
- package/foundation/response/response.doc.mjs +10 -11
- package/foundation/xle/browser.d.mts +3 -3
- package/foundation/xle/browser.mjs +3 -3
- package/foundation/xle/expand.mjs +2 -2
- package/foundation/xle/parse.mjs +1 -1
- package/foundation/xle/print.mjs +2 -2
- package/foundation/xle/splice.mjs +1 -1
- package/package.json +9 -9
- package/api/discover/_adapter.test.mjs +0 -215
- package/api/discover/_catalog-view.d.mts +0 -115
- package/api/discover/_catalog-view.mjs +0 -203
- package/api/discover/_catalog-view.test.mjs +0 -128
- package/api/discover/detail/item/item.d.mts +0 -26
- package/api/discover/detail/item/item.mjs +0 -78
- package/api/discover/detail/item/item.test.mjs +0 -73
- package/api/integration/pack-check.lifecycle-output.test.mjs +0 -107
- package/api/theme/add/add.rollback.test.mjs +0 -158
- package/api/theme/build/build.rollback.test.mjs +0 -148
- package/api/upgrade/run/files-changed.test.mjs +0 -111
- package/assets/codemods/file-count.test.mjs +0 -163
- package/assets/docs/tree/add-a-component.doc.mjs +0 -75
- package/assets/docs/tree/add-a-theme.doc.mjs +0 -85
- package/assets/docs/tree/add-a-topic.doc.mjs +0 -144
- package/assets/docs/tree/agent-guidance.doc.mjs +0 -138
- package/assets/docs/tree/block-template.doc.mjs +0 -130
- package/assets/docs/tree/build-the-template.doc.mjs +0 -28
- package/assets/docs/tree/building-blocks.doc.mjs +0 -46
- package/assets/docs/tree/check-your-docs.doc.mjs +0 -137
- package/assets/docs/tree/checks.doc.mjs +0 -119
- package/assets/docs/tree/codemods.doc.mjs +0 -147
- package/assets/docs/tree/component-family.doc.mjs +0 -113
- package/assets/docs/tree/component-imports.doc.mjs +0 -69
- package/assets/docs/tree/component-lookups.doc.mjs +0 -149
- package/assets/docs/tree/components.doc.mjs +0 -23
- package/assets/docs/tree/configuration.doc.mjs +0 -23
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +0 -182
- package/assets/docs/tree/define-the-theme.doc.mjs +0 -118
- package/assets/docs/tree/describe-the-component.doc.mjs +0 -57
- package/assets/docs/tree/docs.doc.mjs +0 -21
- package/assets/docs/tree/document-the-template.doc.mjs +0 -28
- package/assets/docs/tree/document-the-theme.doc.mjs +0 -68
- package/assets/docs/tree/export-template-assets.doc.mjs +0 -147
- package/assets/docs/tree/extend-or-replace.doc.mjs +0 -103
- package/assets/docs/tree/fonts-and-assets.doc.mjs +0 -106
- package/assets/docs/tree/generate-a-palette.doc.mjs +0 -66
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +0 -105
- package/assets/docs/tree/help.doc.mjs +0 -16
- package/assets/docs/tree/links.doc.mjs +0 -98
- package/assets/docs/tree/package-and-test.doc.mjs +0 -32
- package/assets/docs/tree/page-template.doc.mjs +0 -71
- package/assets/docs/tree/publishing.doc.mjs +0 -111
- package/assets/docs/tree/quick-start.doc.mjs +0 -272
- package/assets/docs/tree/replace-a-core-component.doc.mjs +0 -104
- package/assets/docs/tree/replace-a-core-template.doc.mjs +0 -172
- package/assets/docs/tree/sections-and-placement.doc.mjs +0 -108
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +0 -59
- package/assets/docs/tree/ship.doc.mjs +0 -16
- package/assets/docs/tree/short-and-findable.doc.mjs +0 -108
- package/assets/docs/tree/single-component.doc.mjs +0 -165
- package/assets/docs/tree/start-a-template.doc.mjs +0 -143
- package/assets/docs/tree/subcomponent.doc.mjs +0 -115
- package/assets/docs/tree/template-assets.doc.mjs +0 -64
- package/assets/docs/tree/template-doc-overview.doc.mjs +0 -109
- package/assets/docs/tree/template-fonts.doc.mjs +0 -102
- package/assets/docs/tree/template-grading-rubric.doc.mjs +0 -452
- package/assets/docs/tree/template-icons.doc.mjs +0 -97
- package/assets/docs/tree/template-images-media.doc.mjs +0 -127
- package/assets/docs/tree/template-styles.doc.mjs +0 -93
- package/assets/docs/tree/templates.doc.mjs +0 -34
- package/assets/docs/tree/test-in-an-app.doc.mjs +0 -115
- package/assets/docs/tree/test-template-in-app.doc.mjs +0 -128
- package/assets/docs/tree/themes.doc.mjs +0 -39
- package/assets/docs/tree/troubleshooting.doc.mjs +0 -149
- package/assets/docs/tree/upgrading.doc.mjs +0 -103
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +0 -51
- package/assets/docs/tree/verify-packed-template.doc.mjs +0 -77
- package/assets/docs/tree/versioning.doc.mjs +0 -161
- package/assets/docs/tree/write-good-templates.doc.mjs +0 -64
- package/assets/docs/tree/write-the-template-file.doc.mjs +0 -154
- package/authoring/discover/discover.doc.d.mts +0 -13
- package/authoring/discover/discover.doc.mjs +0 -138
- package/authoring/discover/parse.d.mts +0 -24
- package/authoring/discover/parse.mjs +0 -128
- package/authoring/discover/parse.test.mjs +0 -124
- package/authoring/discover/type.ts +0 -87
- package/clients/cli/commands/component-batch.test.mjs +0 -341
- package/clients/cli/commands/discover.sources.test.mjs +0 -267
- package/clients/cli/commands/integration-verify.doc.mjs +0 -22
- package/clients/cli/lib/parse-error-format.test.mjs +0 -81
- package/foundation/response/batch.type.d.mts +0 -33
- package/foundation/response/batch.type.mjs +0 -34
|
@@ -1,24 +0,0 @@
|
|
|
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"];
|
|
@@ -1,128 +0,0 @@
|
|
|
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
|
-
}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file Tests for the discover source and catalog checks.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import {describe, it, expect} from 'vitest';
|
|
8
|
-
import {
|
|
9
|
-
DISCOVER_KINDS,
|
|
10
|
-
parseDiscoverCatalog,
|
|
11
|
-
parseDiscoverSource,
|
|
12
|
-
} from './parse.mjs';
|
|
13
|
-
|
|
14
|
-
function catalog(overrides = {}) {
|
|
15
|
-
return {
|
|
16
|
-
schemaVersion: 1,
|
|
17
|
-
source: {
|
|
18
|
-
name: 'Acme catalog',
|
|
19
|
-
generatedAt: '2026-09-30T14:00:00.000Z',
|
|
20
|
-
complete: true,
|
|
21
|
-
},
|
|
22
|
-
packages: [
|
|
23
|
-
{
|
|
24
|
-
package: '@acme/ui',
|
|
25
|
-
integration: 'acme-ui',
|
|
26
|
-
aliases: [],
|
|
27
|
-
latest: '2.0.0',
|
|
28
|
-
versions: [
|
|
29
|
-
{
|
|
30
|
-
version: '2.0.0',
|
|
31
|
-
publishedAt: '2026-09-29T00:00:00.000Z',
|
|
32
|
-
prerelease: false,
|
|
33
|
-
status: 'ok',
|
|
34
|
-
},
|
|
35
|
-
],
|
|
36
|
-
contributions: [{kind: 'component', name: 'Button'}],
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
...overrides,
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
describe('parseDiscoverCatalog', () => {
|
|
44
|
-
it('accepts a catalog', () => {
|
|
45
|
-
expect(parseDiscoverCatalog(catalog())).toEqual(catalog());
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('drops fields it does not know, so a newer source still works', () => {
|
|
49
|
-
const parsed = parseDiscoverCatalog({...catalog(), cursor: 'next'});
|
|
50
|
-
expect(parsed).not.toHaveProperty('cursor');
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('drops items of a kind it does not know', () => {
|
|
54
|
-
const value = catalog();
|
|
55
|
-
value.packages[0].contributions.push({kind: 'widget', name: 'Spinner'});
|
|
56
|
-
expect(parseDiscoverCatalog(value).packages[0].contributions).toEqual([
|
|
57
|
-
{kind: 'component', name: 'Button'},
|
|
58
|
-
]);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('puts versions newest first whatever order the source used', () => {
|
|
62
|
-
const value = catalog();
|
|
63
|
-
value.packages[0].versions = [
|
|
64
|
-
{
|
|
65
|
-
version: '1.0.0',
|
|
66
|
-
publishedAt: '2026-01-05T00:00:00.000Z',
|
|
67
|
-
prerelease: false,
|
|
68
|
-
status: 'ok',
|
|
69
|
-
},
|
|
70
|
-
{version: '1.5.0', publishedAt: null, prerelease: false, status: 'ok'},
|
|
71
|
-
{
|
|
72
|
-
version: '2.0.0',
|
|
73
|
-
publishedAt: '2026-09-29T00:00:00.000Z',
|
|
74
|
-
prerelease: false,
|
|
75
|
-
status: 'ok',
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
version: '2.0.0-rc.1',
|
|
79
|
-
publishedAt: '2026-09-01T00:00:00.000Z',
|
|
80
|
-
prerelease: true,
|
|
81
|
-
status: 'ok',
|
|
82
|
-
},
|
|
83
|
-
];
|
|
84
|
-
expect(
|
|
85
|
-
parseDiscoverCatalog(value).packages[0].versions.map(v => v.version),
|
|
86
|
-
).toEqual(['2.0.0', '2.0.0-rc.1', '1.0.0', '1.5.0']);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('refuses a schemaVersion it does not read', () => {
|
|
90
|
-
expect(() => parseDiscoverCatalog(catalog({schemaVersion: 2}))).toThrow(
|
|
91
|
-
'this CLI reads schemaVersion 1',
|
|
92
|
-
);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('names the first problem and where it is', () => {
|
|
96
|
-
expect(() =>
|
|
97
|
-
parseDiscoverCatalog(catalog({packages: [{package: ''}]}), 'the source'),
|
|
98
|
-
).toThrow(/^the source returned an invalid catalog at packages\.0\./);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('lists the kinds in display order', () => {
|
|
102
|
-
expect(DISCOVER_KINDS).toEqual([
|
|
103
|
-
'component',
|
|
104
|
-
'template',
|
|
105
|
-
'doc',
|
|
106
|
-
'theme',
|
|
107
|
-
'codemod',
|
|
108
|
-
'agent-doc',
|
|
109
|
-
]);
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
describe('parseDiscoverSource', () => {
|
|
114
|
-
it('accepts a function', () => {
|
|
115
|
-
const source = async () => catalog();
|
|
116
|
-
expect(parseDiscoverSource(source, 'discover')).toBe(source);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('refuses anything else, such as a URL', () => {
|
|
120
|
-
expect(() =>
|
|
121
|
-
parseDiscoverSource('https://example.com/catalog.json', 'discover'),
|
|
122
|
-
).toThrow('discover must be a function');
|
|
123
|
-
});
|
|
124
|
-
});
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Public type surface for discover sources.
|
|
5
|
-
*
|
|
6
|
-
* A discover source tells `astryx discover` which integrations exist beyond the
|
|
7
|
-
* ones a project already has. A project sets one as `discover` in
|
|
8
|
-
* `astryx.config`; an integration exports one as a `discover` NAMED export from
|
|
9
|
-
* its manifest. Discover calls every source, checks each answer, keeps a saved
|
|
10
|
-
* copy of the last good one, and never installs, enables, or runs anything a
|
|
11
|
-
* catalog names.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
/** Kinds of item a package can add. */
|
|
15
|
-
export type DiscoverKind =
|
|
16
|
-
'component' | 'template' | 'doc' | 'theme' | 'codemod' | 'agent-doc';
|
|
17
|
-
|
|
18
|
-
/** One item a package version adds. */
|
|
19
|
-
export interface DiscoverContribution {
|
|
20
|
-
kind: DiscoverKind;
|
|
21
|
-
/**
|
|
22
|
-
* The name the CLI uses for it: a component name, template id, doc topic,
|
|
23
|
-
* theme slug, or codemod id.
|
|
24
|
-
*/
|
|
25
|
-
name: string;
|
|
26
|
-
title?: string;
|
|
27
|
-
summary?: string;
|
|
28
|
-
keywords?: string[];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** One published version of a package. */
|
|
32
|
-
export interface DiscoverVersion {
|
|
33
|
-
version: string;
|
|
34
|
-
/** ISO 8601 publish time, or null when the source does not know it. */
|
|
35
|
-
publishedAt: string | null;
|
|
36
|
-
prerelease: boolean;
|
|
37
|
-
/** `ok`, or why the source could not read this version. */
|
|
38
|
-
status: string;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** One npm package a source knows about. */
|
|
42
|
-
export interface DiscoverPackage {
|
|
43
|
-
package: string;
|
|
44
|
-
/** Shared by every npm name that publishes the same integration. */
|
|
45
|
-
integration: string;
|
|
46
|
-
/** The integration's other npm names. Discover never offers one the project has. */
|
|
47
|
-
aliases: string[];
|
|
48
|
-
description?: string;
|
|
49
|
-
/** The latest release, or null when the package has only prereleases. */
|
|
50
|
-
latest: string | null;
|
|
51
|
-
/** Every version, newest first. */
|
|
52
|
-
versions: DiscoverVersion[];
|
|
53
|
-
/** What the requested version adds, or the latest when none was requested. */
|
|
54
|
-
contributions: DiscoverContribution[];
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/** What a discover source returns. */
|
|
58
|
-
export interface DiscoverCatalog {
|
|
59
|
-
schemaVersion: 1;
|
|
60
|
-
source: {
|
|
61
|
-
/** Shown to people, for example "Acme catalog". */
|
|
62
|
-
name: string;
|
|
63
|
-
/** ISO 8601 time the source's data was produced. */
|
|
64
|
-
generatedAt: string;
|
|
65
|
-
/** False when the source knows its list is partial. */
|
|
66
|
-
complete: boolean;
|
|
67
|
-
};
|
|
68
|
-
packages: DiscoverPackage[];
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** One call to a discover source. */
|
|
72
|
-
export interface DiscoverSourceContext {
|
|
73
|
-
/** Aborted when the source exceeds its 30-second budget. */
|
|
74
|
-
readonly signal: AbortSignal;
|
|
75
|
-
/** Asks for one package: every version, and `version`'s contributions. */
|
|
76
|
-
readonly package?: string;
|
|
77
|
-
/** With `package`: the version whose contributions to return. Defaults to the latest. */
|
|
78
|
-
readonly version?: string;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* A discover source: an async function, like `debug`. Set it as `discover` in
|
|
83
|
-
* astryx.config, or export it as `discover` from an integration manifest.
|
|
84
|
-
*/
|
|
85
|
-
export type DiscoverSource = (
|
|
86
|
-
context: DiscoverSourceContext,
|
|
87
|
-
) => Promise<DiscoverCatalog>;
|
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @file Multi-selector component lookup contract: one ordered batch envelope,
|
|
5
|
-
* complete per-selector states, unchanged single-selector responses, and matching
|
|
6
|
-
* text/JSON exit behavior.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import {describe, it, expect} from 'vitest';
|
|
10
|
-
import * as path from 'node:path';
|
|
11
|
-
import {
|
|
12
|
-
component,
|
|
13
|
-
COMPONENT_BATCH_SELECTOR_LIMIT,
|
|
14
|
-
} from '../../../api/component/component.mjs';
|
|
15
|
-
import {runCli} from '../../../test-utils/run-cli.mjs';
|
|
16
|
-
|
|
17
|
-
const REPO_ROOT = path.resolve(import.meta.dirname, '../../../../..');
|
|
18
|
-
const SLOW = 60_000;
|
|
19
|
-
|
|
20
|
-
describe('component() batch lookup', () => {
|
|
21
|
-
it(
|
|
22
|
-
'keeps one found row per selector, in order, including duplicates',
|
|
23
|
-
async () => {
|
|
24
|
-
const result = await component(['Button', 'Badge', 'Button'], {
|
|
25
|
-
cwd: REPO_ROOT,
|
|
26
|
-
detail: 'brief',
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
expect(result.type).toBe('component.batch');
|
|
30
|
-
expect(result.data.count).toBe(3);
|
|
31
|
-
expect(result.data.results.map(row => row.selector)).toEqual([
|
|
32
|
-
'Button',
|
|
33
|
-
'Badge',
|
|
34
|
-
'Button',
|
|
35
|
-
]);
|
|
36
|
-
expect(result.data.results.map(row => row.status)).toEqual([
|
|
37
|
-
'found',
|
|
38
|
-
'found',
|
|
39
|
-
'found',
|
|
40
|
-
]);
|
|
41
|
-
expect(
|
|
42
|
-
result.data.results.map(row =>
|
|
43
|
-
row.status === 'found' ? row.result.type : null,
|
|
44
|
-
),
|
|
45
|
-
).toEqual(['component.detail', 'component.detail', 'component.detail']);
|
|
46
|
-
},
|
|
47
|
-
SLOW,
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
it(
|
|
51
|
-
'applies every focused projection to each found row',
|
|
52
|
-
async () => {
|
|
53
|
-
const projections = [
|
|
54
|
-
{options: {props: true}, expectedType: 'component.detail.props'},
|
|
55
|
-
{options: {source: true}, expectedType: 'component.detail.source'},
|
|
56
|
-
{options: {showcase: true}, expectedType: 'component.detail.showcase'},
|
|
57
|
-
{options: {blocks: true}, expectedType: 'component.detail.blocks'},
|
|
58
|
-
];
|
|
59
|
-
for (const projection of projections) {
|
|
60
|
-
const result = await component(['Button', 'Card'], {
|
|
61
|
-
cwd: REPO_ROOT,
|
|
62
|
-
...projection.options,
|
|
63
|
-
});
|
|
64
|
-
expect(result.type).toBe('component.batch');
|
|
65
|
-
expect(
|
|
66
|
-
result.data.results.map(row =>
|
|
67
|
-
row.status === 'found' ? row.result.type : null,
|
|
68
|
-
),
|
|
69
|
-
).toEqual([projection.expectedType, projection.expectedType]);
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
SLOW,
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
it(
|
|
76
|
-
'uses input shape to distinguish catalog, single, and batch calls',
|
|
77
|
-
async () => {
|
|
78
|
-
expect((await component(undefined, {cwd: REPO_ROOT})).type).toBe(
|
|
79
|
-
'component.list',
|
|
80
|
-
);
|
|
81
|
-
expect((await component('Button', {cwd: REPO_ROOT})).type).toBe(
|
|
82
|
-
'component.detail',
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
const emptyBatch = await component([], {cwd: REPO_ROOT});
|
|
86
|
-
expect(emptyBatch).toEqual({
|
|
87
|
-
type: 'component.batch',
|
|
88
|
-
data: {count: 0, results: []},
|
|
89
|
-
});
|
|
90
|
-
expect(
|
|
91
|
-
await component([], {
|
|
92
|
-
cwd: REPO_ROOT,
|
|
93
|
-
list: true,
|
|
94
|
-
category: 'Form',
|
|
95
|
-
}),
|
|
96
|
-
).toEqual(emptyBatch);
|
|
97
|
-
|
|
98
|
-
const oneRowBatch = await component(['Button'], {
|
|
99
|
-
cwd: REPO_ROOT,
|
|
100
|
-
detail: 'brief',
|
|
101
|
-
});
|
|
102
|
-
expect(oneRowBatch).toMatchObject({
|
|
103
|
-
type: 'component.batch',
|
|
104
|
-
data: {
|
|
105
|
-
count: 1,
|
|
106
|
-
results: [
|
|
107
|
-
{
|
|
108
|
-
selector: 'Button',
|
|
109
|
-
status: 'found',
|
|
110
|
-
result: {type: 'component.detail'},
|
|
111
|
-
},
|
|
112
|
-
],
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
},
|
|
116
|
-
SLOW,
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
it('rejects an oversized array before component resolution starts', async () => {
|
|
120
|
-
const selectors = Array.from(
|
|
121
|
-
{length: COMPONENT_BATCH_SELECTOR_LIMIT + 1},
|
|
122
|
-
() => 'Button',
|
|
123
|
-
);
|
|
124
|
-
await expect(
|
|
125
|
-
component(selectors, {
|
|
126
|
-
cwd: path.join(REPO_ROOT, 'missing-batch-cwd'),
|
|
127
|
-
}),
|
|
128
|
-
).rejects.toMatchObject({
|
|
129
|
-
code: 'ERR_INVALID_ARGUMENT',
|
|
130
|
-
message: `Component batch accepts at most ${COMPONENT_BATCH_SELECTOR_LIMIT} selectors; received ${selectors.length}`,
|
|
131
|
-
});
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it(
|
|
135
|
-
'keeps receipt invariants across a deterministic selector chaos matrix',
|
|
136
|
-
async () => {
|
|
137
|
-
const found = new Set(['Button', 'Card']);
|
|
138
|
-
const selectorCases = [
|
|
139
|
-
[],
|
|
140
|
-
['Button'],
|
|
141
|
-
['ZzzNope99'],
|
|
142
|
-
['Button', 'Button'],
|
|
143
|
-
['ZzzNope98', 'ZzzNope99'],
|
|
144
|
-
['Button', 'ZzzNope99', 'Card'],
|
|
145
|
-
['ZzzNope99', 'Button', 'ZzzNope99', 'Button'],
|
|
146
|
-
['Card', 'Button', 'Card', 'ZzzNope98', 'Button'],
|
|
147
|
-
];
|
|
148
|
-
|
|
149
|
-
for (const selectors of selectorCases) {
|
|
150
|
-
const result = await component(selectors, {
|
|
151
|
-
cwd: REPO_ROOT,
|
|
152
|
-
detail: 'brief',
|
|
153
|
-
});
|
|
154
|
-
expect(result.type).toBe('component.batch');
|
|
155
|
-
expect(result.data.count).toBe(selectors.length);
|
|
156
|
-
expect(result.data.results.map(row => row.selector)).toEqual(selectors);
|
|
157
|
-
expect(result.data.results.map(row => row.status)).toEqual(
|
|
158
|
-
selectors.map(selector =>
|
|
159
|
-
found.has(selector) ? 'found' : 'not_found',
|
|
160
|
-
),
|
|
161
|
-
);
|
|
162
|
-
for (const row of result.data.results) {
|
|
163
|
-
if (row.status === 'found') {
|
|
164
|
-
expect(row.result.type).toBe('component.detail');
|
|
165
|
-
} else {
|
|
166
|
-
expect(row.code).toBe('ERR_UNKNOWN_COMPONENT');
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
},
|
|
171
|
-
SLOW,
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
it(
|
|
175
|
-
'composes every detail and language control over a batch',
|
|
176
|
-
async () => {
|
|
177
|
-
/** @type {Array<{detail?: 'full'|'compact'|'brief'; lang?: string; zh?: boolean; dense?: boolean}>} */
|
|
178
|
-
const controls = [
|
|
179
|
-
{detail: 'brief'},
|
|
180
|
-
{detail: 'compact'},
|
|
181
|
-
{detail: 'full'},
|
|
182
|
-
{lang: 'en'},
|
|
183
|
-
{lang: 'dense'},
|
|
184
|
-
{zh: true},
|
|
185
|
-
{dense: true},
|
|
186
|
-
];
|
|
187
|
-
for (const control of controls) {
|
|
188
|
-
const result = await component(['Button', 'Card'], {
|
|
189
|
-
cwd: REPO_ROOT,
|
|
190
|
-
...control,
|
|
191
|
-
});
|
|
192
|
-
expect(result.type).toBe('component.batch');
|
|
193
|
-
expect(result.data.results).toHaveLength(2);
|
|
194
|
-
expect(
|
|
195
|
-
result.data.results.every(
|
|
196
|
-
row =>
|
|
197
|
-
row.status === 'found' && row.result.type === 'component.detail',
|
|
198
|
-
),
|
|
199
|
-
).toBe(true);
|
|
200
|
-
}
|
|
201
|
-
},
|
|
202
|
-
SLOW,
|
|
203
|
-
);
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
describe('astryx component batch lookup', () => {
|
|
207
|
-
it('documents variadic selector grammar in --help', async () => {
|
|
208
|
-
const run = await runCli(['component', '--help'], REPO_ROOT);
|
|
209
|
-
expect(run.code).toBe(0);
|
|
210
|
-
expect(run.stdout).toContain(
|
|
211
|
-
'Usage: astryx component [options] [names...]',
|
|
212
|
-
);
|
|
213
|
-
expect(run.stdout).toContain('@scope/package@version/Name');
|
|
214
|
-
expect(run.stdout).toContain('Two or more return one ordered batch');
|
|
215
|
-
expect(run.stdout).toContain('At most 100 selectors');
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
it(
|
|
219
|
-
'keeps catalog and single-result CLI envelopes at zero and one selectors',
|
|
220
|
-
async () => {
|
|
221
|
-
const catalog = await runCli(['--json', 'component'], REPO_ROOT);
|
|
222
|
-
expect(catalog.code).toBe(0);
|
|
223
|
-
expect(JSON.parse(catalog.stdout).type).toBe('component.list');
|
|
224
|
-
|
|
225
|
-
const single = await runCli(
|
|
226
|
-
['--json', '--detail', 'brief', 'component', 'Button'],
|
|
227
|
-
REPO_ROOT,
|
|
228
|
-
);
|
|
229
|
-
expect(single.code).toBe(0);
|
|
230
|
-
expect(JSON.parse(single.stdout).type).toBe('component.detail');
|
|
231
|
-
},
|
|
232
|
-
SLOW,
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
it(
|
|
236
|
-
'emits one component.batch JSON envelope for several found selectors',
|
|
237
|
-
async () => {
|
|
238
|
-
const run = await runCli(
|
|
239
|
-
['--json', '--detail', 'brief', 'component', 'Button', 'Badge'],
|
|
240
|
-
REPO_ROOT,
|
|
241
|
-
);
|
|
242
|
-
expect(run.code).toBe(0);
|
|
243
|
-
const envelope = JSON.parse(run.stdout);
|
|
244
|
-
expect(envelope.type).toBe('component.batch');
|
|
245
|
-
expect(envelope.data.count).toBe(2);
|
|
246
|
-
expect(envelope.data.results.map(row => row.selector)).toEqual([
|
|
247
|
-
'Button',
|
|
248
|
-
'Badge',
|
|
249
|
-
]);
|
|
250
|
-
expect(envelope.data.results.every(row => row.status === 'found')).toBe(
|
|
251
|
-
true,
|
|
252
|
-
);
|
|
253
|
-
},
|
|
254
|
-
SLOW,
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
it(
|
|
258
|
-
'rejects an oversized batch before emitting JSON or text results',
|
|
259
|
-
async () => {
|
|
260
|
-
const selectors = Array.from(
|
|
261
|
-
{length: COMPONENT_BATCH_SELECTOR_LIMIT + 1},
|
|
262
|
-
() => 'Button',
|
|
263
|
-
);
|
|
264
|
-
const json = await runCli(
|
|
265
|
-
['--json', 'component', ...selectors],
|
|
266
|
-
REPO_ROOT,
|
|
267
|
-
);
|
|
268
|
-
expect(json.code).toBe(1);
|
|
269
|
-
expect(JSON.parse(json.stdout)).toMatchObject({
|
|
270
|
-
code: 'ERR_INVALID_ARGUMENT',
|
|
271
|
-
error: `Component batch accepts at most ${COMPONENT_BATCH_SELECTOR_LIMIT} selectors; received ${selectors.length}`,
|
|
272
|
-
});
|
|
273
|
-
expect(JSON.parse(json.stdout).type).toBeUndefined();
|
|
274
|
-
|
|
275
|
-
const text = await runCli(['component', ...selectors], REPO_ROOT);
|
|
276
|
-
expect(text.code).toBe(1);
|
|
277
|
-
expect(text.stdout + text.stderr).toContain(
|
|
278
|
-
`accepts at most ${COMPONENT_BATCH_SELECTOR_LIMIT} selectors`,
|
|
279
|
-
);
|
|
280
|
-
},
|
|
281
|
-
SLOW,
|
|
282
|
-
);
|
|
283
|
-
|
|
284
|
-
it(
|
|
285
|
-
'emits every row and exits 1 when one selector is not found',
|
|
286
|
-
async () => {
|
|
287
|
-
const run = await runCli(
|
|
288
|
-
['--json', '--detail', 'brief', 'component', 'Button', 'ZzzNope99'],
|
|
289
|
-
REPO_ROOT,
|
|
290
|
-
);
|
|
291
|
-
expect(run.code).toBe(1);
|
|
292
|
-
const envelope = JSON.parse(run.stdout);
|
|
293
|
-
expect(envelope.type).toBe('component.batch');
|
|
294
|
-
expect(envelope.data.results).toMatchObject([
|
|
295
|
-
{selector: 'Button', status: 'found'},
|
|
296
|
-
{
|
|
297
|
-
selector: 'ZzzNope99',
|
|
298
|
-
status: 'not_found',
|
|
299
|
-
code: 'ERR_UNKNOWN_COMPONENT',
|
|
300
|
-
},
|
|
301
|
-
]);
|
|
302
|
-
},
|
|
303
|
-
SLOW,
|
|
304
|
-
);
|
|
305
|
-
|
|
306
|
-
it(
|
|
307
|
-
'emits every failed row and exits 1 when no selector resolves',
|
|
308
|
-
async () => {
|
|
309
|
-
const run = await runCli(
|
|
310
|
-
['--json', 'component', 'ZzzNope98', 'ZzzNope99'],
|
|
311
|
-
REPO_ROOT,
|
|
312
|
-
);
|
|
313
|
-
expect(run.code).toBe(1);
|
|
314
|
-
const envelope = JSON.parse(run.stdout);
|
|
315
|
-
expect(envelope.type).toBe('component.batch');
|
|
316
|
-
expect(envelope.data.count).toBe(2);
|
|
317
|
-
expect(envelope.data.results).toMatchObject([
|
|
318
|
-
{selector: 'ZzzNope98', status: 'not_found'},
|
|
319
|
-
{selector: 'ZzzNope99', status: 'not_found'},
|
|
320
|
-
]);
|
|
321
|
-
},
|
|
322
|
-
SLOW,
|
|
323
|
-
);
|
|
324
|
-
|
|
325
|
-
it(
|
|
326
|
-
'projects every row in text and keeps the same failing exit status',
|
|
327
|
-
async () => {
|
|
328
|
-
const run = await runCli(
|
|
329
|
-
['--detail', 'brief', 'component', 'Button', 'ZzzNope99'],
|
|
330
|
-
REPO_ROOT,
|
|
331
|
-
);
|
|
332
|
-
expect(run.code).toBe(1);
|
|
333
|
-
expect(run.stdout).toContain('count: 2');
|
|
334
|
-
expect(run.stdout).toMatch(/selector: Button\nstatus:\s+found/);
|
|
335
|
-
expect(run.stdout).toMatch(
|
|
336
|
-
/selector: ZzzNope99\nstatus:\s+not_found\ncode:\s+ERR_UNKNOWN_COMPONENT/,
|
|
337
|
-
);
|
|
338
|
-
},
|
|
339
|
-
SLOW,
|
|
340
|
-
);
|
|
341
|
-
});
|