@astryxdesign/cli 0.7.2-canary.fe2c655 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +119 -0
- package/README.md +175 -154
- package/api/build/_adapter.d.mts +8 -0
- package/api/build/_adapter.mjs +12 -1
- package/api/build/build.doc.mjs +4 -0
- package/api/build/help/help.mjs +1 -1
- package/api/build/kit/kit.mjs +3 -11
- package/api/component/_adapter.d.mts +72 -1
- package/api/component/_adapter.mjs +212 -18
- package/api/component/component.doc.mjs +6 -1
- package/api/component/component.mjs +82 -15
- package/api/component/component.test.mjs +80 -0
- package/api/component/doc-links.test.mjs +386 -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 +132 -12
- package/api/discover/_adapter.mjs +488 -27
- 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/detail/doc/doc.mjs +9 -1
- package/api/discover/discover.d.mts +11 -0
- package/api/discover/discover.doc.mjs +9 -7
- package/api/discover/discover.mjs +121 -19
- package/api/discover/discover.type.d.mts +20 -7
- package/api/discover/discover.type.mjs +17 -7
- package/api/discover/list/list.d.mts +4 -3
- package/api/discover/list/list.mjs +17 -10
- package/api/docs/_adapter.d.mts +74 -0
- package/api/docs/_adapter.mjs +553 -16
- package/api/docs/docs.doc.mjs +2 -1
- package/api/docs/docs.mjs +2 -1
- package/api/docs/docs.test.mjs +5 -2
- package/api/docs/integration-tree.test.mjs +22 -0
- package/api/docs/integrationDocs.test.mjs +124 -0
- package/api/docs/list/list.mjs +12 -2
- package/api/docs/reference-blocks.test.mjs +1 -3
- package/api/doctor/_adapter.d.mts +108 -0
- package/api/doctor/_adapter.mjs +223 -4
- package/api/doctor/doctor.d.mts +199 -0
- package/api/doctor/doctor.doc.mjs +3 -2
- package/api/doctor/doctor.mjs +530 -34
- package/api/doctor/doctor.test.mjs +180 -14
- package/api/doctor/release-checks.test.mjs +156 -0
- package/api/doctor/theme-checks.mjs +17 -4
- package/api/doctor/theme-checks.test.mjs +223 -7
- package/api/error.d.mts +10 -0
- package/api/error.mjs +25 -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/hook/_adapter.mjs +3 -11
- package/api/hook/hook.doc.mjs +4 -0
- package/api/hook/list/list.d.mts +1 -1
- package/api/index.d.mts +2 -0
- package/api/index.mjs +2 -0
- package/api/init/_adapter.d.mts +22 -0
- package/api/init/_adapter.mjs +59 -0
- package/api/init/init.d.mts +7 -5
- package/api/init/init.doc.mjs +28 -7
- package/api/init/init.mjs +28 -4
- package/api/init/init.type.d.mts +48 -3
- package/api/init/init.type.mjs +37 -3
- package/api/init/run/run.d.mts +1 -1
- package/api/init/run/run.mjs +17 -6
- package/api/init/user/user.d.mts +14 -0
- package/api/init/user/user.mjs +87 -0
- package/api/init/user/user.test.mjs +232 -0
- package/api/integration/_adapter.d.mts +45 -0
- package/api/integration/_adapter.mjs +112 -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 +110 -6
- package/api/integration/authoring-checks.test.mjs +808 -0
- package/api/integration/authoring-checks.type.d.mts +143 -0
- package/api/integration/authoring-checks.type.mjs +74 -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 +45 -6
- package/api/integration/integrationDocConflicts.doc.mjs +22 -5
- package/api/integration/pack-check.mjs +364 -120
- package/api/integration/pack-check.test.mjs +730 -10
- package/api/integration/validate-integration-fixes.test.mjs +67 -0
- package/api/integration/validate-integration.d.mts +8 -0
- package/api/integration/validate-integration.mjs +63 -9
- package/api/integration/validate-integration.test.mjs +88 -8
- package/api/integration/validate-integration.type.d.mts +16 -0
- package/api/integration/validate-integration.type.mjs +14 -1
- package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
- package/api/integration/validateIntegration.doc.mjs +19 -3
- package/api/search/_adapter.d.mts +11 -0
- package/api/search/_adapter.mjs +25 -0
- package/api/search/search.d.mts +82 -13
- package/api/search/search.doc.mjs +8 -3
- 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 +645 -64
- package/api/search/search.test.mjs +179 -1
- package/api/search/search.type.d.mts +14 -1
- package/api/search/search.type.mjs +6 -1
- package/api/swizzle/_adapter.mjs +2 -2
- package/api/swizzle/copy/copy.mjs +29 -15
- package/api/template/template-integration.test.mjs +1 -1
- package/api/template/template.test.mjs +120 -3
- package/api/theme/_adapter.d.mts +16 -0
- package/api/theme/_adapter.mjs +32 -5
- package/api/theme/build/build.d.mts +2 -1
- package/api/theme/build/build.family.test.mjs +64 -0
- package/api/theme/build/build.mjs +250 -38
- package/api/theme/build/build.packed-old-core.test.mjs +20 -3
- package/api/theme/build/font-warning.mjs +5 -3
- package/api/theme/build/font-warning.test.mjs +2 -1
- package/api/theme/remove/remove.test.mjs +2 -2
- package/api/theme/targets/targets.mjs +3 -10
- package/api/theme/themeBuild.doc.mjs +4 -4
- package/api/theme/themeTargets.doc.mjs +4 -0
- package/api/theme/use/use.test.mjs +1 -1
- package/api/upgrade/_adapter.d.mts +40 -2
- package/api/upgrade/_adapter.mjs +118 -5
- package/api/upgrade/run/cli-behind-core.test.mjs +438 -0
- package/api/upgrade/run/run.mjs +35 -2
- package/api/upgrade/status/status.d.mts +21 -5
- package/api/upgrade/status/status.mjs +45 -8
- package/api/upgrade/upgrade.doc.mjs +6 -3
- package/api/upgrade/upgrade.mjs +5 -1
- package/api/upgrade/upgrade.type.d.mts +23 -0
- package/api/upgrade/upgrade.type.mjs +16 -1
- package/assets/codemods/__tests__/registry.test.mjs +1 -0
- package/assets/codemods/registry.mjs +1 -0
- package/assets/codemods/runner.mjs +7 -1
- package/assets/codemods/transforms/v0.7.2/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +120 -0
- package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
- package/assets/codemods/transforms/v0.7.2/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/browser-support.doc.mjs +1 -1
- package/assets/docs/getting-started.doc.mjs +26 -6
- 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 +22 -2
- package/assets/docs/tree/add-a-theme.doc.mjs +13 -3
- package/assets/docs/tree/add-a-topic.doc.mjs +54 -9
- package/assets/docs/tree/agent-guidance.doc.mjs +19 -5
- 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/building-blocks.doc.mjs +4 -0
- package/assets/docs/tree/check-the-props.doc.mjs +201 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +69 -11
- package/assets/docs/tree/checks.doc.mjs +32 -24
- package/assets/docs/tree/ci-and-containers.doc.mjs +88 -0
- package/assets/docs/tree/cli-command.doc.mjs +142 -0
- package/assets/docs/tree/cli.doc.mjs +6 -0
- package/assets/docs/tree/codemods.doc.mjs +17 -7
- package/assets/docs/tree/commands.doc.mjs +7 -1
- package/assets/docs/tree/component-family.doc.mjs +8 -6
- package/assets/docs/tree/component-imports.doc.mjs +21 -3
- package/assets/docs/tree/components.doc.mjs +7 -1
- package/assets/docs/tree/computer-agent-guide.doc.mjs +160 -0
- package/assets/docs/tree/computer-integrations.doc.mjs +93 -0
- package/assets/docs/tree/configuration.doc.mjs +7 -3
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +41 -22
- package/assets/docs/tree/define-the-theme.doc.mjs +6 -5
- package/assets/docs/tree/describe-the-component.doc.mjs +3 -3
- package/assets/docs/tree/docs.doc.mjs +9 -3
- package/assets/docs/tree/document-the-template.doc.mjs +1 -1
- package/assets/docs/tree/document-the-theme.doc.mjs +3 -3
- package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
- package/assets/docs/tree/extend-or-replace.doc.mjs +19 -9
- package/assets/docs/tree/fonts-and-assets.doc.mjs +2 -2
- package/assets/docs/tree/generate-a-palette.doc.mjs +7 -5
- package/assets/docs/tree/global-integrations.doc.mjs +124 -0
- package/assets/docs/tree/global.doc.mjs +131 -0
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +5 -5
- package/assets/docs/tree/install-once.doc.mjs +105 -0
- package/assets/docs/tree/integrations.doc.mjs +13 -1
- 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 +7 -6
- 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/monorepos.doc.mjs +84 -0
- 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/problems.doc.mjs +205 -0
- package/assets/docs/tree/project-global-or-both.doc.mjs +131 -0
- package/assets/docs/tree/publishing.doc.mjs +6 -6
- package/assets/docs/tree/quick-start.doc.mjs +53 -27
- package/assets/docs/tree/reference.doc.mjs +192 -0
- package/assets/docs/tree/replace-a-core-component.doc.mjs +15 -7
- package/assets/docs/tree/replace-a-core-template.doc.mjs +10 -12
- package/assets/docs/tree/scaffold.doc.mjs +1 -1
- package/assets/docs/tree/sections-and-placement.doc.mjs +9 -11
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +17 -5
- package/assets/docs/tree/short-and-findable.doc.mjs +9 -8
- package/assets/docs/tree/single-component.doc.mjs +15 -6
- package/assets/docs/tree/start-a-template.doc.mjs +18 -8
- 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 +6 -17
- 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 +7 -1
- package/assets/docs/tree/test-in-an-app.doc.mjs +7 -7
- package/assets/docs/tree/test-template-in-app.doc.mjs +5 -5
- package/assets/docs/tree/themes.doc.mjs +4 -0
- package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
- package/assets/docs/tree/troubleshooting.doc.mjs +29 -13
- package/assets/docs/tree/type-scale.doc.mjs +3 -3
- package/assets/docs/tree/uninstall.doc.mjs +109 -0
- package/assets/docs/tree/updates.doc.mjs +92 -0
- package/assets/docs/tree/upgrading.doc.mjs +6 -6
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +14 -2
- package/assets/docs/tree/verify-packed-template.doc.mjs +3 -3
- package/assets/docs/tree/versioning.doc.mjs +10 -9
- package/assets/docs/tree/who-answers.doc.mjs +119 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +7 -6
- package/assets/docs/use-a-theme.doc.mjs +2 -2
- package/assets/docs/working-with-ai.doc.mjs +66 -13
- 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/debug/parse.d.mts +5 -5
- package/authoring/discover/discover.doc.mjs +7 -1
- package/authoring/doctypes/_schema.d.mts +8 -3
- package/authoring/doctypes/_schema.mjs +1 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
- package/authoring/doctypes/command/command.doc.mjs +20 -12
- package/authoring/doctypes/command/type.ts +14 -0
- package/authoring/doctypes/component/component.doc.mjs +30 -27
- package/authoring/doctypes/component/type.ts +21 -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/hook/type.ts +4 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
- package/authoring/doctypes/reference/reference.doc.mjs +12 -11
- 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 +2 -0
- package/authoring/integration/integration.doc.mjs +30 -6
- package/authoring/integration/parse.test.mjs +21 -0
- package/authoring/integration/schema.d.mts +16 -3
- package/authoring/integration/schema.mjs +34 -2
- package/authoring/integration/type.ts +12 -0
- package/clients/cli/bin/astryx.mjs +20 -3
- package/clients/cli/cli-command.test.mjs +166 -0
- package/clients/cli/commands/blog.doc.mjs +1 -0
- package/clients/cli/commands/build-theme.batch-report.test.mjs +17 -3
- package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
- package/clients/cli/commands/build-theme.mjs +26 -13
- 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/build.doc.mjs +1 -0
- package/clients/cli/commands/build.exit-codes-doc.test.mjs +4 -0
- package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
- package/clients/cli/commands/component.doc.mjs +1 -0
- package/clients/cli/commands/discover.broken-integration.test.mjs +11 -7
- package/clients/cli/commands/discover.doc.mjs +9 -1
- package/clients/cli/commands/discover.mjs +144 -93
- package/clients/cli/commands/discover.no-source.test.mjs +448 -33
- package/clients/cli/commands/discover.sources.test.mjs +20 -1
- package/clients/cli/commands/docs.doc.mjs +1 -0
- package/clients/cli/commands/docs.mjs +49 -19
- package/clients/cli/commands/docs.test.mjs +2 -2
- package/clients/cli/commands/doctor-integration-components.doc.mjs +19 -4
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +20 -5
- package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -0
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +22 -2
- package/clients/cli/commands/doctor-integration.test.mjs +888 -3
- package/clients/cli/commands/doctor.doc.mjs +12 -2
- package/clients/cli/commands/doctor.mjs +292 -7
- package/clients/cli/commands/doctor.test.mjs +10 -4
- package/clients/cli/commands/gap-report.doc.mjs +15 -2
- package/clients/cli/commands/gap-report.mjs +24 -2
- package/clients/cli/commands/gap-report.test.mjs +79 -0
- package/clients/cli/commands/hook.doc.mjs +1 -0
- package/clients/cli/commands/init.behavior.test.mjs +5 -0
- package/clients/cli/commands/init.doc.mjs +29 -3
- package/clients/cli/commands/integration-add.doc.mjs +7 -0
- package/clients/cli/commands/integration-authoring.test.mjs +49 -3
- package/clients/cli/commands/integration-check.doc.mjs +93 -0
- package/clients/cli/commands/integration-check.test.mjs +441 -0
- package/clients/cli/commands/integration-pack.doc.mjs +8 -1
- package/clients/cli/commands/integration-verify.doc.mjs +8 -1
- package/clients/cli/commands/integration.doc.mjs +6 -2
- package/clients/cli/commands/integration.mjs +119 -7
- package/clients/cli/commands/json-contract.test.mjs +11 -2
- package/clients/cli/commands/manifest.doc.mjs +1 -0
- package/clients/cli/commands/outside-project.test.mjs +774 -0
- package/clients/cli/commands/search.doc.mjs +1 -0
- package/clients/cli/commands/search.mjs +16 -11
- package/clients/cli/commands/search.test.mjs +429 -296
- package/clients/cli/commands/setup-nudge.test.mjs +102 -2
- package/clients/cli/commands/swizzle.doc.mjs +7 -0
- package/clients/cli/commands/swizzle.mjs +5 -3
- package/clients/cli/commands/swizzle.routing.test.mjs +19 -2
- package/clients/cli/commands/template.doc.mjs +1 -0
- package/clients/cli/commands/text-json-parity.test.mjs +5 -0
- package/clients/cli/commands/theme-add-lifecycle.test.mjs +3 -3
- package/clients/cli/commands/theme-add.doc.mjs +8 -1
- package/clients/cli/commands/theme-build.doc.mjs +3 -2
- package/clients/cli/commands/theme-eject.doc.mjs +1 -0
- package/clients/cli/commands/theme-list.behavior.test.mjs +6 -0
- package/clients/cli/commands/theme-list.doc.mjs +1 -0
- package/clients/cli/commands/theme-palette-generate.doc.mjs +1 -0
- package/clients/cli/commands/theme-remove.doc.mjs +7 -0
- package/clients/cli/commands/theme-targets.doc.mjs +1 -0
- package/clients/cli/commands/theme-template.doc.mjs +1 -0
- package/clients/cli/commands/theme-use.doc.mjs +7 -0
- package/clients/cli/commands/upgrade.config-ordering.test.mjs +2 -1
- package/clients/cli/commands/upgrade.doc.mjs +22 -1
- package/clients/cli/commands/upgrade.file-protection.test.mjs +3 -2
- package/clients/cli/commands/upgrade.hook-output.test.mjs +2 -1
- package/clients/cli/commands/upgrade.older-cli.test.mjs +160 -0
- package/clients/cli/index.mjs +112 -16
- package/clients/cli/lib/cli-error.mjs +4 -1
- package/clients/cli/lib/component-format.test.mjs +1 -1
- package/clients/cli/lib/define-command.mjs +2 -2
- package/clients/cli/lib/json-shim.mjs +3 -1
- package/clients/cli/lib/manifest.d.ts +9 -0
- package/clients/cli/lib/manifest.mjs +17 -1
- package/clients/cli/lib/manifest.test.mjs +25 -0
- package/foundation/agent-docs/agent-doc-state.d.mts +35 -6
- package/foundation/agent-docs/agent-doc-state.mjs +66 -6
- package/foundation/agent-docs/agent-docs.d.mts +4 -3
- package/foundation/agent-docs/agent-docs.mjs +11 -9
- package/foundation/agent-docs/computer-agent-text.d.mts +133 -0
- package/foundation/agent-docs/computer-agent-text.mjs +623 -0
- package/foundation/agent-docs/computer-agent-text.test.mjs +602 -0
- package/foundation/config/project.d.mts +35 -3
- package/foundation/config/project.mjs +226 -7
- package/foundation/config/project.test.mjs +66 -0
- package/foundation/config/theme-state.mjs +5 -4
- package/foundation/discovery/authoring-self-docs.mjs +2 -1
- package/foundation/discovery/cli-self-docs.mjs +20 -3
- package/foundation/discovery/cli-self-docs.test.mjs +3 -2
- 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 +20 -1
- package/foundation/discovery/component-replacement.test.mjs +40 -0
- package/foundation/discovery/copied-passages.d.mts +216 -0
- package/foundation/discovery/copied-passages.mjs +720 -0
- package/foundation/discovery/copied-passages.test.mjs +124 -0
- package/foundation/discovery/doc-consistency.d.mts +34 -0
- package/foundation/discovery/doc-consistency.mjs +513 -0
- package/foundation/discovery/doc-consistency.test.mjs +347 -0
- package/foundation/discovery/doc-fluff.d.mts +112 -0
- package/foundation/discovery/doc-fluff.mjs +328 -0
- package/foundation/discovery/doc-fluff.test.mjs +142 -0
- package/foundation/discovery/doc-types.d.mts +157 -0
- package/foundation/discovery/doc-types.mjs +1231 -0
- package/foundation/discovery/doc-types.test.mjs +744 -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 +297 -0
- package/foundation/discovery/prop-drift.mjs +2428 -0
- package/foundation/discovery/prop-drift.test.mjs +2337 -0
- package/foundation/discovery/runner-allowlist.d.mts +40 -0
- package/foundation/discovery/runner-allowlist.mjs +53 -0
- package/foundation/discovery/stray-pointers.d.mts +52 -0
- package/foundation/discovery/stray-pointers.mjs +293 -0
- package/foundation/discovery/stray-pointers.test.mjs +86 -0
- package/foundation/discovery/template-adapter.mjs +74 -5
- package/foundation/discovery/template-needs.mjs +5 -2
- package/foundation/discovery/theme-imports.mjs +8 -4
- package/foundation/discovery/theme-imports.test.mjs +1 -1
- 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 +51 -1
- package/foundation/doc-compiler/inputs.mjs +27 -1
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/doc-compiler/links.d.mts +41 -5
- package/foundation/doc-compiler/links.mjs +167 -28
- package/foundation/doc-compiler/links.test.mjs +97 -4
- package/foundation/doc-compiler/read.d.mts +1 -1
- package/foundation/doc-compiler/tree.mjs +30 -1
- package/foundation/doc-compiler/tree.test.mjs +8 -1
- package/foundation/env/cli-command.d.mts +83 -0
- package/foundation/env/cli-command.mjs +152 -0
- package/foundation/env/cli-command.test.mjs +129 -0
- package/foundation/env/node-version.test.mjs +15 -3
- package/foundation/env/package-manager.d.mts +93 -9
- package/foundation/env/package-manager.global.test.mjs +66 -0
- package/foundation/env/package-manager.mjs +184 -13
- package/foundation/env/package-manager.test.mjs +341 -15
- package/foundation/env/project-scope.d.mts +9 -0
- package/foundation/env/project-scope.mjs +33 -0
- package/foundation/env/search-path.d.mts +42 -0
- package/foundation/env/search-path.mjs +205 -0
- package/foundation/env/search-path.test.mjs +122 -0
- package/foundation/env/user-dirs.d.mts +39 -0
- package/foundation/env/user-dirs.mjs +93 -0
- package/foundation/env/user-dirs.test.mjs +72 -0
- package/foundation/env/user-settings.d.mts +46 -0
- package/foundation/env/user-settings.mjs +106 -0
- package/foundation/env/user-settings.test.mjs +64 -0
- package/foundation/fs/file-protection.mjs +15 -1
- package/foundation/fs/module-loader.d.mts +2 -1
- package/foundation/fs/module-loader.mjs +60 -4
- package/foundation/fs/module-loader.stdout.test.mjs +3 -2
- package/foundation/fs/module-loader.test.mjs +194 -0
- package/foundation/fs/path-compare.d.mts +33 -0
- package/foundation/fs/path-compare.mjs +73 -0
- package/foundation/fs/paths.d.mts +57 -1
- package/foundation/fs/paths.mjs +131 -3
- package/foundation/fs/paths.test.mjs +10 -1
- package/foundation/integrations/computer-integrations.d.mts +78 -0
- package/foundation/integrations/computer-integrations.mjs +316 -0
- package/foundation/integrations/computer-integrations.test.mjs +292 -0
- package/foundation/integrations/contribution-inventory.d.mts +11 -0
- package/foundation/integrations/contribution-inventory.mjs +56 -3
- package/foundation/integrations/integration-warnings.mjs +3 -2
- package/foundation/integrations/integration-warnings.test.mjs +8 -9
- package/foundation/integrations/integrations.d.mts +25 -1
- package/foundation/integrations/integrations.mjs +46 -3
- package/foundation/integrations/issue.ts +6 -0
- package/foundation/integrations/validate-contributions.d.mts +2 -0
- package/foundation/integrations/validate-contributions.mjs +41 -1
- package/foundation/release/agent-text-worker.d.mts +4 -0
- package/foundation/release/agent-text-worker.mjs +52 -0
- package/foundation/release/cache.d.mts +310 -0
- package/foundation/release/cache.mjs +1216 -0
- package/foundation/release/cache.test.mjs +920 -0
- package/foundation/release/choose.d.mts +207 -0
- package/foundation/release/choose.mjs +677 -0
- package/foundation/release/choose.test.mjs +427 -0
- package/foundation/release/core-worker.d.mts +4 -0
- package/foundation/release/core-worker.mjs +38 -0
- package/foundation/release/global-state.d.mts +259 -0
- package/foundation/release/global-state.mjs +472 -0
- package/foundation/release/global-state.test.mjs +381 -0
- package/foundation/release/handoff.d.mts +60 -0
- package/foundation/release/handoff.e2e.test.mjs +278 -0
- package/foundation/release/handoff.mjs +357 -0
- package/foundation/release/lock-lease.d.mts +23 -0
- package/foundation/release/lock-lease.mjs +80 -0
- package/foundation/release/notices.d.mts +253 -0
- package/foundation/release/notices.mjs +596 -0
- package/foundation/release/notices.test.mjs +565 -0
- package/foundation/release/npm-guard.d.mts +4 -0
- package/foundation/release/npm-guard.mjs +126 -0
- package/foundation/release/project.d.mts +141 -0
- package/foundation/release/project.mjs +466 -0
- package/foundation/release/project.test.mjs +288 -0
- package/foundation/release/refresh-worker.d.mts +4 -0
- package/foundation/release/refresh-worker.mjs +27 -0
- package/foundation/release/run-context.d.mts +47 -0
- package/foundation/release/run-context.mjs +149 -0
- package/foundation/release/update-notice-env.d.mts +28 -0
- package/foundation/release/update-notice-env.mjs +39 -0
- package/foundation/response/base.d.ts +26 -3
- package/foundation/response/error-codes.d.mts +3 -1
- package/foundation/response/error-codes.doc.mjs +12 -0
- package/foundation/response/error-codes.mjs +17 -0
- package/foundation/response/error-codes.test.mjs +2 -0
- package/foundation/response/json-contract.test.mjs +7 -2
- package/foundation/response/json.mjs +4 -1
- package/foundation/response/response-types.doc.mjs +22 -11
- package/foundation/response/response-types.doc.test.mjs +46 -0
- package/foundation/response/response.doc.mjs +3 -3
- package/foundation/xle/browser-imports.test.mjs +74 -0
- package/foundation/xle/registry.mjs +4 -0
- package/foundation/xle/registry.test.mjs +28 -0
- package/package.json +11 -11
- package/scripts/postinstall.mjs +24 -5
|
@@ -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,8 @@ import {
|
|
|
29
31
|
ComponentAmbiguityError,
|
|
30
32
|
installedComponentPackageVersion,
|
|
31
33
|
resolveComponentReplacement,
|
|
34
|
+
unscopedComponentOwners,
|
|
35
|
+
linkComponentResponse,
|
|
32
36
|
} from './_adapter.mjs';
|
|
33
37
|
import {componentList} from './list/list.mjs';
|
|
34
38
|
import {componentDetail} from './detail/detail.mjs';
|
|
@@ -254,6 +258,23 @@ async function componentBatch(selectors, options, coreDir) {
|
|
|
254
258
|
* )>}
|
|
255
259
|
*/
|
|
256
260
|
export async function component(name, options = {}) {
|
|
261
|
+
// Every read resolves the links in the doc text it returns (spec:AST-047
|
|
262
|
+
// FR9); a batch's results are each a read of their own.
|
|
263
|
+
return /** @type {any} */ (
|
|
264
|
+
await linkComponentResponse(
|
|
265
|
+
await componentRead(name, options),
|
|
266
|
+
options.cwd ?? process.cwd(),
|
|
267
|
+
)
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* {@link component}, with each `{@link}` in its doc text as written.
|
|
273
|
+
* @param {string|string[]} [name]
|
|
274
|
+
* @param {Parameters<typeof component>[1]} [options]
|
|
275
|
+
* @returns {ReturnType<typeof component>}
|
|
276
|
+
*/
|
|
277
|
+
async function componentRead(name, options = {}) {
|
|
257
278
|
const {
|
|
258
279
|
cwd = process.cwd(),
|
|
259
280
|
list = false,
|
|
@@ -354,7 +375,7 @@ export async function component(name, options = {}) {
|
|
|
354
375
|
requireInstalledSelectorVersion(target, coreDir, loadedIntegrations);
|
|
355
376
|
}
|
|
356
377
|
if (target.name !== name || target.package !== packageScope) {
|
|
357
|
-
return
|
|
378
|
+
return componentRead(target.name, {...options, package: target.package});
|
|
358
379
|
}
|
|
359
380
|
name = target.name;
|
|
360
381
|
}
|
|
@@ -393,7 +414,10 @@ export async function component(name, options = {}) {
|
|
|
393
414
|
dirName,
|
|
394
415
|
);
|
|
395
416
|
if (replacement?.package === packageScope) {
|
|
396
|
-
return
|
|
417
|
+
return componentRead(replacement.name, {
|
|
418
|
+
...options,
|
|
419
|
+
package: packageScope,
|
|
420
|
+
});
|
|
397
421
|
}
|
|
398
422
|
}
|
|
399
423
|
const scoped = classifyScope(packageScope, {
|
|
@@ -421,20 +445,40 @@ export async function component(name, options = {}) {
|
|
|
421
445
|
// a showcase, so skip discovery entirely.
|
|
422
446
|
if (showcase) {
|
|
423
447
|
return scoped.kind === 'core'
|
|
424
|
-
? componentDetailShowcase(dirName, {
|
|
425
|
-
|
|
448
|
+
? componentDetailShowcase(dirName, {
|
|
449
|
+
cwd,
|
|
450
|
+
name,
|
|
451
|
+
ownerPackage: owner.package,
|
|
452
|
+
})
|
|
453
|
+
: componentDetailShowcase(dirName, {
|
|
454
|
+
cwd,
|
|
455
|
+
name,
|
|
456
|
+
resolve: false,
|
|
457
|
+
ownerPackage: owner.package,
|
|
458
|
+
});
|
|
426
459
|
}
|
|
427
460
|
if (blocks) {
|
|
428
461
|
return componentDetailBlocks(dirName, cwd, owner.package);
|
|
429
462
|
}
|
|
430
|
-
const
|
|
463
|
+
const loaded = await loadComponentDoc(owner.docPath, docOpts);
|
|
464
|
+
// A family member an integration lists under its own name reads as that
|
|
465
|
+
// member, the way a Core sub-component does below.
|
|
466
|
+
const docs =
|
|
467
|
+
scoped.kind === 'integration'
|
|
468
|
+
? scopeIntegrationMember(loaded, owner, dirName)
|
|
469
|
+
: loaded;
|
|
431
470
|
if (props) return componentDetailProps(docs, owner.package);
|
|
432
471
|
return componentDetail(docs, owner, dirName, coreDir);
|
|
433
472
|
}
|
|
434
473
|
|
|
435
474
|
// Legacy `pkg.astryx.docs` external package.
|
|
436
475
|
if (showcase) {
|
|
437
|
-
return componentDetailShowcase(dirName, {
|
|
476
|
+
return componentDetailShowcase(dirName, {
|
|
477
|
+
cwd,
|
|
478
|
+
name,
|
|
479
|
+
packageScope,
|
|
480
|
+
ownerPackage: packageScope,
|
|
481
|
+
});
|
|
438
482
|
}
|
|
439
483
|
const extDocPath = resolveLegacyExternalDoc(scoped.ext, dirName);
|
|
440
484
|
if (extDocPath) {
|
|
@@ -475,18 +519,20 @@ export async function component(name, options = {}) {
|
|
|
475
519
|
dirName,
|
|
476
520
|
);
|
|
477
521
|
if (replacement) {
|
|
478
|
-
return
|
|
522
|
+
return componentRead(replacement.name, {
|
|
479
523
|
...options,
|
|
480
524
|
package: replacement.package,
|
|
481
525
|
});
|
|
482
526
|
}
|
|
483
527
|
|
|
528
|
+
// The owner rule runs first, over valid and invalid owners alike.
|
|
529
|
+
const ruled = unscopedComponentOwners(owners);
|
|
484
530
|
// Invalid integration metadata does not create ambiguity against a valid
|
|
485
|
-
// owner. Keep
|
|
531
|
+
// owner. Keep ruled owners only when no doc owner is valid, so an integration-
|
|
486
532
|
// only component still exposes its source and returns ERR_INVALID_DOC for
|
|
487
533
|
// detail instead of degrading to an unrelated unknown-component error.
|
|
488
534
|
const validOwners = [];
|
|
489
|
-
for (const owner of
|
|
535
|
+
for (const owner of ruled) {
|
|
490
536
|
if (owner.package === CORE_PACKAGE) {
|
|
491
537
|
validOwners.push(owner);
|
|
492
538
|
continue;
|
|
@@ -498,7 +544,12 @@ export async function component(name, options = {}) {
|
|
|
498
544
|
// Project/Doctor report invalid metadata; it is not an effective owner.
|
|
499
545
|
}
|
|
500
546
|
}
|
|
501
|
-
const
|
|
547
|
+
const loadable = validOwners.length > 0 ? validOwners : ruled;
|
|
548
|
+
// A legacy docs package's exact doc keeps its name over an export name a doc
|
|
549
|
+
// records, as Core and file-named owners do.
|
|
550
|
+
const effectiveOwners = legacyExternalKeeps(cwd, dirName, loadable)
|
|
551
|
+
? []
|
|
552
|
+
: loadable;
|
|
502
553
|
|
|
503
554
|
// ── Ambiguity: owned by MORE THAN ONE valid package, no --package ──
|
|
504
555
|
assertUnambiguousOwners(effectiveOwners, dirName);
|
|
@@ -510,13 +561,22 @@ export async function component(name, options = {}) {
|
|
|
510
561
|
) {
|
|
511
562
|
const owner = effectiveOwners[0];
|
|
512
563
|
if (source) {
|
|
513
|
-
return componentDetailSource(dirName, owner.sourcePath, {
|
|
564
|
+
return componentDetailSource(dirName, owner.sourcePath, {
|
|
565
|
+
name,
|
|
566
|
+
ownerPackage: owner.package,
|
|
567
|
+
});
|
|
514
568
|
}
|
|
515
569
|
if (showcase) {
|
|
516
570
|
// Integration components don't carry showcases — fail without scanning.
|
|
517
|
-
return componentDetailShowcase(dirName, {
|
|
571
|
+
return componentDetailShowcase(dirName, {
|
|
572
|
+
cwd,
|
|
573
|
+
name,
|
|
574
|
+
resolve: false,
|
|
575
|
+
ownerPackage: owner.package,
|
|
576
|
+
});
|
|
518
577
|
}
|
|
519
|
-
const
|
|
578
|
+
const loaded = await loadComponentDoc(owner.docPath, docOpts);
|
|
579
|
+
const docs = scopeIntegrationMember(loaded, owner, dirName);
|
|
520
580
|
if (props) return componentDetailProps(docs, owner.package);
|
|
521
581
|
return componentDetail(docs, owner, dirName, coreDir);
|
|
522
582
|
}
|
|
@@ -531,7 +591,11 @@ export async function component(name, options = {}) {
|
|
|
531
591
|
);
|
|
532
592
|
}
|
|
533
593
|
if (showcase) {
|
|
534
|
-
return componentDetailShowcase(dirName, {
|
|
594
|
+
return componentDetailShowcase(dirName, {
|
|
595
|
+
cwd,
|
|
596
|
+
name,
|
|
597
|
+
ownerPackage: CORE_PACKAGE,
|
|
598
|
+
});
|
|
535
599
|
}
|
|
536
600
|
|
|
537
601
|
const resolved = await resolveUnscopedDoc(dirName, {coreDir, cwd, name});
|
|
@@ -548,7 +612,10 @@ export async function component(name, options = {}) {
|
|
|
548
612
|
const sub = scopeSubComponent(docs, dirName, coreDir);
|
|
549
613
|
if (sub) {
|
|
550
614
|
if (props)
|
|
551
|
-
return componentDetailProps(
|
|
615
|
+
return componentDetailProps(
|
|
616
|
+
{props: sub.matchingComponent.props},
|
|
617
|
+
resolved.resolvedOwnerPackage,
|
|
618
|
+
);
|
|
552
619
|
return componentDetail(
|
|
553
620
|
sub.scoped,
|
|
554
621
|
{
|
|
@@ -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',
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Links in a component doc's text and a topic's description
|
|
5
|
+
* (spec:AST-047 FR9): a read resolves each `{@link <target>}` to the command
|
|
6
|
+
* that opens its doc, in text and JSON, the way a topic section's links read.
|
|
7
|
+
* Code fields and code ticks show the syntax as written.
|
|
8
|
+
*
|
|
9
|
+
* Fixtures live under a repo-local temp dir, not /tmp, because Vite refuses to
|
|
10
|
+
* dynamically import a module from outside the project root.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
import {afterEach, beforeEach, describe, expect, it} from 'vitest';
|
|
16
|
+
import {component} from './component.mjs';
|
|
17
|
+
import {CORE_PACKAGE, linkComponentResponse} from './_adapter.mjs';
|
|
18
|
+
import {docs} from '../docs/docs.mjs';
|
|
19
|
+
import {search} from '../search/search.mjs';
|
|
20
|
+
import {runCli} from '../../test-utils/run-cli.mjs';
|
|
21
|
+
|
|
22
|
+
const SLOW = 60_000;
|
|
23
|
+
|
|
24
|
+
let tmpDir;
|
|
25
|
+
|
|
26
|
+
const ACME_BUTTON = {
|
|
27
|
+
type: 'component',
|
|
28
|
+
name: 'AcmeButton',
|
|
29
|
+
displayName: 'Acme Button',
|
|
30
|
+
usage: {
|
|
31
|
+
description:
|
|
32
|
+
'A button. Set it up as {@link generic:acme-setup} says; theme it with {@link @astryxdesign/cli:generic:theme}.',
|
|
33
|
+
bestPractices: [
|
|
34
|
+
{
|
|
35
|
+
guidance: true,
|
|
36
|
+
description: 'Pair it with {@link component:AcmeButton}.',
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
props: [
|
|
41
|
+
{
|
|
42
|
+
name: 'tone',
|
|
43
|
+
type: 'string',
|
|
44
|
+
description:
|
|
45
|
+
'Read {@link generic:acme-setup}; write `{@link generic:acme-setup}` to link.',
|
|
46
|
+
default: "'{@link generic:acme-setup}'",
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
examples: [
|
|
50
|
+
{
|
|
51
|
+
label: 'As {@link generic:acme-setup} shows',
|
|
52
|
+
code: '// {@link generic:acme-setup}',
|
|
53
|
+
},
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const ACME_SETUP = {
|
|
58
|
+
type: 'generic',
|
|
59
|
+
name: 'acme-setup',
|
|
60
|
+
title: 'Acme setup',
|
|
61
|
+
description:
|
|
62
|
+
'Set up Acme, then theme it as {@link @astryxdesign/cli:generic:theme} says.',
|
|
63
|
+
sections: [
|
|
64
|
+
{title: 'Overview', content: [{type: 'prose', text: 'Install it.'}]},
|
|
65
|
+
],
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
function scaffold() {
|
|
69
|
+
fs.writeFileSync(
|
|
70
|
+
path.join(tmpDir, 'package.json'),
|
|
71
|
+
JSON.stringify({name: 'consumer'}),
|
|
72
|
+
);
|
|
73
|
+
fs.writeFileSync(
|
|
74
|
+
path.join(tmpDir, 'astryx.config.mjs'),
|
|
75
|
+
"export default {integrations: ['@acme/widgets']};\n",
|
|
76
|
+
);
|
|
77
|
+
const pkgDir = path.join(tmpDir, 'node_modules', '@acme', 'widgets');
|
|
78
|
+
fs.mkdirSync(path.join(pkgDir, 'components'), {recursive: true});
|
|
79
|
+
fs.mkdirSync(path.join(pkgDir, 'docs'), {recursive: true});
|
|
80
|
+
fs.writeFileSync(
|
|
81
|
+
path.join(pkgDir, 'package.json'),
|
|
82
|
+
JSON.stringify({name: '@acme/widgets', version: '1.0.0'}),
|
|
83
|
+
);
|
|
84
|
+
fs.writeFileSync(
|
|
85
|
+
path.join(pkgDir, 'astryx.integration.mjs'),
|
|
86
|
+
"export default {components: './components', docs: './docs'};\n",
|
|
87
|
+
);
|
|
88
|
+
fs.writeFileSync(
|
|
89
|
+
path.join(pkgDir, 'components', 'AcmeButton.doc.mjs'),
|
|
90
|
+
`export default ${JSON.stringify(ACME_BUTTON, null, 2)};\n`,
|
|
91
|
+
);
|
|
92
|
+
fs.writeFileSync(
|
|
93
|
+
path.join(pkgDir, 'components', 'AcmeButton.tsx'),
|
|
94
|
+
'export function AcmeButton() { return null; }\n',
|
|
95
|
+
);
|
|
96
|
+
fs.writeFileSync(
|
|
97
|
+
path.join(pkgDir, 'docs', 'acme-setup.doc.mjs'),
|
|
98
|
+
`export default ${JSON.stringify(ACME_SETUP, null, 2)};\n`,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
beforeEach(() => {
|
|
103
|
+
tmpDir = fs.mkdtempSync(path.join(process.cwd(), '.astryx-component-links-'));
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
afterEach(() => {
|
|
107
|
+
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe("a link in a component doc's text", () => {
|
|
111
|
+
it(
|
|
112
|
+
"reads as the command that opens its doc, against the integration's own docs",
|
|
113
|
+
async () => {
|
|
114
|
+
scaffold();
|
|
115
|
+
const read = /** @type {any} */ (
|
|
116
|
+
await component('AcmeButton', {cwd: tmpDir})
|
|
117
|
+
);
|
|
118
|
+
expect(read.type).toBe('component.detail');
|
|
119
|
+
expect(read.data.usage.description).toBe(
|
|
120
|
+
'A button. Set it up as `astryx docs acme-setup` says; theme it with `astryx docs theme`.',
|
|
121
|
+
);
|
|
122
|
+
expect(read.data.usage.bestPractices[0].description).toBe(
|
|
123
|
+
'Pair it with `astryx component AcmeButton --package @acme/widgets`.',
|
|
124
|
+
);
|
|
125
|
+
// Code ticks and code fields show the syntax as written.
|
|
126
|
+
expect(read.data.props[0].description).toBe(
|
|
127
|
+
'Read `astryx docs acme-setup`; write `{@link generic:acme-setup}` to link.',
|
|
128
|
+
);
|
|
129
|
+
expect(read.data.props[0].default).toBe("'{@link generic:acme-setup}'");
|
|
130
|
+
expect(read.data.examples[0]).toEqual({
|
|
131
|
+
label: 'As `astryx docs acme-setup` shows',
|
|
132
|
+
code: '// {@link generic:acme-setup}',
|
|
133
|
+
});
|
|
134
|
+
},
|
|
135
|
+
SLOW,
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
it(
|
|
139
|
+
'reads the same in `astryx discover <package>/<Component>`',
|
|
140
|
+
async () => {
|
|
141
|
+
scaffold();
|
|
142
|
+
const json = await runCli(
|
|
143
|
+
['--json', 'discover', '@acme/widgets/AcmeButton'],
|
|
144
|
+
tmpDir,
|
|
145
|
+
);
|
|
146
|
+
expect(json.status).toBe(0);
|
|
147
|
+
expect(JSON.parse(json.stdout).data.usage.description).toBe(
|
|
148
|
+
'A button. Set it up as `astryx docs acme-setup` says; theme it with `astryx docs theme`.',
|
|
149
|
+
);
|
|
150
|
+
},
|
|
151
|
+
SLOW,
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
it(
|
|
155
|
+
"reads the same in a search hit's description",
|
|
156
|
+
async () => {
|
|
157
|
+
scaffold();
|
|
158
|
+
const found = /** @type {any} */ (
|
|
159
|
+
await search('AcmeButton', {cwd: tmpDir, type: 'component'})
|
|
160
|
+
);
|
|
161
|
+
const hit = found.data.results.find(
|
|
162
|
+
(/** @type {any} */ result) => result.name === 'AcmeButton',
|
|
163
|
+
);
|
|
164
|
+
expect(hit.description).toBe(
|
|
165
|
+
'A button. Set it up as `astryx docs acme-setup` says; theme it with `astryx docs theme`.',
|
|
166
|
+
);
|
|
167
|
+
},
|
|
168
|
+
SLOW,
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
it(
|
|
172
|
+
'reads the same in the props projection, in JSON, and in text',
|
|
173
|
+
async () => {
|
|
174
|
+
scaffold();
|
|
175
|
+
const props = /** @type {any} */ (
|
|
176
|
+
await component('AcmeButton', {cwd: tmpDir, props: true})
|
|
177
|
+
);
|
|
178
|
+
expect(props.data[0].description).toBe(
|
|
179
|
+
'Read `astryx docs acme-setup`; write `{@link generic:acme-setup}` to link.',
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
const json = await runCli(['--json', 'component', 'AcmeButton'], tmpDir);
|
|
183
|
+
expect(json.status).toBe(0);
|
|
184
|
+
expect(JSON.parse(json.stdout).data.usage.description).toContain(
|
|
185
|
+
'`astryx docs acme-setup`',
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const text = await runCli(['component', 'AcmeButton'], tmpDir);
|
|
189
|
+
expect(text.status).toBe(0);
|
|
190
|
+
expect(text.stdout).toContain('`astryx docs acme-setup`');
|
|
191
|
+
expect(text.stdout).not.toContain('{@link generic:acme-setup} says');
|
|
192
|
+
},
|
|
193
|
+
SLOW,
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
it("resolves a Core component's links against the CLI's own docs", async () => {
|
|
197
|
+
const read = await linkComponentResponse(
|
|
198
|
+
{
|
|
199
|
+
type: 'component.detail',
|
|
200
|
+
package: CORE_PACKAGE,
|
|
201
|
+
data: {
|
|
202
|
+
usage: {description: 'Theme it with {@link generic:theme}.'},
|
|
203
|
+
props: [
|
|
204
|
+
{
|
|
205
|
+
name: 'x',
|
|
206
|
+
type: 'string',
|
|
207
|
+
description: 'See {@link generic:nope}.',
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
tmpDir,
|
|
213
|
+
);
|
|
214
|
+
expect(read.data.usage.description).toBe(
|
|
215
|
+
'Theme it with `astryx docs theme`.',
|
|
216
|
+
);
|
|
217
|
+
// A link that names no doc prints as written.
|
|
218
|
+
expect(read.data.props[0].description).toBe('See {@link generic:nope}.');
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe("a link in a topic's description", () => {
|
|
223
|
+
it(
|
|
224
|
+
'reads as the command that opens its doc, in the detail and the list',
|
|
225
|
+
async () => {
|
|
226
|
+
scaffold();
|
|
227
|
+
const detail = /** @type {any} */ (
|
|
228
|
+
await docs('acme-setup', undefined, {cwd: tmpDir, full: true})
|
|
229
|
+
);
|
|
230
|
+
expect(detail.data.description).toBe(
|
|
231
|
+
'Set up Acme, then theme it as `astryx docs theme` says.',
|
|
232
|
+
);
|
|
233
|
+
const listed = /** @type {any} */ (
|
|
234
|
+
await docs(undefined, undefined, {cwd: tmpDir})
|
|
235
|
+
);
|
|
236
|
+
expect(
|
|
237
|
+
listed.data.find((/** @type {any} */ t) => t.topic === 'acme-setup')
|
|
238
|
+
.description,
|
|
239
|
+
).toBe('Set up Acme, then theme it as `astryx docs theme` says.');
|
|
240
|
+
},
|
|
241
|
+
SLOW,
|
|
242
|
+
);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
describe("a link in a guide's description, as the docs tree shows it", () => {
|
|
246
|
+
it(
|
|
247
|
+
'reads as the command that opens its doc in the guide and its namespace',
|
|
248
|
+
async () => {
|
|
249
|
+
const expected =
|
|
250
|
+
'Document a theme by extending the core theme topic, so an app reads it in `astryx docs theme`.';
|
|
251
|
+
const guide = /** @type {any} */ (
|
|
252
|
+
await docs(
|
|
253
|
+
'cli/integrations/building-blocks/themes/document-the-theme',
|
|
254
|
+
undefined,
|
|
255
|
+
{cwd: tmpDir, full: true},
|
|
256
|
+
)
|
|
257
|
+
);
|
|
258
|
+
expect(guide.data.description).toBe(expected);
|
|
259
|
+
const namespace = /** @type {any} */ (
|
|
260
|
+
await docs('cli/integrations/building-blocks/themes', undefined, {
|
|
261
|
+
cwd: tmpDir,
|
|
262
|
+
})
|
|
263
|
+
);
|
|
264
|
+
const child = namespace.data.slots
|
|
265
|
+
.flatMap((/** @type {any} */ slot) => slot.children)
|
|
266
|
+
.find((/** @type {any} */ each) => each.name === 'document-the-theme');
|
|
267
|
+
expect(child.summary).toBe(expected);
|
|
268
|
+
},
|
|
269
|
+
SLOW,
|
|
270
|
+
);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
describe("a reference block's summary of another package's component", () => {
|
|
274
|
+
it(
|
|
275
|
+
"resolves the summary's links against the component's own package",
|
|
276
|
+
async () => {
|
|
277
|
+
const write = (
|
|
278
|
+
/** @type {string} */ file,
|
|
279
|
+
/** @type {string} */ text,
|
|
280
|
+
) => {
|
|
281
|
+
fs.mkdirSync(path.dirname(path.join(tmpDir, file)), {recursive: true});
|
|
282
|
+
fs.writeFileSync(path.join(tmpDir, file), text);
|
|
283
|
+
};
|
|
284
|
+
const doc = (/** @type {object} */ value) =>
|
|
285
|
+
`export default ${JSON.stringify(value)};\n`;
|
|
286
|
+
write('package.json', JSON.stringify({name: 'consumer'}));
|
|
287
|
+
write(
|
|
288
|
+
'astryx.config.mjs',
|
|
289
|
+
"export default {integrations: ['@acme/widgets', '@acme/other']};\n",
|
|
290
|
+
);
|
|
291
|
+
const widgets = 'node_modules/@acme/widgets';
|
|
292
|
+
write(
|
|
293
|
+
`${widgets}/package.json`,
|
|
294
|
+
JSON.stringify({name: '@acme/widgets', version: '1.0.0'}),
|
|
295
|
+
);
|
|
296
|
+
write(
|
|
297
|
+
`${widgets}/astryx.integration.mjs`,
|
|
298
|
+
"export default {docs: './docs'};\n",
|
|
299
|
+
);
|
|
300
|
+
write(
|
|
301
|
+
`${widgets}/docs/acme-ref.doc.mjs`,
|
|
302
|
+
doc({
|
|
303
|
+
type: 'generic',
|
|
304
|
+
name: 'acme-ref',
|
|
305
|
+
title: 'Acme ref',
|
|
306
|
+
description: 'Where the card is documented.',
|
|
307
|
+
sections: [
|
|
308
|
+
{
|
|
309
|
+
title: 'Overview',
|
|
310
|
+
content: [
|
|
311
|
+
{
|
|
312
|
+
type: 'reference',
|
|
313
|
+
target: '@acme/other:component:OtherCardBody',
|
|
314
|
+
},
|
|
315
|
+
],
|
|
316
|
+
},
|
|
317
|
+
],
|
|
318
|
+
}),
|
|
319
|
+
);
|
|
320
|
+
const other = 'node_modules/@acme/other';
|
|
321
|
+
write(
|
|
322
|
+
`${other}/package.json`,
|
|
323
|
+
JSON.stringify({name: '@acme/other', version: '1.0.0'}),
|
|
324
|
+
);
|
|
325
|
+
write(
|
|
326
|
+
`${other}/astryx.integration.mjs`,
|
|
327
|
+
"export default {components: './components', docs: './docs'};\n",
|
|
328
|
+
);
|
|
329
|
+
write(
|
|
330
|
+
`${other}/docs/other-setup.doc.mjs`,
|
|
331
|
+
doc({
|
|
332
|
+
type: 'generic',
|
|
333
|
+
name: 'other-setup',
|
|
334
|
+
title: 'Other setup',
|
|
335
|
+
description: 'Set up Other.',
|
|
336
|
+
sections: [
|
|
337
|
+
{
|
|
338
|
+
title: 'Overview',
|
|
339
|
+
content: [{type: 'prose', text: 'Install it.'}],
|
|
340
|
+
},
|
|
341
|
+
],
|
|
342
|
+
}),
|
|
343
|
+
);
|
|
344
|
+
write(
|
|
345
|
+
`${other}/components/OtherCard.doc.mjs`,
|
|
346
|
+
doc({
|
|
347
|
+
type: 'component',
|
|
348
|
+
name: 'OtherCard',
|
|
349
|
+
displayName: 'Other Card',
|
|
350
|
+
usage: {description: 'A card.'},
|
|
351
|
+
props: [],
|
|
352
|
+
}),
|
|
353
|
+
);
|
|
354
|
+
write(
|
|
355
|
+
`${other}/components/OtherCard.tsx`,
|
|
356
|
+
'export function OtherCard() { return null; }\n',
|
|
357
|
+
);
|
|
358
|
+
write(
|
|
359
|
+
`${other}/components/OtherCardBody.doc.mjs`,
|
|
360
|
+
doc({
|
|
361
|
+
type: 'component',
|
|
362
|
+
name: 'OtherCardBody',
|
|
363
|
+
displayName: 'Other Card Body',
|
|
364
|
+
subComponentOf: 'OtherCard',
|
|
365
|
+
description: 'Its body, set up as {@link generic:other-setup} says.',
|
|
366
|
+
props: [],
|
|
367
|
+
}),
|
|
368
|
+
);
|
|
369
|
+
write(
|
|
370
|
+
`${other}/components/OtherCardBody.tsx`,
|
|
371
|
+
'export function OtherCardBody() { return null; }\n',
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
const read = /** @type {any} */ (
|
|
375
|
+
await docs('acme-ref', undefined, {cwd: tmpDir, full: true})
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
// `other-setup` is @acme/other's topic: from @acme/widgets, the
|
|
379
|
+
// linking package, the same link names no doc.
|
|
380
|
+
expect(read.data.sections[0].content[0].text).toContain(
|
|
381
|
+
'Its body, set up as `astryx docs other-setup` says.',
|
|
382
|
+
);
|
|
383
|
+
},
|
|
384
|
+
SLOW,
|
|
385
|
+
);
|
|
386
|
+
});
|