@astryxdesign/cli 0.7.2-canary.ccf1a1c → 0.7.2-canary.d216097
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 +21 -20
- package/api/build/help/help.mjs +1 -1
- package/api/component/_adapter.d.mts +41 -1
- package/api/component/_adapter.mjs +93 -7
- package/api/component/component.mjs +22 -5
- package/api/component/component.test.mjs +80 -0
- package/api/component/integration-export-name.test.mjs +644 -0
- package/api/component/list/list.mjs +42 -4
- package/api/discover/_adapter.d.mts +119 -12
- package/api/discover/_adapter.mjs +449 -10
- package/api/discover/_adapter.test.mjs +599 -17
- package/api/discover/_catalog-view.d.mts +16 -5
- package/api/discover/_catalog-view.mjs +32 -8
- package/api/discover/discover.d.mts +11 -0
- package/api/discover/discover.doc.mjs +7 -6
- package/api/discover/discover.mjs +107 -19
- package/api/discover/discover.type.d.mts +18 -7
- package/api/discover/discover.type.mjs +15 -7
- package/api/discover/list/list.d.mts +4 -3
- package/api/discover/list/list.mjs +17 -10
- package/api/docs/_adapter.d.mts +11 -0
- package/api/docs/_adapter.mjs +244 -1
- package/api/docs/integrationDocs.test.mjs +124 -0
- package/api/doctor/doctor.mjs +27 -3
- package/api/doctor/doctor.test.mjs +43 -0
- package/api/doctor/theme-checks.mjs +1 -1
- package/api/doctor/theme-checks.test.mjs +136 -0
- package/api/gap-report/gap-report.d.mts +3 -0
- package/api/gap-report/gap-report.doc.mjs +11 -3
- package/api/gap-report/gap-report.mjs +219 -52
- package/api/gap-report/gap-report.test.mjs +233 -0
- package/api/gap-report/gap-report.type.d.mts +41 -0
- package/api/gap-report/gap-report.type.mjs +18 -0
- package/api/index.d.mts +2 -0
- package/api/index.mjs +2 -0
- package/api/init/run/run.mjs +2 -2
- package/api/integration/_adapter.d.mts +22 -0
- package/api/integration/_adapter.mjs +67 -0
- package/api/integration/add-contribution.component-names.test.mjs +66 -0
- package/api/integration/add-contribution.mjs +8 -4
- package/api/integration/add-contribution.test.mjs +4 -2
- package/api/integration/authoring-checks.mjs +24 -4
- package/api/integration/authoring-checks.test.mjs +365 -0
- package/api/integration/authoring-checks.type.d.mts +59 -0
- package/api/integration/authoring-checks.type.mjs +35 -2
- package/api/integration/check/check.d.mts +96 -0
- package/api/integration/check/check.mjs +357 -0
- package/api/integration/check/check.test.mjs +489 -0
- package/api/integration/integration-check.type.d.mts +118 -0
- package/api/integration/integration-check.type.mjs +84 -0
- package/api/integration/integrationCheck.doc.d.mts +10 -0
- package/api/integration/integrationCheck.doc.mjs +73 -0
- package/api/integration/integrationComponentConflicts.doc.mjs +43 -6
- package/api/integration/integrationDocConflicts.doc.mjs +17 -5
- package/api/integration/pack-check.mjs +353 -114
- package/api/integration/pack-check.test.mjs +700 -0
- package/api/integration/validate-integration.mjs +8 -0
- package/api/integration/validate-integration.test.mjs +11 -0
- package/api/integration/validate-integration.type.d.mts +8 -0
- package/api/integration/validate-integration.type.mjs +12 -1
- package/api/integration/validateIntegration.doc.mjs +19 -3
- package/api/search/search.d.mts +81 -12
- package/api/search/search.domain-priority.test.mjs +108 -18
- package/api/search/search.integration-check.test.mjs +24 -0
- package/api/search/search.mjs +609 -53
- package/api/search/search.test.mjs +175 -0
- package/api/swizzle/copy/copy.mjs +28 -14
- package/api/template/template.test.mjs +120 -3
- package/api/theme/build/build.family.test.mjs +64 -0
- package/api/theme/build/build.mjs +180 -24
- package/api/theme/themeBuild.doc.mjs +4 -4
- package/api/upgrade/_adapter.d.mts +40 -2
- package/api/upgrade/_adapter.mjs +117 -4
- package/api/upgrade/run/cli-behind-core.test.mjs +438 -0
- package/api/upgrade/run/run.mjs +30 -1
- package/api/upgrade/status/status.d.mts +21 -5
- package/api/upgrade/status/status.mjs +45 -8
- package/api/upgrade/upgrade.doc.mjs +5 -3
- package/api/upgrade/upgrade.type.d.mts +23 -0
- package/api/upgrade/upgrade.type.mjs +16 -1
- package/assets/codemods/runner.mjs +7 -1
- package/assets/codemods/transforms/next/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +120 -0
- package/assets/codemods/transforms/next/index.mjs +11 -1
- package/assets/codemods/transforms/next/migrate-list-edge-compensation-to-edge.mjs +198 -0
- package/assets/discover/official-packages.json +367 -0
- package/assets/docs/README.md +10 -0
- package/assets/docs/author-a-theme.doc.mjs +3 -3
- package/assets/docs/getting-started.doc.mjs +3 -3
- package/assets/docs/styling-overview.doc.mjs +1 -1
- package/assets/docs/theme.doc.dense.mjs +1 -1
- package/assets/docs/theme.doc.mjs +2 -2
- package/assets/docs/theme.doc.zh.mjs +1 -1
- package/assets/docs/tree/add-a-component.doc.mjs +11 -1
- package/assets/docs/tree/add-a-theme.doc.mjs +1 -1
- package/assets/docs/tree/add-a-topic.doc.mjs +11 -8
- package/assets/docs/tree/agent-guidance.doc.mjs +2 -2
- package/assets/docs/tree/block-template.doc.mjs +8 -20
- package/assets/docs/tree/build-the-template.doc.mjs +1 -1
- package/assets/docs/tree/check-the-props.doc.mjs +196 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +57 -7
- package/assets/docs/tree/checks.doc.mjs +26 -18
- package/assets/docs/tree/codemods.doc.mjs +4 -4
- package/assets/docs/tree/component-family.doc.mjs +8 -6
- package/assets/docs/tree/component-imports.doc.mjs +10 -2
- package/assets/docs/tree/components.doc.mjs +1 -1
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +25 -16
- package/assets/docs/tree/define-the-theme.doc.mjs +6 -5
- package/assets/docs/tree/describe-the-component.doc.mjs +2 -2
- package/assets/docs/tree/docs.doc.mjs +3 -3
- package/assets/docs/tree/document-the-template.doc.mjs +1 -1
- package/assets/docs/tree/document-the-theme.doc.mjs +1 -1
- package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
- package/assets/docs/tree/extend-or-replace.doc.mjs +6 -6
- package/assets/docs/tree/fonts-and-assets.doc.mjs +2 -2
- package/assets/docs/tree/generate-a-palette.doc.mjs +5 -3
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +1 -1
- package/assets/docs/tree/integrations.doc.mjs +8 -0
- package/assets/docs/tree/layout-spacing.doc.mjs +2 -3
- package/assets/docs/tree/layout.doc.mjs +6 -6
- package/assets/docs/tree/links.doc.mjs +6 -5
- package/assets/docs/tree/migration-setup.doc.mjs +3 -2
- package/assets/docs/tree/migration-verification.doc.mjs +0 -1
- package/assets/docs/tree/migration.doc.mjs +0 -1
- package/assets/docs/tree/package-and-test.doc.mjs +1 -1
- package/assets/docs/tree/page-template.doc.mjs +4 -8
- package/assets/docs/tree/publishing.doc.mjs +2 -2
- package/assets/docs/tree/quick-start.doc.mjs +38 -22
- package/assets/docs/tree/replace-a-core-component.doc.mjs +4 -6
- package/assets/docs/tree/replace-a-core-template.doc.mjs +6 -8
- package/assets/docs/tree/sections-and-placement.doc.mjs +4 -6
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +4 -2
- package/assets/docs/tree/short-and-findable.doc.mjs +6 -5
- package/assets/docs/tree/single-component.doc.mjs +15 -6
- package/assets/docs/tree/start-a-template.doc.mjs +3 -3
- package/assets/docs/tree/subcomponent.doc.mjs +6 -6
- package/assets/docs/tree/template-assets.doc.mjs +2 -2
- package/assets/docs/tree/template-doc-overview.doc.mjs +5 -16
- package/assets/docs/tree/template-fonts.doc.mjs +1 -1
- package/assets/docs/tree/template-icons.doc.mjs +1 -1
- package/assets/docs/tree/template-images-media.doc.mjs +1 -1
- package/assets/docs/tree/template-styles.doc.mjs +2 -2
- package/assets/docs/tree/templates.doc.mjs +1 -1
- package/assets/docs/tree/test-in-an-app.doc.mjs +3 -3
- package/assets/docs/tree/test-template-in-app.doc.mjs +1 -1
- package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
- package/assets/docs/tree/troubleshooting.doc.mjs +16 -8
- package/assets/docs/tree/type-scale.doc.mjs +3 -3
- package/assets/docs/tree/upgrading.doc.mjs +4 -4
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +3 -1
- package/assets/docs/tree/verify-packed-template.doc.mjs +1 -1
- package/assets/docs/tree/versioning.doc.mjs +7 -6
- package/assets/docs/tree/write-the-template-file.doc.mjs +4 -3
- package/assets/docs/use-a-theme.doc.mjs +2 -2
- package/assets/docs/working-with-ai.doc.mjs +43 -4
- package/assets/theme.template.ts +1 -1
- package/authoring/codemod/codemod.doc.mjs +7 -3
- package/authoring/config/config.doc.mjs +9 -6
- package/authoring/config/type.ts +4 -2
- package/authoring/discover/discover.doc.mjs +1 -1
- package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
- package/authoring/doctypes/command/command.doc.mjs +14 -12
- package/authoring/doctypes/component/component.doc.mjs +30 -27
- package/authoring/doctypes/component/type.ts +13 -8
- package/authoring/doctypes/enum/enum.doc.mjs +7 -4
- package/authoring/doctypes/function/function.doc.mjs +9 -8
- package/authoring/doctypes/hook/hook.doc.mjs +5 -4
- package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
- package/authoring/doctypes/reference/reference.doc.mjs +11 -10
- package/authoring/doctypes/schema/schema.doc.mjs +9 -9
- package/authoring/doctypes/template/integration-template.doc.d.mts +11 -0
- package/authoring/doctypes/template/integration-template.doc.mjs +49 -0
- package/authoring/doctypes/template/parse.d.mts +6 -2
- package/authoring/doctypes/template/parse.mjs +3 -1
- package/authoring/doctypes/template/template.doc.mjs +3 -3
- package/authoring/doctypes/template/type.ts +22 -0
- package/authoring/doctypes/theme/theme.doc.mjs +2 -2
- package/authoring/gap-report/gap-report.doc.mjs +2 -2
- package/authoring/identity/identity.doc.mjs +3 -3
- package/authoring/index.d.ts +1 -0
- package/authoring/integration/integration.doc.mjs +12 -4
- package/authoring/integration/parse.test.mjs +10 -0
- package/authoring/integration/schema.d.mts +2 -0
- package/authoring/integration/schema.mjs +1 -0
- package/authoring/integration/type.ts +4 -0
- package/clients/cli/commands/build-theme.batch-report.test.mjs +3 -1
- package/clients/cli/commands/build-theme.mjs +1 -1
- package/clients/cli/commands/build-theme.path-safety.test.mjs +224 -6
- package/clients/cli/commands/build-theme.registry.test.mjs +5 -2
- package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
- package/clients/cli/commands/discover.broken-integration.test.mjs +4 -1
- package/clients/cli/commands/discover.doc.mjs +1 -1
- package/clients/cli/commands/discover.mjs +144 -93
- package/clients/cli/commands/discover.no-source.test.mjs +447 -33
- package/clients/cli/commands/discover.sources.test.mjs +20 -1
- package/clients/cli/commands/doctor-integration-components.doc.mjs +17 -4
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +17 -5
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +13 -2
- package/clients/cli/commands/doctor-integration.test.mjs +837 -0
- package/clients/cli/commands/doctor.mjs +224 -3
- package/clients/cli/commands/gap-report.doc.mjs +14 -2
- package/clients/cli/commands/gap-report.mjs +24 -2
- package/clients/cli/commands/gap-report.test.mjs +79 -0
- package/clients/cli/commands/integration-check.doc.mjs +85 -0
- package/clients/cli/commands/integration-check.test.mjs +332 -0
- package/clients/cli/commands/integration.doc.mjs +6 -2
- package/clients/cli/commands/integration.mjs +106 -1
- package/clients/cli/commands/json-contract.test.mjs +5 -1
- package/clients/cli/commands/setup-nudge.test.mjs +79 -1
- package/clients/cli/commands/swizzle.mjs +5 -3
- package/clients/cli/commands/swizzle.routing.test.mjs +18 -1
- package/clients/cli/commands/text-json-parity.test.mjs +5 -0
- package/clients/cli/commands/theme-build.doc.mjs +2 -2
- package/clients/cli/commands/upgrade.doc.mjs +14 -0
- package/clients/cli/commands/upgrade.older-cli.test.mjs +160 -0
- package/clients/cli/index.mjs +30 -5
- package/foundation/agent-docs/agent-doc-state.d.mts +14 -0
- package/foundation/agent-docs/agent-doc-state.mjs +38 -0
- package/foundation/agent-docs/agent-docs.d.mts +2 -1
- package/foundation/agent-docs/agent-docs.mjs +8 -6
- package/foundation/config/project.mjs +82 -0
- package/foundation/discovery/authoring-self-docs.mjs +2 -1
- package/foundation/discovery/component-discovery.d.mts +190 -10
- package/foundation/discovery/component-discovery.export-names.test.mjs +760 -0
- package/foundation/discovery/component-discovery.mjs +864 -56
- package/foundation/discovery/component-discovery.test.mjs +96 -0
- package/foundation/discovery/component-replacement.mjs +18 -0
- package/foundation/discovery/component-replacement.test.mjs +40 -0
- package/foundation/discovery/copied-passages.d.mts +208 -0
- package/foundation/discovery/copied-passages.mjs +720 -0
- package/foundation/discovery/copied-passages.test.mjs +124 -0
- package/foundation/discovery/doc-types.d.mts +157 -0
- package/foundation/discovery/doc-types.mjs +1224 -0
- package/foundation/discovery/doc-types.test.mjs +700 -0
- package/foundation/discovery/docs-discovery.d.mts +88 -0
- package/foundation/discovery/docs-discovery.mjs +83 -2
- package/foundation/discovery/integration-doc-files.d.mts +22 -0
- package/foundation/discovery/integration-doc-files.mjs +231 -0
- package/foundation/discovery/integration-doc-files.test.mjs +246 -0
- package/foundation/discovery/module-exports.d.mts +27 -0
- package/foundation/discovery/module-exports.mjs +356 -31
- package/foundation/discovery/module-exports.test.mjs +172 -0
- package/foundation/discovery/package-tsconfig.d.mts +14 -0
- package/foundation/discovery/package-tsconfig.mjs +228 -0
- package/foundation/discovery/package-tsconfig.test.mjs +210 -0
- package/foundation/discovery/project-typescript.d.mts +32 -0
- package/foundation/discovery/project-typescript.mjs +89 -0
- package/foundation/discovery/prop-drift.d.mts +278 -0
- package/foundation/discovery/prop-drift.mjs +2263 -0
- package/foundation/discovery/prop-drift.test.mjs +2272 -0
- package/foundation/discovery/template-adapter.mjs +74 -5
- package/foundation/discovery/type-match.d.mts +53 -0
- package/foundation/discovery/type-match.mjs +660 -0
- package/foundation/discovery/type-match.test.mjs +169 -0
- package/foundation/discovery/type-text.d.mts +68 -0
- package/foundation/discovery/type-text.mjs +658 -0
- package/foundation/discovery/type-text.test.mjs +196 -0
- package/foundation/discovery/unresolved-references.d.mts +62 -0
- package/foundation/discovery/unresolved-references.mjs +790 -0
- package/foundation/discovery/unresolved-references.test.mjs +567 -0
- package/foundation/doc-compiler/doc-loads.test.mjs +19 -1
- package/foundation/doc-compiler/inputs.mjs +23 -0
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/doc-compiler/links.d.mts +9 -5
- package/foundation/doc-compiler/links.mjs +4 -2
- package/foundation/env/package-manager.d.mts +32 -0
- package/foundation/env/package-manager.mjs +47 -0
- package/foundation/env/package-manager.test.mjs +194 -7
- package/foundation/fs/module-loader.d.mts +2 -1
- package/foundation/fs/module-loader.mjs +60 -4
- package/foundation/fs/module-loader.test.mjs +194 -0
- package/foundation/integrations/contribution-inventory.mjs +6 -1
- package/foundation/response/response-types.doc.mjs +14 -8
- package/foundation/xle/registry.mjs +4 -0
- package/foundation/xle/registry.test.mjs +28 -0
- package/package.json +9 -9
- package/scripts/postinstall.mjs +3 -3
package/README.md
CHANGED
|
@@ -437,7 +437,7 @@ Every response has a `type` discriminant. The full set is below (generated from
|
|
|
437
437
|
| `docs.node` | One node of the docs tree, read by its route: its id, kind, package, title, summary, and breadcrumb, plus a namespace's slots with their children (one level down, each naming its package) or a typed doc's content, and links ({up, previous, next, related}: the commands that open its parent, its neighbors, and the docs it names). |
|
|
438
438
|
| `blog.list` | The feed URL plus every post parsed from the RSS feed, each with slug, title, description, date, type, authors, link, and plaintext URL. |
|
|
439
439
|
| `blog.detail` | One post's metadata plus the feed URL and the post's full plaintext body. |
|
|
440
|
-
| `discover.list` |
|
|
440
|
+
| `discover.list` | What the project has, the integrations it loads and the official packages it declares, official packages first (name, category, components, version, a list per other kind they add, and latest when a source knows it); meta.available lists what the project could add, the official packages first, each with the command that adds it, and meta.sources reports each source, the official list last; when it lists no integration it carries meta.configured to tell "nothing configured" from "nothing discovered". |
|
|
441
441
|
| `discover.detail` | One package, for an @scope/name or @scope/name@version query: what the shown version adds, whether the project has it, and, when a source knows the package, its versions, latest release, and the command that adds it. |
|
|
442
442
|
| `discover.detail.doc` | The validated ComponentDoc for one installed component, for an @scope/name/Component query. |
|
|
443
443
|
| `discover.item` | One item that is not an installed component, for an @scope/name/<item> query: its kind, name, package, version, and whether the project has the package. |
|
|
@@ -447,8 +447,8 @@ Every response has a `type` discriminant. The full set is below (generated from
|
|
|
447
447
|
| `build.kit` | The template to start from and its kit: query, hasResults, matchCount (never a cap), directMatch, start {name, package, command, basis, reason, alternatives, ...} (the start and each alternative name the package that owns the template), pages (search's closest templates), blocks and domain as SearchResultEntry[] (each naming its package), frame and foundation (Core component names), and hint {reason, commands} when thin. |
|
|
448
448
|
| `swizzle.list` | The names of swizzlable components discoverable from cwd's @astryxdesign/core. The envelope's package is @astryxdesign/core. |
|
|
449
449
|
| `swizzle.copy` | An eject receipt: component name, owning package, output directory, files-copied count, the written file names, whether any file uses StyleX, and, when the owner has an issues URL, feedback ({issuesUrl, ghCommand?}): where to report the gap that led to swizzling. The envelope's package names the same owning package. |
|
|
450
|
-
| `gap-report.categories` | The fixed gap category values and human-readable labels.
|
|
451
|
-
| `gap-report.file` | An aggregate receipt: overall status, the selected package, issuesUrl (or null), deliveries in handler order, each {handlerType: project \| integration \| fallback, handler, audience, status, url, message}, and filedCount/routedOnlyCount totals.
|
|
450
|
+
| `gap-report.categories` | The fixed gap category values and human-readable labels; when a loaded integration names its own issues URL, meta.destinations lists every destination ({to, default, issuesUrl}) and meta.ask tells an agent to ask the person. |
|
|
451
|
+
| `gap-report.file` | An aggregate receipt: overall status, the selected package, issuesUrl (or null), deliveries in handler order, each {handlerType: project \| integration \| fallback, handler, audience, status, url, message}, and filedCount/routedOnlyCount totals; without --to, when a loaded integration names its own issues URL, destinations and ask as on gap-report.categories. |
|
|
452
452
|
| `template.list` | The effective discovered TemplateListEntry[] for pages and blocks. A winning replacement entry includes optional `replaces`, naming the Core id omitted from the default list. |
|
|
453
453
|
| `template.show` | The resolved template's source, exactly as a copy writes it, plus its description, kind, the component names it composes, and demoMediaReplaced (how many Astryx demo media references were replaced with placeholders for you to swap for your own media). |
|
|
454
454
|
| `template.skeleton` | A layout skeleton (structural tags with spatial annotations) plus the template's description and the components it composes. The envelope's package names the npm package that owns the template. |
|
|
@@ -468,18 +468,19 @@ Every response has a `type` discriminant. The full set is below (generated from
|
|
|
468
468
|
| `theme.palette.generate` | An author-reviewable OKLCH palette candidate, its reproducibility receipt, summary counts, and optional candidate/receipt file-write result. |
|
|
469
469
|
| `upgrade.list` | Every available codemod, oldest→newest, as {name, package, title, version, optional}; returned for --list without running anything. |
|
|
470
470
|
| `upgrade.registry` | The copied-composition receipt for --registry: applied, ok, the counts (found, current, wouldUpdate, updated, wouldMerge, merged, wouldRefreshReceipt, receiptsRefreshed, conflicts, missing, invalid, failed), and items. |
|
|
471
|
-
| `upgrade.status` | A short-circuit outcome with no codemods run (up_to_date, no_codemods, or config_fixable), each carrying the agent-docs summary.
|
|
472
|
-
| `upgrade.run` | The run receipt: from/to versions, codemod count, integrations processed, the agent-docs summary, sourcePathFound (false when the resolved source directory does not exist, so no source file was read), and (apply mode) filesChanged, transformsApplied, and per-codemod errors.
|
|
471
|
+
| `upgrade.status` | A short-circuit outcome with no codemods run (up_to_date, no_codemods, or config_fixable), each carrying the agent-docs summary. no_codemods and config_fixable carry cliBehindCore ({cliVersion, command}) when the installed Core is newer than the CLI, which then has no codemods for the releases after its own version. |
|
|
472
|
+
| `upgrade.run` | The run receipt: from/to versions, codemod count, integrations processed, the agent-docs summary, sourcePathFound (false when the resolved source directory does not exist, so no source file was read), and (apply mode) filesChanged, transformsApplied, and per-codemod errors. When the installed Core is newer than the CLI, it also carries cliBehindCore ({cliVersion, command}): codemods for the releases after cliVersion did not run. |
|
|
473
473
|
| `manifest` | The CLI capability manifest: name, version, apiVersion, description, globalOptions, commands (each name, description, arguments, options, json, aliases?, responseTypes?, examples?, exitCodes? as [{code, when}], subcommands?), jsonSupported, and the flat responseTypes index. |
|
|
474
474
|
| `help` | Help, in one of two shapes. A bare `astryx --json` returns the root manifest: name, version, commands (the command names), jsonSupported, and manifest (the full payload `astryx manifest --json` returns). `--help --json` on any command, or `astryx help [command] --json`, returns that command's help: command, description, usage, options (each flags, description, and defaultValue and choices when set), and subcommands (each name and description). data.manifest marks the first shape; data.usage marks the second. |
|
|
475
475
|
| `version` | The CLI version, for `astryx --version --json`: {version}. |
|
|
476
476
|
| `doctor` | The health-check report: `checks` (each with id, label, status: pass \| warn \| fail \| info, a message, and an optional fix, always present on warn and fail) plus a `summary` of counts per status. |
|
|
477
477
|
| `integration.add` | A contribution-writer receipt: kind, name, optional root {path, created}, integration-manifest path, every affected project-relative path, written, and dryRun. |
|
|
478
478
|
| `integration.pack-check` | The packed-package check: name, version, packable, tarball {filename, fileCount, size, unpackedSize} or null, inventory {manifest, roots [{kind, path, expectedFiles, missingFiles, complete}], expectedFiles, packedFiles}, contributions {local, packed}, each null or {themes [{slug, exportName}], components, templates [{id, type, name}], codemods [{version, id}], docs, agentDocsAppend}, and issues [{code, severity, message}]. |
|
|
479
|
-
| `integration.validate` | The validation result: validated (false when nothing was validated: with no package.json the issues list carries one no_package error so the command exits 1, and with a package.json but no integration manifest the issues list is empty and proves nothing), the package name and version (both null when validated is false) plus issues, an AstryxIntegrationIssue[] of {code, severity: warning \| error, message}.
|
|
479
|
+
| `integration.validate` | The validation result: validated (false when nothing was validated: with no package.json the issues list carries one no_package error so the command exits 1, and with a package.json but no integration manifest the issues list is empty and proves nothing), the package name and version (both null when validated is false) plus issues, an AstryxIntegrationIssue[] of {code, severity: warning \| error, message}. When the manifest loads, docTypes checks each doc against its published authoring type: status (checked \| skipped), reason, typescript, docs, findings (all warnings, each naming the field and a fix), unchecked, and fixtures (test fixture docs not checked). |
|
|
480
480
|
| `integration.template-conflicts` | validated (false when no integration manifest was found, so nothing was inspected), the integration identity, structural issues, and non-blocking Core template-id conflicts as {id, severity: warning, integrationPackage, integrationType, integrationName, coreMatches, message, command}. |
|
|
481
|
-
| `integration.component-conflicts` | validated (false when no integration manifest was found, so nothing was inspected), the integration identity, structural issues, and non-blocking conflicts where an integration component name is also owned by Core; each conflict includes the exact package-qualified command.
|
|
482
|
-
| `integration.doc-conflicts` | validated (false when no integration manifest was found, so nothing was inspected), the integration identity, structural issues, and Core doc overlaps. Each finding includes `severity` (`info` \| `error`) and `relationship` (`replaces` \| `extends` \| `accidental`).
|
|
481
|
+
| `integration.component-conflicts` | validated (false when no integration manifest was found, so nothing was inspected), the integration identity, structural issues, and non-blocking conflicts where an integration component name is also owned by Core; each conflict includes the exact package-qualified command. When the manifest loads and declares a components root, propDrift compares documented props with the TypeScript props: status (checked \| skipped), reason, typescript, components, typesCompared, typesSkipped, findings (all warnings), unchecked, typesNotCompared, and propsNotChecked. |
|
|
482
|
+
| `integration.doc-conflicts` | validated (false when no integration manifest was found, so nothing was inspected), the integration identity, structural issues, and Core doc overlaps. Each finding includes `severity` (`info` \| `error`) and `relationship` (`replaces` \| `extends` \| `accidental`). copiedPassages lists each pair of topics that repeat 10 or more words of prose word for word: topic, section, otherTopic, otherOwner (package \| core), words, passages, owner (the topic that should keep the text), text (the passage as the topic writes it), line (where the copy starts in the topic to change, or null), and message (the exact replacement); each is also a copied_passage warning in issues. |
|
|
483
|
+
| `integration.check` | Every source check of an integration package in one result: validated (false when no integration manifest was found, so nothing was checked), the package name and version, strict, and checks, one entry per check (validate, components, templates, docs), each with check, errors, warnings, skipped, failed, and response, the envelope that check returns on its own. The totals are errors, warnings, and skipped; unchecked counts what the checks could not compare. With --strict, failures lists each warning and each piece of skipped work again as an error, in the issue format the checks use; it is empty without --strict. failed decides the exit code. |
|
|
483
484
|
|
|
484
485
|
<!-- END GENERATED: response-types -->
|
|
485
486
|
<!-- Generated by scripts/generate-cli-readme.mjs from the response-types EnumDoc. Run `pnpm -F @astryxdesign/cli readme`. -->
|
|
@@ -551,12 +552,12 @@ data: { checks, summary } }`) that AI agents and scripts can parse.
|
|
|
551
552
|
Omit `[package]` to inspect the package at the current directory, or pass an
|
|
552
553
|
installed package name:
|
|
553
554
|
|
|
554
|
-
| Command | What it checks
|
|
555
|
-
| ----------------------------------------- |
|
|
556
|
-
| `doctor integration validate [package]` | Manifest shape and every declared contribution
|
|
557
|
-
| `doctor integration templates [package]` | Template IDs shared with Core
|
|
558
|
-
| `doctor integration components [package]` | Component names shared with Core
|
|
559
|
-
| `doctor integration docs [package]` | Core topic replacements, extensions, and same-name conflicts
|
|
555
|
+
| Command | What it checks | Exit `1` when |
|
|
556
|
+
| ----------------------------------------- | ----------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
557
|
+
| `doctor integration validate [package]` | Manifest shape and every declared contribution | A structural issue has error severity |
|
|
558
|
+
| `doctor integration templates [package]` | Template IDs shared with Core | The integration is invalid; ID conflicts are warnings |
|
|
559
|
+
| `doctor integration components [package]` | Component names shared with Core, and each props table against the TypeScript props | The integration is invalid; name conflicts and prop differences are warnings |
|
|
560
|
+
| `doctor integration docs [package]` | Core topic replacements, extensions, and same-name conflicts | A Core overlap is accidental or the docs are invalid |
|
|
560
561
|
|
|
561
562
|
Template and component conflicts include the exact `--package` command needed
|
|
562
563
|
to select the integration contribution. Doc replacements and extensions are
|
|
@@ -580,12 +581,12 @@ There is no factory: write a plain object. For editor autocomplete and
|
|
|
580
581
|
type-checking, annotate it with the `AstryxConfig` type exported from
|
|
581
582
|
`@astryxdesign/cli/authoring`.
|
|
582
583
|
|
|
583
|
-
| Field | Type | Purpose
|
|
584
|
-
| ----------------------------- | ------------------------------ |
|
|
585
|
-
| `integrations` | `string[]` | Integration package names to load (see [Integrations](#integrations)).
|
|
586
|
-
| `issuesUrl` | `string` | Where "report an issue" links point for your project. Defaults to the core issue tracker.
|
|
587
|
-
| `hooks.postCodemod` | `PostCodemodHook[]` | Commands to run after `astryx upgrade` applies codemods (e.g. reinstall, rebuild, reformat).
|
|
588
|
-
| `experimental.xle.components` | `Record<string, XleComponent>` |
|
|
584
|
+
| Field | Type | Purpose |
|
|
585
|
+
| ----------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
586
|
+
| `integrations` | `string[]` | Integration package names to load (see [Integrations](#integrations)). |
|
|
587
|
+
| `issuesUrl` | `string` | Where "report an issue" links point for your project. Defaults to the core issue tracker. |
|
|
588
|
+
| `hooks.postCodemod` | `PostCodemodHook[]` | Commands to run after `astryx upgrade` applies codemods (e.g. reinstall, rebuild, reformat). |
|
|
589
|
+
| `experimental.xle.components` | `Record<string, XleComponent>` | Custom components for the removed layout expander, keyed by component name. The CLI still validates the field, so an entry without a string `from` makes `astryx.config` invalid, but nothing reads it. |
|
|
589
590
|
|
|
590
591
|
The config is validated against a strict schema when the CLI loads it, so an
|
|
591
592
|
unknown field is a hard error rather than a silent no-op. `astryx doctor`
|
package/api/build/help/help.mjs
CHANGED
|
@@ -63,7 +63,7 @@ export function buildHelp() {
|
|
|
63
63
|
"Keep the template's page frame, gap, and padding values. Replace its data, copy, and sections.",
|
|
64
64
|
'No <div>/raw HTML for layout — use VStack/HStack/Grid/Stack/Card etc.',
|
|
65
65
|
'No style={{}} — use component props, and design tokens for values.',
|
|
66
|
-
"Wrap the app in <Theme theme={...}> (import {Theme} from '@astryxdesign/core') and import core reset.css + astryx.css.",
|
|
66
|
+
"Wrap the app in <Theme theme={...}> (import {Theme} from '@astryxdesign/core/theme') and import core reset.css + astryx.css.",
|
|
67
67
|
],
|
|
68
68
|
related: [
|
|
69
69
|
{
|
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
* @property {string|null} sourcePath
|
|
27
27
|
* @property {string|undefined} issuesUrl
|
|
28
28
|
* @property {import('../../foundation/integrations/integrations.mjs').LoadedIntegration|null} integration
|
|
29
|
+
* @property {import('../../foundation/discovery/component-discovery.mjs').NameHold} hold
|
|
30
|
+
* how the owner holds the name, for the owner rule
|
|
29
31
|
*/
|
|
30
32
|
/**
|
|
31
33
|
* What ownership shaping needs from an owner. The core and legacy-external
|
|
@@ -138,6 +140,25 @@ export function assertUnambiguousOwners(owners: ComponentOwner[], dirName: strin
|
|
|
138
140
|
* @returns {string | null}
|
|
139
141
|
*/
|
|
140
142
|
export function resolveLegacyExternalDoc(ext: ExternalPackageRef, dirName: string): string | null;
|
|
143
|
+
/**
|
|
144
|
+
* Whether a legacy external package documents `dirName`.
|
|
145
|
+
* @param {string} cwd
|
|
146
|
+
* @param {string} dirName
|
|
147
|
+
* @returns {boolean}
|
|
148
|
+
*/
|
|
149
|
+
export function legacyExternalDocuments(cwd: string, dirName: string): boolean;
|
|
150
|
+
/**
|
|
151
|
+
* Whether a legacy docs package keeps `dirName` over these owners, each of which
|
|
152
|
+
* holds it only as an export a doc records.
|
|
153
|
+
* @param {string} cwd
|
|
154
|
+
* @param {string} dirName
|
|
155
|
+
* @param {Array<{hold?: string, docPath?: string | null}>} owners
|
|
156
|
+
* @returns {boolean}
|
|
157
|
+
*/
|
|
158
|
+
export function legacyExternalKeeps(cwd: string, dirName: string, owners: Array<{
|
|
159
|
+
hold?: string;
|
|
160
|
+
docPath?: string | null;
|
|
161
|
+
}>): boolean;
|
|
141
162
|
/**
|
|
142
163
|
* The core source file for `dirName` (the no-scope `--source` path reads core
|
|
143
164
|
* directly — it does NOT fall back to externals or fuzzy search).
|
|
@@ -210,7 +231,20 @@ export function scopeSubComponent(docs: LoadedComponentDoc, dirName: string, cor
|
|
|
210
231
|
};
|
|
211
232
|
matchingComponent: any;
|
|
212
233
|
} | null;
|
|
213
|
-
|
|
234
|
+
/**
|
|
235
|
+
* The doc an integration owner shows for `dirName`: when `dirName` is a member
|
|
236
|
+
* its family doc lists under its own name (`AcmeSlide` in an `AcmeCarousel`
|
|
237
|
+
* doc), the doc scoped to that member as {@link scopeSubComponent} scopes
|
|
238
|
+
* Core's, keeping the import the family doc states; otherwise `docs` itself.
|
|
239
|
+
* @param {LoadedComponentDoc} docs
|
|
240
|
+
* @param {OwnershipSubject} owner
|
|
241
|
+
* @param {string} dirName
|
|
242
|
+
* @returns {LoadedComponentDoc & {parentDoc?: string, import?: string}}
|
|
243
|
+
*/
|
|
244
|
+
export function scopeIntegrationMember(docs: LoadedComponentDoc, owner: OwnershipSubject, dirName: string): LoadedComponentDoc & {
|
|
245
|
+
parentDoc?: string;
|
|
246
|
+
import?: string;
|
|
247
|
+
};
|
|
214
248
|
/**
|
|
215
249
|
* Internal ambiguity marker. Single-component callers still receive the same
|
|
216
250
|
* AstryxError code, message, and suggestions; batch callers can additionally
|
|
@@ -261,6 +295,10 @@ export type ComponentOwner = {
|
|
|
261
295
|
sourcePath: string | null;
|
|
262
296
|
issuesUrl: string | undefined;
|
|
263
297
|
integration: import("../../foundation/integrations/integrations.mjs").LoadedIntegration | null;
|
|
298
|
+
/**
|
|
299
|
+
* how the owner holds the name, for the owner rule
|
|
300
|
+
*/
|
|
301
|
+
hold: import("../../foundation/discovery/component-discovery.mjs").NameHold;
|
|
264
302
|
};
|
|
265
303
|
/**
|
|
266
304
|
* What ownership shaping needs from an owner. The core and legacy-external
|
|
@@ -303,4 +341,6 @@ export type ResolvedUnscopedDoc = {
|
|
|
303
341
|
resolvedSourcePath: string | null;
|
|
304
342
|
};
|
|
305
343
|
import { CORE_PACKAGE } from '../../foundation/discovery/component-discovery.mjs';
|
|
344
|
+
import { unscopedComponentOwners } from '../../foundation/discovery/component-discovery.mjs';
|
|
306
345
|
import { AstryxError } from '../error.mjs';
|
|
346
|
+
export { CORE_PACKAGE, unscopedComponentOwners };
|
|
@@ -28,13 +28,17 @@ import {
|
|
|
28
28
|
import {
|
|
29
29
|
CORE_PACKAGE,
|
|
30
30
|
discoverComponents,
|
|
31
|
+
docStem,
|
|
31
32
|
findComponentReadme,
|
|
32
33
|
findComponentSource,
|
|
33
34
|
findExternalComponentDoc,
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
findIntegrationComponent,
|
|
36
|
+
integrationMemberEntry,
|
|
37
|
+
isIntegrationMember,
|
|
38
|
+
recordedDocName,
|
|
36
39
|
resolveImportPath,
|
|
37
40
|
resolveIntegrationImportPath as resolveIntegrationImport,
|
|
41
|
+
unscopedComponentOwners,
|
|
38
42
|
} from '../../foundation/discovery/component-discovery.mjs';
|
|
39
43
|
import {Project} from '../../foundation/config/project.mjs';
|
|
40
44
|
import {loadComponentDoc as loadValidatedComponentDoc} from '../../foundation/discovery/component-loader.mjs';
|
|
@@ -42,7 +46,7 @@ import {resolveComponentReplacements} from '../../foundation/discovery/component
|
|
|
42
46
|
import {searchComponents} from '../../foundation/text/string-utils.mjs';
|
|
43
47
|
import {AstryxError} from '../error.mjs';
|
|
44
48
|
|
|
45
|
-
export {CORE_PACKAGE};
|
|
49
|
+
export {CORE_PACKAGE, unscopedComponentOwners};
|
|
46
50
|
|
|
47
51
|
/**
|
|
48
52
|
* A loaded component doc. The shared validated loader accepts stamped and legacy
|
|
@@ -71,6 +75,8 @@ export {CORE_PACKAGE};
|
|
|
71
75
|
* @property {string|null} sourcePath
|
|
72
76
|
* @property {string|undefined} issuesUrl
|
|
73
77
|
* @property {import('../../foundation/integrations/integrations.mjs').LoadedIntegration|null} integration
|
|
78
|
+
* @property {import('../../foundation/discovery/component-discovery.mjs').NameHold} hold
|
|
79
|
+
* how the owner holds the name, for the owner rule
|
|
74
80
|
*/
|
|
75
81
|
|
|
76
82
|
/**
|
|
@@ -240,17 +246,19 @@ export function resolveOwners(coreDir, dirName, loadedIntegrations) {
|
|
|
240
246
|
sourcePath: findComponentSource(coreDir, dirName),
|
|
241
247
|
issuesUrl: undefined,
|
|
242
248
|
integration: null,
|
|
249
|
+
hold: 'core',
|
|
243
250
|
});
|
|
244
251
|
}
|
|
245
252
|
for (const integration of loadedIntegrations) {
|
|
246
|
-
const
|
|
247
|
-
if (!
|
|
253
|
+
const found = findIntegrationComponent(integration, dirName);
|
|
254
|
+
if (!found) continue;
|
|
248
255
|
owners.push({
|
|
249
256
|
package: integration.name,
|
|
250
|
-
docPath,
|
|
251
|
-
sourcePath:
|
|
257
|
+
docPath: found.docPath,
|
|
258
|
+
sourcePath: found.sourcePath,
|
|
252
259
|
issuesUrl: integration.issuesUrl,
|
|
253
260
|
integration,
|
|
261
|
+
hold: found.hold,
|
|
254
262
|
});
|
|
255
263
|
}
|
|
256
264
|
return owners;
|
|
@@ -361,6 +369,39 @@ export function resolveLegacyExternalDoc(ext, dirName) {
|
|
|
361
369
|
return extDocPath && extDocPath.endsWith('.doc.mjs') ? extDocPath : null;
|
|
362
370
|
}
|
|
363
371
|
|
|
372
|
+
/**
|
|
373
|
+
* Whether a legacy external package documents `dirName`.
|
|
374
|
+
* @param {string} cwd
|
|
375
|
+
* @param {string} dirName
|
|
376
|
+
* @returns {boolean}
|
|
377
|
+
*/
|
|
378
|
+
export function legacyExternalDocuments(cwd, dirName) {
|
|
379
|
+
return discoverExternalPackages(cwd).some(
|
|
380
|
+
ext => resolveLegacyExternalDoc(ext, dirName) != null,
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Whether a legacy docs package keeps `dirName` over these owners, each of which
|
|
386
|
+
* holds it only as an export a doc records.
|
|
387
|
+
* @param {string} cwd
|
|
388
|
+
* @param {string} dirName
|
|
389
|
+
* @param {Array<{hold?: string, docPath?: string | null}>} owners
|
|
390
|
+
* @returns {boolean}
|
|
391
|
+
*/
|
|
392
|
+
export function legacyExternalKeeps(cwd, dirName, owners) {
|
|
393
|
+
return (
|
|
394
|
+
owners.length > 0 &&
|
|
395
|
+
owners.every(
|
|
396
|
+
owner =>
|
|
397
|
+
owner.hold === 'doc' &&
|
|
398
|
+
owner.docPath != null &&
|
|
399
|
+
docStem(owner.docPath).toLowerCase() !== dirName.toLowerCase(),
|
|
400
|
+
) &&
|
|
401
|
+
legacyExternalDocuments(cwd, dirName)
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
|
|
364
405
|
/**
|
|
365
406
|
* The core source file for `dirName` (the no-scope `--source` path reads core
|
|
366
407
|
* directly — it does NOT fall back to externals or fuzzy search).
|
|
@@ -583,3 +624,48 @@ export function scopeSubComponent(docs, dirName, coreDir) {
|
|
|
583
624
|
|
|
584
625
|
return {scoped, matchingComponent};
|
|
585
626
|
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* The doc an integration owner shows for `dirName`: when `dirName` is a member
|
|
630
|
+
* its family doc lists under its own name (`AcmeSlide` in an `AcmeCarousel`
|
|
631
|
+
* doc), the doc scoped to that member as {@link scopeSubComponent} scopes
|
|
632
|
+
* Core's, keeping the import the family doc states; otherwise `docs` itself.
|
|
633
|
+
* @param {LoadedComponentDoc} docs
|
|
634
|
+
* @param {OwnershipSubject} owner
|
|
635
|
+
* @param {string} dirName
|
|
636
|
+
* @returns {LoadedComponentDoc & {parentDoc?: string, import?: string}}
|
|
637
|
+
*/
|
|
638
|
+
export function scopeIntegrationMember(docs, owner, dirName) {
|
|
639
|
+
const record = {name: dirName, docPath: owner.docPath ?? null};
|
|
640
|
+
if (!isIntegrationMember(record)) return docs;
|
|
641
|
+
const entry = integrationMemberEntry(docs, record);
|
|
642
|
+
// The files list the member but the doc this process loaded has no entry
|
|
643
|
+
// for it (the doc changed after it loaded): never answer with the family.
|
|
644
|
+
if (entry == null) {
|
|
645
|
+
throw new AstryxError(
|
|
646
|
+
`No component named "${dirName}": its family doc changed after this process loaded it.`,
|
|
647
|
+
undefined,
|
|
648
|
+
ERROR_CODES.ERR_UNKNOWN_COMPONENT,
|
|
649
|
+
);
|
|
650
|
+
}
|
|
651
|
+
// Built from the entry, as scopeSubComponent scopes Core's, so a member that
|
|
652
|
+
// shares the doc's own `name` is scoped too.
|
|
653
|
+
/** @type {LoadedComponentDoc & {parentDoc?: string, import?: string}} */
|
|
654
|
+
const scoped = {
|
|
655
|
+
name: dirName,
|
|
656
|
+
description: entry.description,
|
|
657
|
+
props: entry.props,
|
|
658
|
+
components: [entry],
|
|
659
|
+
// The name the family doc opens under, for every member.
|
|
660
|
+
parentDoc:
|
|
661
|
+
owner.integration && record.docPath
|
|
662
|
+
? recordedDocName(owner.integration, record.docPath)
|
|
663
|
+
: docs.name === dirName && record.docPath
|
|
664
|
+
? docStem(record.docPath)
|
|
665
|
+
: docs.name,
|
|
666
|
+
};
|
|
667
|
+
if (docs.usage) scoped.usage = docs.usage;
|
|
668
|
+
if (docs.theming) scoped.theming = docs.theming;
|
|
669
|
+
if (docs.import) scoped.import = docs.import;
|
|
670
|
+
return scoped;
|
|
671
|
+
}
|
|
@@ -19,9 +19,11 @@ import {
|
|
|
19
19
|
requireCoreDir,
|
|
20
20
|
loadIntegrationsSafely,
|
|
21
21
|
resolveOwners,
|
|
22
|
+
scopeIntegrationMember,
|
|
22
23
|
classifyScope,
|
|
23
24
|
assertUnambiguousOwners,
|
|
24
25
|
resolveLegacyExternalDoc,
|
|
26
|
+
legacyExternalKeeps,
|
|
25
27
|
resolveCoreSourcePath,
|
|
26
28
|
resolveUnscopedDoc,
|
|
27
29
|
loadComponentDoc,
|
|
@@ -29,6 +31,7 @@ import {
|
|
|
29
31
|
ComponentAmbiguityError,
|
|
30
32
|
installedComponentPackageVersion,
|
|
31
33
|
resolveComponentReplacement,
|
|
34
|
+
unscopedComponentOwners,
|
|
32
35
|
} from './_adapter.mjs';
|
|
33
36
|
import {componentList} from './list/list.mjs';
|
|
34
37
|
import {componentDetail} from './detail/detail.mjs';
|
|
@@ -427,7 +430,13 @@ export async function component(name, options = {}) {
|
|
|
427
430
|
if (blocks) {
|
|
428
431
|
return componentDetailBlocks(dirName, cwd, owner.package);
|
|
429
432
|
}
|
|
430
|
-
const
|
|
433
|
+
const loaded = await loadComponentDoc(owner.docPath, docOpts);
|
|
434
|
+
// A family member an integration lists under its own name reads as that
|
|
435
|
+
// member, the way a Core sub-component does below.
|
|
436
|
+
const docs =
|
|
437
|
+
scoped.kind === 'integration'
|
|
438
|
+
? scopeIntegrationMember(loaded, owner, dirName)
|
|
439
|
+
: loaded;
|
|
431
440
|
if (props) return componentDetailProps(docs, owner.package);
|
|
432
441
|
return componentDetail(docs, owner, dirName, coreDir);
|
|
433
442
|
}
|
|
@@ -481,12 +490,14 @@ export async function component(name, options = {}) {
|
|
|
481
490
|
});
|
|
482
491
|
}
|
|
483
492
|
|
|
493
|
+
// The owner rule runs first, over valid and invalid owners alike.
|
|
494
|
+
const ruled = unscopedComponentOwners(owners);
|
|
484
495
|
// Invalid integration metadata does not create ambiguity against a valid
|
|
485
|
-
// owner. Keep
|
|
496
|
+
// owner. Keep ruled owners only when no doc owner is valid, so an integration-
|
|
486
497
|
// only component still exposes its source and returns ERR_INVALID_DOC for
|
|
487
498
|
// detail instead of degrading to an unrelated unknown-component error.
|
|
488
499
|
const validOwners = [];
|
|
489
|
-
for (const owner of
|
|
500
|
+
for (const owner of ruled) {
|
|
490
501
|
if (owner.package === CORE_PACKAGE) {
|
|
491
502
|
validOwners.push(owner);
|
|
492
503
|
continue;
|
|
@@ -498,7 +509,12 @@ export async function component(name, options = {}) {
|
|
|
498
509
|
// Project/Doctor report invalid metadata; it is not an effective owner.
|
|
499
510
|
}
|
|
500
511
|
}
|
|
501
|
-
const
|
|
512
|
+
const loadable = validOwners.length > 0 ? validOwners : ruled;
|
|
513
|
+
// A legacy docs package's exact doc keeps its name over an export name a doc
|
|
514
|
+
// records, as Core and file-named owners do.
|
|
515
|
+
const effectiveOwners = legacyExternalKeeps(cwd, dirName, loadable)
|
|
516
|
+
? []
|
|
517
|
+
: loadable;
|
|
502
518
|
|
|
503
519
|
// ── Ambiguity: owned by MORE THAN ONE valid package, no --package ──
|
|
504
520
|
assertUnambiguousOwners(effectiveOwners, dirName);
|
|
@@ -516,7 +532,8 @@ export async function component(name, options = {}) {
|
|
|
516
532
|
// Integration components don't carry showcases — fail without scanning.
|
|
517
533
|
return componentDetailShowcase(dirName, {cwd, name, resolve: false, ownerPackage: owner.package});
|
|
518
534
|
}
|
|
519
|
-
const
|
|
535
|
+
const loaded = await loadComponentDoc(owner.docPath, docOpts);
|
|
536
|
+
const docs = scopeIntegrationMember(loaded, owner, dirName);
|
|
520
537
|
if (props) return componentDetailProps(docs, owner.package);
|
|
521
538
|
return componentDetail(docs, owner, dirName, coreDir);
|
|
522
539
|
}
|
|
@@ -13,6 +13,7 @@ import {describe, it, expect} from 'vitest';
|
|
|
13
13
|
import * as path from 'node:path';
|
|
14
14
|
import {fileURLToPath} from 'node:url';
|
|
15
15
|
import {component} from './component.mjs';
|
|
16
|
+
import {search} from '../search/search.mjs';
|
|
16
17
|
import {AstryxError} from '../error.mjs';
|
|
17
18
|
import {runCli} from '../../test-utils/run-cli.mjs';
|
|
18
19
|
|
|
@@ -92,6 +93,85 @@ describe('component dispatcher — detail levels on list', () => {
|
|
|
92
93
|
);
|
|
93
94
|
});
|
|
94
95
|
|
|
96
|
+
describe('component list — components whose docs live in a family folder', () => {
|
|
97
|
+
it('lists HStack, VStack and Heading at every detail level, each with its own import', async () => {
|
|
98
|
+
const {docs: stackDoc} = await import(
|
|
99
|
+
path.join(REPO, 'packages', 'core', 'src', 'Stack', 'Stack.doc.mjs')
|
|
100
|
+
);
|
|
101
|
+
const vstackMember = stackDoc.components.find(c => c.name === 'VStack');
|
|
102
|
+
|
|
103
|
+
const names = await component(undefined, {cwd, list: true});
|
|
104
|
+
const listed = Object.values(names.data.components).flat();
|
|
105
|
+
for (const name of ['HStack', 'VStack', 'Heading']) {
|
|
106
|
+
expect(listed).toContainEqual({name, package: '@astryxdesign/core'});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const compact = await component(undefined, {cwd, list: true, detail: 'compact'});
|
|
110
|
+
const brief = Object.values(compact.data.components).flat();
|
|
111
|
+
expect(brief.find(e => e.name === 'VStack')).toEqual({
|
|
112
|
+
name: 'VStack',
|
|
113
|
+
package: '@astryxdesign/core',
|
|
114
|
+
description: vstackMember.description,
|
|
115
|
+
import: '@astryxdesign/core/VStack',
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const full = await component(undefined, {cwd, list: true, detail: 'full'});
|
|
119
|
+
const entry = Object.values(full.data.components)
|
|
120
|
+
.flat()
|
|
121
|
+
.find(e => e.name === 'VStack');
|
|
122
|
+
// Shaped like every other full entry (a component doc plus its package):
|
|
123
|
+
// the member's own name, display name and summary, and no scoping field
|
|
124
|
+
// the full-entry type does not describe.
|
|
125
|
+
expect(entry).toEqual({
|
|
126
|
+
name: 'VStack',
|
|
127
|
+
package: '@astryxdesign/core',
|
|
128
|
+
displayName: vstackMember.displayName,
|
|
129
|
+
group: stackDoc.group,
|
|
130
|
+
category: stackDoc.category,
|
|
131
|
+
usage: {description: vstackMember.description},
|
|
132
|
+
props: vstackMember.props,
|
|
133
|
+
theming: stackDoc.theming,
|
|
134
|
+
import: '@astryxdesign/core/VStack',
|
|
135
|
+
});
|
|
136
|
+
}, SLOW);
|
|
137
|
+
|
|
138
|
+
it('prints each one\'s own import path in the list, the detail, and search', async () => {
|
|
139
|
+
// The path `component <Name>` prints is the one docs and examples teach:
|
|
140
|
+
// the component's own entry point, never its family's (/Stack, /Text) or
|
|
141
|
+
// a re-export (/Layout).
|
|
142
|
+
const compact = Object.values(
|
|
143
|
+
(await component(undefined, {cwd, list: true, detail: 'compact'})).data.components,
|
|
144
|
+
).flat();
|
|
145
|
+
const full = Object.values(
|
|
146
|
+
(await component(undefined, {cwd, list: true, detail: 'full'})).data.components,
|
|
147
|
+
).flat();
|
|
148
|
+
const textList = (await runCli(['component', '--list'], cwd)).stdout;
|
|
149
|
+
const textCompact = (
|
|
150
|
+
await runCli(['component', '--list', '--detail', 'compact'], cwd)
|
|
151
|
+
).stdout;
|
|
152
|
+
/** The `import:` line of a text record, found by its `name:` line. */
|
|
153
|
+
const textImport = (text, name) =>
|
|
154
|
+
new RegExp(`^name:\\s+${name}\\n(?:(?!name:).*\\n)*?import:\\s+(\\S+)`, 'm').exec(
|
|
155
|
+
text,
|
|
156
|
+
)?.[1];
|
|
157
|
+
for (const name of ['VStack', 'HStack', 'Heading']) {
|
|
158
|
+
const expected = `@astryxdesign/core/${name}`;
|
|
159
|
+
expect(compact.find(e => e.name === name)?.import).toBe(expected);
|
|
160
|
+
expect((await component(name, {cwd})).data.import).toBe(expected);
|
|
161
|
+
const hits = (await search(name, {cwd, type: 'component'})).data.results;
|
|
162
|
+
expect(hits.find(r => r.name === name)?.import).toBe(expected);
|
|
163
|
+
expect(textImport(textList, name)).toBe(expected);
|
|
164
|
+
expect(textImport(textCompact, name)).toBe(expected);
|
|
165
|
+
}
|
|
166
|
+
// The full level spreads a component's own doc, which states no import
|
|
167
|
+
// (Button's entry has none either); a member's entry is scoped to the
|
|
168
|
+
// member and states its own.
|
|
169
|
+
for (const name of ['VStack', 'HStack']) {
|
|
170
|
+
expect(full.find(e => e.name === name)?.import).toBe(`@astryxdesign/core/${name}`);
|
|
171
|
+
}
|
|
172
|
+
}, SLOW);
|
|
173
|
+
});
|
|
174
|
+
|
|
95
175
|
describe('component dispatcher — projection precedence (locked)', () => {
|
|
96
176
|
it(
|
|
97
177
|
'--props routes to component.detail.props',
|