@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
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
tokenizeQuery,
|
|
37
37
|
SEARCH_DOMAINS,
|
|
38
38
|
} from './search.mjs';
|
|
39
|
+
import {linkThisCliAsProjectCli} from '../../test-utils/release-fixtures.mjs';
|
|
39
40
|
|
|
40
41
|
const REPO = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../..');
|
|
41
42
|
const cwd = REPO;
|
|
@@ -470,8 +471,10 @@ describe('search leaf — error paths (pinned)', () => {
|
|
|
470
471
|
|
|
471
472
|
it('searches the docs without @astryxdesign/core, and throws for a domain that needs it', async () => {
|
|
472
473
|
const empty = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-search-no-core-'));
|
|
474
|
+
// A project whose own CLI answers, with no Core installed.
|
|
475
|
+
linkThisCliAsProjectCli(empty);
|
|
473
476
|
try {
|
|
474
|
-
// An open search
|
|
477
|
+
// An open search without Core covers the docs, as `astryx docs` does.
|
|
475
478
|
const open = await search('make an integration', {cwd: empty});
|
|
476
479
|
expect(open.data.results.length).toBeGreaterThan(0);
|
|
477
480
|
expect(new Set(open.data.results.map(r => r.domain))).toEqual(
|
|
@@ -616,6 +619,42 @@ describe('search leaf — a theme is found by its names; its description is pros
|
|
|
616
619
|
);
|
|
617
620
|
});
|
|
618
621
|
|
|
622
|
+
describe('search leaf — components whose docs live in a family folder', () => {
|
|
623
|
+
it("indexes a family member from its own entry, not the family's keywords", async () => {
|
|
624
|
+
// HStack and VStack are documented in Stack's doc, whose keywords
|
|
625
|
+
// (horizontal, vertical, row, column, ...) describe Stack.
|
|
626
|
+
const reasons = async (/** @type {string} */ query) =>
|
|
627
|
+
Object.fromEntries(
|
|
628
|
+
(await search(query, {cwd, type: 'component'})).data.results.map(r => [
|
|
629
|
+
r.name,
|
|
630
|
+
r.reason,
|
|
631
|
+
]),
|
|
632
|
+
);
|
|
633
|
+
const column = await reasons('column');
|
|
634
|
+
expect(column.HStack ?? '').not.toMatch(/keyword/);
|
|
635
|
+
expect(column.VStack ?? '').not.toMatch(/keyword/);
|
|
636
|
+
expect(column.Stack).toMatch(/keyword/);
|
|
637
|
+
const vertical = (await search('vertical', {cwd, type: 'component'})).data.results.map(
|
|
638
|
+
r => r.name,
|
|
639
|
+
);
|
|
640
|
+
expect(vertical.indexOf('VStack')).toBeGreaterThanOrEqual(0);
|
|
641
|
+
if (vertical.includes('HStack')) {
|
|
642
|
+
expect(vertical.indexOf('VStack')).toBeLessThan(vertical.indexOf('HStack'));
|
|
643
|
+
}
|
|
644
|
+
}, SLOW);
|
|
645
|
+
|
|
646
|
+
it('ranks VStack, HStack and Heading first for their own names, with their own import', async () => {
|
|
647
|
+
for (const name of ['VStack', 'HStack', 'Heading']) {
|
|
648
|
+
const r = await search(name.toLowerCase(), {cwd, type: 'component'});
|
|
649
|
+
expect(r.data.results[0]).toMatchObject({
|
|
650
|
+
domain: 'component',
|
|
651
|
+
name,
|
|
652
|
+
import: `@astryxdesign/core/${name}`,
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
}, SLOW);
|
|
656
|
+
});
|
|
657
|
+
|
|
619
658
|
describe('search leaf — integration components', () => {
|
|
620
659
|
/**
|
|
621
660
|
* A minimal consumer project: a stub `@astryxdesign/core` (so `findCoreDir`
|
|
@@ -827,3 +866,142 @@ describe('search — usage guidance is indexed, a tier below description', () =>
|
|
|
827
866
|
expect(hit?.score).toBe(45);
|
|
828
867
|
});
|
|
829
868
|
});
|
|
869
|
+
|
|
870
|
+
describe('search leaf — compound names, other names, and word forms', () => {
|
|
871
|
+
it('finds a compound name typed as separate words inside a longer query', async () => {
|
|
872
|
+
const {data} = await search('table header cell with sort arrow', {cwd});
|
|
873
|
+
expect(
|
|
874
|
+
data.results.slice(0, 3).map(r => r.name),
|
|
875
|
+
).toContain('TableHeaderCell');
|
|
876
|
+
}, SLOW);
|
|
877
|
+
|
|
878
|
+
it('finds a one-word keyword typed as separate words', async () => {
|
|
879
|
+
// MetadataList declares `keyvalue`.
|
|
880
|
+
const {data} = await search('key value pairs', {cwd});
|
|
881
|
+
expect(data.results[0]).toMatchObject({
|
|
882
|
+
domain: 'component',
|
|
883
|
+
name: 'MetadataList',
|
|
884
|
+
});
|
|
885
|
+
}, SLOW);
|
|
886
|
+
|
|
887
|
+
it('finds a hook named by its words without the `use` prefix', async () => {
|
|
888
|
+
const {data} = await search('persisted table column settings', {cwd});
|
|
889
|
+
expect(data.results[0]).toMatchObject({
|
|
890
|
+
domain: 'hook',
|
|
891
|
+
name: 'useTableColumnSettings',
|
|
892
|
+
});
|
|
893
|
+
}, SLOW);
|
|
894
|
+
|
|
895
|
+
it('reads a camelCase identifier as the words it spells', async () => {
|
|
896
|
+
const {data} = await search('useTablePaginationState', {cwd});
|
|
897
|
+
expect(data.results[0]).toMatchObject({
|
|
898
|
+
domain: 'hook',
|
|
899
|
+
name: 'useTablePagination',
|
|
900
|
+
});
|
|
901
|
+
}, SLOW);
|
|
902
|
+
|
|
903
|
+
it('keeps each identifier of a multi-word query whole', async () => {
|
|
904
|
+
const {data} = await search('ChatMessageList ChatComposer', {cwd});
|
|
905
|
+
expect(data.results.slice(0, 2).map(r => r.name).sort()).toEqual([
|
|
906
|
+
'ChatComposer',
|
|
907
|
+
'ChatMessageList',
|
|
908
|
+
]);
|
|
909
|
+
}, SLOW);
|
|
910
|
+
|
|
911
|
+
it("finds a component by another library's name for it", async () => {
|
|
912
|
+
for (const [q, name] of [
|
|
913
|
+
['ScrollArea viewport', 'ScrollableArea'],
|
|
914
|
+
['toggle group of buttons', 'ToggleButtonGroup'],
|
|
915
|
+
['circular progress for uploads', 'Spinner'],
|
|
916
|
+
]) {
|
|
917
|
+
const {data} = await search(q, {cwd});
|
|
918
|
+
expect(data.results[0], q).toMatchObject({domain: 'component', name});
|
|
919
|
+
}
|
|
920
|
+
}, SLOW);
|
|
921
|
+
|
|
922
|
+
it('reads a one-identifier other name as typed', async () => {
|
|
923
|
+
const {data} = await search('AppHeader', {cwd});
|
|
924
|
+
expect(data.results[0]).toMatchObject({
|
|
925
|
+
domain: 'component',
|
|
926
|
+
name: 'LayoutHeader',
|
|
927
|
+
});
|
|
928
|
+
}, SLOW);
|
|
929
|
+
|
|
930
|
+
it('adds no near siblings beside an entry the query names outright', async () => {
|
|
931
|
+
const {data} = await search('top nav mega menu', {cwd});
|
|
932
|
+
expect(data.results[0]).toMatchObject({name: 'TopNavMegaMenu'});
|
|
933
|
+
// Its sub-parts start with its name; read joined they would score in the
|
|
934
|
+
// whole-name tier right under it.
|
|
935
|
+
const siblings = data.results.filter(
|
|
936
|
+
r => r.name !== 'TopNavMegaMenu' && r.name.startsWith('TopNavMegaMenu'),
|
|
937
|
+
);
|
|
938
|
+
for (const sibling of siblings) expect(sibling.score).toBeLessThan(190);
|
|
939
|
+
}, SLOW);
|
|
940
|
+
|
|
941
|
+
it('ranks an entry the query names above a match on part of another name', async () => {
|
|
942
|
+
// `table header` names TableHeader; useTableStickyColumns only holds the
|
|
943
|
+
// words `sticky columns`.
|
|
944
|
+
const {data} = await search('table header with sticky columns', {cwd});
|
|
945
|
+
const names = data.results.map(r => r.name);
|
|
946
|
+
expect(names.indexOf('TableHeader')).toBeLessThan(
|
|
947
|
+
names.indexOf('useTableStickyColumns') === -1
|
|
948
|
+
? Infinity
|
|
949
|
+
: names.indexOf('useTableStickyColumns'),
|
|
950
|
+
);
|
|
951
|
+
}, SLOW);
|
|
952
|
+
|
|
953
|
+
it('keeps an entry a query word names by its whole name at its own rank', async () => {
|
|
954
|
+
// Two words join into TextInput, and TextArea also matches two words
|
|
955
|
+
// through its joined keyword; one word is still TextArea's whole name.
|
|
956
|
+
const {data} = await search('text input and textarea with multi line', {
|
|
957
|
+
cwd,
|
|
958
|
+
});
|
|
959
|
+
expect(data.results[0]).toMatchObject({name: 'TextArea'});
|
|
960
|
+
}, SLOW);
|
|
961
|
+
|
|
962
|
+
it('ranks a match on more of the query above a shorter named entry', async () => {
|
|
963
|
+
const {data} = await search('dropdown menu radio options', {cwd});
|
|
964
|
+
expect(data.results[0]).toMatchObject({name: 'DropdownMenuRadioItem'});
|
|
965
|
+
}, SLOW);
|
|
966
|
+
|
|
967
|
+
it('lets a plural start a name through its singular', () => {
|
|
968
|
+
expect(
|
|
969
|
+
scoreCandidate('tokens', {domain: 'component', name: 'Tokenizer'}),
|
|
970
|
+
).toMatchObject({score: 60});
|
|
971
|
+
});
|
|
972
|
+
|
|
973
|
+
it('finds Icon by a glyph name', async () => {
|
|
974
|
+
for (const q of ['cog', 'lightning bolt']) {
|
|
975
|
+
const {data} = await search(q, {cwd});
|
|
976
|
+
expect(data.results[0], q).toMatchObject({
|
|
977
|
+
domain: 'component',
|
|
978
|
+
name: 'Icon',
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
}, SLOW);
|
|
982
|
+
|
|
983
|
+
it('matches a verb form against its verb', () => {
|
|
984
|
+
// "spacing" lost the final e of "space".
|
|
985
|
+
expect(
|
|
986
|
+
scoreCandidate('spacing', {domain: 'component', name: 'Gap', keywords: ['space']}),
|
|
987
|
+
).toMatchObject({score: 88});
|
|
988
|
+
expect(
|
|
989
|
+
scoreCandidate('dragging', {domain: 'component', name: 'Gap', keywords: ['drag']}),
|
|
990
|
+
).toMatchObject({score: 88});
|
|
991
|
+
});
|
|
992
|
+
|
|
993
|
+
it('lets a plural start a longer word through its singular', () => {
|
|
994
|
+
expect(
|
|
995
|
+
scoreCandidate('chips', {domain: 'component', name: 'Chipset'}),
|
|
996
|
+
).toMatchObject({score: 60});
|
|
997
|
+
// A four-letter singular is too short: "stats" does not start "statusbar".
|
|
998
|
+
expect(
|
|
999
|
+
scoreCandidate('stats', {domain: 'component', name: 'Statusbar'}),
|
|
1000
|
+
).toBeNull();
|
|
1001
|
+
});
|
|
1002
|
+
|
|
1003
|
+
it('leaves an identifier joined with _ unmatched when nothing has it', async () => {
|
|
1004
|
+
const {data} = await search('qqzz_no_match_here', {cwd});
|
|
1005
|
+
expect(data.results).toEqual([]);
|
|
1006
|
+
}, SLOW);
|
|
1007
|
+
});
|
|
@@ -30,7 +30,7 @@ export type SearchResultEntry = {
|
|
|
30
30
|
*/
|
|
31
31
|
description: string;
|
|
32
32
|
/**
|
|
33
|
-
* - Follow-up command to act on this result (e.g. `astryx component Button`, or `astryx theme add neutral` for a theme).
|
|
33
|
+
* - Follow-up command to act on this result (e.g. `astryx component Button`, or `astryx theme add neutral` for a theme; `astryx theme eject neutral` outside a project).
|
|
34
34
|
*/
|
|
35
35
|
command: string;
|
|
36
36
|
/**
|
|
@@ -72,6 +72,19 @@ export type SearchResponse = {
|
|
|
72
72
|
matchCount: number;
|
|
73
73
|
results: SearchResultEntry[];
|
|
74
74
|
};
|
|
75
|
+
/**
|
|
76
|
+
* -
|
|
77
|
+
* `partial`, when an open search could not get the Core that components,
|
|
78
|
+
* hooks, and templates are read from (such as outside a project, offline,
|
|
79
|
+
* before the release's Core was downloaded): the domains it skipped and why.
|
|
80
|
+
* The results are the docs and themes.
|
|
81
|
+
*/
|
|
82
|
+
meta?: {
|
|
83
|
+
partial?: {
|
|
84
|
+
skipped: SearchDomain[];
|
|
85
|
+
reason: string;
|
|
86
|
+
};
|
|
87
|
+
} | undefined;
|
|
75
88
|
};
|
|
76
89
|
/**
|
|
77
90
|
* Options for `search()`.
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* @property {number} score - Relevance score (higher is better).
|
|
21
21
|
* @property {string} reason - Human-readable reason the candidate matched (e.g. `keyword "button"`).
|
|
22
22
|
* @property {string} description - One-line description, when available.
|
|
23
|
-
* @property {string} command - Follow-up command to act on this result (e.g. `astryx component Button`, or `astryx theme add neutral` for a theme).
|
|
23
|
+
* @property {string} command - Follow-up command to act on this result (e.g. `astryx component Button`, or `astryx theme add neutral` for a theme; `astryx theme eject neutral` outside a project).
|
|
24
24
|
* @property {string} [import] - Import path — present for component and hook results.
|
|
25
25
|
* @property {string} [title] - Doc title — present for doc results.
|
|
26
26
|
* @property {string} [section] - Section key — present when a doc result is one section of a topic; `command` reads only that section.
|
|
@@ -38,6 +38,11 @@
|
|
|
38
38
|
* @property {string} data.query
|
|
39
39
|
* @property {number} data.matchCount - How many candidates matched the query in total, before `limit` was applied. `results` is the bounded slice of that set, so `matchCount > results.length` means the answer was capped.
|
|
40
40
|
* @property {SearchResultEntry[]} data.results
|
|
41
|
+
* @property {{partial?: {skipped: SearchDomain[], reason: string}}} [meta] -
|
|
42
|
+
* `partial`, when an open search could not get the Core that components,
|
|
43
|
+
* hooks, and templates are read from (such as outside a project, offline,
|
|
44
|
+
* before the release's Core was downloaded): the domains it skipped and why.
|
|
45
|
+
* The results are the docs and themes.
|
|
41
46
|
*/
|
|
42
47
|
|
|
43
48
|
/**
|
package/api/swizzle/_adapter.mjs
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* (ERR_CORE_NOT_FOUND) when core can't be located.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {findProjectCoreDir, listComponents} from '../../foundation/fs/paths.mjs';
|
|
15
15
|
import {resolveComponentReplacements} from '../../foundation/discovery/component-replacement.mjs';
|
|
16
16
|
import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
|
|
17
17
|
import {AstryxError} from '../error.mjs';
|
|
@@ -44,7 +44,7 @@ export async function resolveComponentReplacement(
|
|
|
44
44
|
* @returns {{coreDir: string, components: string[]}}
|
|
45
45
|
*/
|
|
46
46
|
export function resolveCore(cwd) {
|
|
47
|
-
const coreDir =
|
|
47
|
+
const coreDir = findProjectCoreDir(cwd);
|
|
48
48
|
if (!coreDir) {
|
|
49
49
|
throw new AstryxError(
|
|
50
50
|
'Could not find @astryxdesign/core package. Make sure you are inside the design system monorepo or have @astryxdesign/core installed.',
|
|
@@ -21,8 +21,10 @@ import {checkGhCli} from '../_github.mjs';
|
|
|
21
21
|
import {Project} from '../../../foundation/config/project.mjs';
|
|
22
22
|
import {
|
|
23
23
|
CORE_PACKAGE,
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
docStem,
|
|
25
|
+
findComponentReadme,
|
|
26
|
+
findIntegrationComponent,
|
|
27
|
+
unscopedComponentOwners,
|
|
26
28
|
} from '../../../foundation/discovery/component-discovery.mjs';
|
|
27
29
|
import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
|
|
28
30
|
import {AstryxError, writeFailed} from '../../error.mjs';
|
|
@@ -113,7 +115,7 @@ function buildFeedback(component, issuesUrl) {
|
|
|
113
115
|
*/
|
|
114
116
|
async function loadConfigSafely(cwd) {
|
|
115
117
|
try {
|
|
116
|
-
const project = await Project.load(cwd);
|
|
118
|
+
const project = await Project.load(cwd, {core: 'project'});
|
|
117
119
|
return {
|
|
118
120
|
loadedIntegrations: project.loadedIntegrations,
|
|
119
121
|
issuesUrl: project.config.issuesUrl,
|
|
@@ -126,33 +128,38 @@ async function loadConfigSafely(cwd) {
|
|
|
126
128
|
|
|
127
129
|
/**
|
|
128
130
|
* Build the set of OWNER packages that provide a component named `name` across
|
|
129
|
-
* core + every loaded integration.
|
|
131
|
+
* core + every loaded integration. Core holds every name it documents, but has
|
|
132
|
+
* source to copy (`sourceDir`) only for a name with its own folder.
|
|
130
133
|
* @param {string} coreDir
|
|
131
134
|
* @param {Array<{name: string, components?: string, issuesUrl?: string}>} loadedIntegrations
|
|
132
135
|
* @param {string} name
|
|
133
136
|
* @param {string|undefined} coreIssuesUrl
|
|
134
|
-
* @returns {Array<{package: string, sourceDir: string|null, ownerPackage: string, issuesUrl: string|undefined}>}
|
|
137
|
+
* @returns {Array<{package: string, sourceDir: string|null, docPath: string|null, ownerPackage: string, issuesUrl: string|undefined, hold: string}>}
|
|
135
138
|
*/
|
|
136
139
|
function resolveOwners(coreDir, loadedIntegrations, name, coreIssuesUrl) {
|
|
137
140
|
const owners = [];
|
|
138
141
|
const coreComponentDir = path.join(coreDir, 'src', name);
|
|
139
|
-
|
|
142
|
+
const coreFolder = fs.existsSync(coreComponentDir);
|
|
143
|
+
if (coreFolder || findComponentReadme(coreDir, name)) {
|
|
140
144
|
owners.push({
|
|
141
145
|
package: CORE_PACKAGE,
|
|
142
|
-
sourceDir: coreComponentDir,
|
|
146
|
+
sourceDir: coreFolder ? coreComponentDir : null,
|
|
147
|
+
docPath: null,
|
|
143
148
|
ownerPackage: CORE_PACKAGE,
|
|
144
149
|
issuesUrl: coreIssuesUrl || DEFAULT_ISSUES_URL,
|
|
150
|
+
hold: 'core',
|
|
145
151
|
});
|
|
146
152
|
}
|
|
147
153
|
for (const integration of loadedIntegrations) {
|
|
148
|
-
const
|
|
149
|
-
if (!
|
|
150
|
-
const sourcePath = findIntegrationComponentSource(integration, name);
|
|
154
|
+
const found = findIntegrationComponent(integration, name);
|
|
155
|
+
if (!found) continue;
|
|
151
156
|
owners.push({
|
|
152
157
|
package: integration.name,
|
|
153
|
-
sourceDir: sourcePath ? path.dirname(sourcePath) : null,
|
|
158
|
+
sourceDir: found.sourcePath ? path.dirname(found.sourcePath) : null,
|
|
159
|
+
docPath: found.docPath,
|
|
154
160
|
ownerPackage: integration.name,
|
|
155
161
|
issuesUrl: integration.issuesUrl,
|
|
162
|
+
hold: found.hold,
|
|
156
163
|
});
|
|
157
164
|
}
|
|
158
165
|
return owners;
|
|
@@ -222,25 +229,32 @@ export async function swizzleCopy(component, options = {}) {
|
|
|
222
229
|
: undefined;
|
|
223
230
|
// An active integration replacement answers to the Core name it replaces,
|
|
224
231
|
// bare or qualified by its own package (spec:AST-035 FR11): copy it under its
|
|
225
|
-
//
|
|
232
|
+
// doc's file name, the folder it has always gone to. `--package
|
|
233
|
+
// @astryxdesign/core` still copies the Core original.
|
|
226
234
|
if (pkg !== CORE_PACKAGE) {
|
|
227
235
|
const replacement = await resolveComponentReplacement(
|
|
228
236
|
coreDir,
|
|
229
237
|
loadedIntegrations,
|
|
230
238
|
dirName,
|
|
231
239
|
);
|
|
240
|
+
const copyName = replacement ? docStem(replacement.docPath) : null;
|
|
232
241
|
if (
|
|
233
242
|
replacement &&
|
|
234
|
-
|
|
243
|
+
copyName &&
|
|
244
|
+
(!pkg || (pkg === replacement.package && copyName !== dirName))
|
|
235
245
|
) {
|
|
236
|
-
return swizzleCopy(
|
|
246
|
+
return swizzleCopy(copyName, {
|
|
237
247
|
...options,
|
|
238
248
|
package: replacement.package,
|
|
239
249
|
});
|
|
240
250
|
}
|
|
241
251
|
}
|
|
242
252
|
|
|
243
|
-
const
|
|
253
|
+
const found = resolveOwners(coreDir, loadedIntegrations, dirName, coreIssuesUrl);
|
|
254
|
+
// The owner rule, then a Core name without its own folder drops out.
|
|
255
|
+
const allOwners = (pkg ? found : unscopedComponentOwners(found)).filter(
|
|
256
|
+
owner => owner.package !== CORE_PACKAGE || owner.sourceDir != null,
|
|
257
|
+
);
|
|
244
258
|
|
|
245
259
|
if (allOwners.length === 0) {
|
|
246
260
|
throw new AstryxError(
|
|
@@ -736,7 +736,7 @@ describe('integration template discovery', () => {
|
|
|
736
736
|
const command = await runCli(['template', 'shell-side-nav'], tmpDir);
|
|
737
737
|
expect(command.status).toBe(0);
|
|
738
738
|
expect(command.stderr).toContain('@acme/extra has 1 integration issue');
|
|
739
|
-
expect(command.stderr).
|
|
739
|
+
expect(command.stderr).toMatch(/Run: .+ doctor/);
|
|
740
740
|
|
|
741
741
|
const doctor = await runCli(['doctor'], tmpDir);
|
|
742
742
|
expect(doctor.status).toBe(0);
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
2
|
|
|
3
|
+
import * as fs from 'node:fs';
|
|
4
|
+
import * as os from 'node:os';
|
|
5
|
+
import * as path from 'node:path';
|
|
3
6
|
import {describe, it, expect} from 'vitest';
|
|
4
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
stripTemplateAssetRefs,
|
|
9
|
+
template,
|
|
10
|
+
extractComponents,
|
|
11
|
+
} from './template.mjs';
|
|
5
12
|
|
|
6
13
|
describe('stripTemplateAssetRefs', () => {
|
|
7
14
|
it('replaces a /template-assets image path with an inline data URI', () => {
|
|
@@ -31,8 +38,7 @@ describe('stripTemplateAssetRefs', () => {
|
|
|
31
38
|
});
|
|
32
39
|
|
|
33
40
|
it('preserves surrounding source structure', () => {
|
|
34
|
-
const src =
|
|
35
|
-
"const data = [{src: '/template-assets/x.png', alt: 'X'}];";
|
|
41
|
+
const src = "const data = [{src: '/template-assets/x.png', alt: 'X'}];";
|
|
36
42
|
const out = stripTemplateAssetRefs(src);
|
|
37
43
|
expect(out).toContain("alt: 'X'");
|
|
38
44
|
expect(out).toContain('const data = [{src:');
|
|
@@ -102,4 +108,115 @@ describe('template --skeleton component extraction (prefix-agnostic)', () => {
|
|
|
102
108
|
|
|
103
109
|
expect(result.data.skeleton).toContain('columns={{minWidth: 200}}');
|
|
104
110
|
});
|
|
111
|
+
|
|
112
|
+
it('filters out local helper components declared in the same file', () => {
|
|
113
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-test-'));
|
|
114
|
+
const pagePath = path.join(tmpDir, 'page.tsx');
|
|
115
|
+
fs.writeFileSync(
|
|
116
|
+
pagePath,
|
|
117
|
+
`
|
|
118
|
+
import {Card} from '@astryxdesign/core/Layout';
|
|
119
|
+
|
|
120
|
+
function TimelineSection() {
|
|
121
|
+
return <div />;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export default function Page() {
|
|
125
|
+
return (
|
|
126
|
+
<Card>
|
|
127
|
+
<TimelineSection />
|
|
128
|
+
</Card>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
`,
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const components = extractComponents(pagePath);
|
|
136
|
+
expect(components).toContain('Card');
|
|
137
|
+
expect(components).not.toContain('Timeline');
|
|
138
|
+
} finally {
|
|
139
|
+
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('filters out a type-annotated local helper', () => {
|
|
144
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-test-'));
|
|
145
|
+
const pagePath = path.join(tmpDir, 'page.tsx');
|
|
146
|
+
fs.writeFileSync(
|
|
147
|
+
pagePath,
|
|
148
|
+
`
|
|
149
|
+
import type {FC} from 'react';
|
|
150
|
+
import {Card} from '@astryxdesign/core/Layout';
|
|
151
|
+
|
|
152
|
+
const TimelineSection: FC = () => <div />;
|
|
153
|
+
|
|
154
|
+
export default function Page() {
|
|
155
|
+
return (
|
|
156
|
+
<Card>
|
|
157
|
+
<TimelineSection />
|
|
158
|
+
</Card>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
`,
|
|
162
|
+
);
|
|
163
|
+
try {
|
|
164
|
+
const components = extractComponents(pagePath);
|
|
165
|
+
expect(components).toContain('Card');
|
|
166
|
+
expect(components).not.toContain('Timeline');
|
|
167
|
+
} finally {
|
|
168
|
+
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('keeps an imported component when declaration-like text appears in a comment or string', () => {
|
|
173
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-test-'));
|
|
174
|
+
const pagePath = path.join(tmpDir, 'page.tsx');
|
|
175
|
+
fs.writeFileSync(
|
|
176
|
+
pagePath,
|
|
177
|
+
`
|
|
178
|
+
import {Card} from '@astryxdesign/core/Layout';
|
|
179
|
+
|
|
180
|
+
// const Card = () => null;
|
|
181
|
+
const note = 'function Card() {}';
|
|
182
|
+
|
|
183
|
+
export default function Page() {
|
|
184
|
+
return <Card>{note}</Card>;
|
|
185
|
+
}
|
|
186
|
+
`,
|
|
187
|
+
);
|
|
188
|
+
try {
|
|
189
|
+
expect(extractComponents(pagePath)).toContain('Card');
|
|
190
|
+
} finally {
|
|
191
|
+
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('keeps a bare imported component whose name is itself a stripped suffix', () => {
|
|
196
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-test-'));
|
|
197
|
+
const pagePath = path.join(tmpDir, 'page.tsx');
|
|
198
|
+
fs.writeFileSync(
|
|
199
|
+
pagePath,
|
|
200
|
+
`
|
|
201
|
+
import {Section} from '@astryxdesign/core/Section';
|
|
202
|
+
|
|
203
|
+
function SectionHeading() {
|
|
204
|
+
return <div />;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export default function Page() {
|
|
208
|
+
return (
|
|
209
|
+
<Section>
|
|
210
|
+
<SectionHeading />
|
|
211
|
+
</Section>
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
`,
|
|
215
|
+
);
|
|
216
|
+
try {
|
|
217
|
+
expect(extractComponents(pagePath)).toContain('Section');
|
|
218
|
+
} finally {
|
|
219
|
+
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
220
|
+
}
|
|
221
|
+
});
|
|
105
222
|
});
|
package/api/theme/_adapter.d.mts
CHANGED
|
@@ -129,6 +129,22 @@ export function removeThemeFromApp(slug: string, options?: {
|
|
|
129
129
|
export function useThemeInApp(slug: string, options?: {
|
|
130
130
|
cwd?: string;
|
|
131
131
|
}): Promise<import("./theme.type.mjs").ThemeAppResponse>;
|
|
132
|
+
/**
|
|
133
|
+
* The Core theme targets are read from: the project's, else the release's
|
|
134
|
+
* own, installed into the per-user cache first when needed (a network install
|
|
135
|
+
* and an npm subprocess; spec AST-081 FR3). Throws as requireCoreDir does.
|
|
136
|
+
* @param {string} cwd
|
|
137
|
+
* @returns {string}
|
|
138
|
+
*/
|
|
139
|
+
export function requireThemeCoreDir(cwd: string): string;
|
|
140
|
+
/**
|
|
141
|
+
* The Core a theme build reads outside a project: the one the answering copy
|
|
142
|
+
* carries, installed into the per-user cache first when needed (a network
|
|
143
|
+
* install and an npm subprocess; spec AST-081 FR3); null when there is none.
|
|
144
|
+
* @param {string} cwd
|
|
145
|
+
* @returns {string | null}
|
|
146
|
+
*/
|
|
147
|
+
export function fetchCarriedThemeCoreDir(cwd: string): string | null;
|
|
132
148
|
/**
|
|
133
149
|
* A bundled theme entry kept for the historical public `listThemes()` helper.
|
|
134
150
|
*/
|
package/api/theme/_adapter.mjs
CHANGED
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
|
|
12
12
|
import * as fs from 'node:fs';
|
|
13
13
|
import * as path from 'node:path';
|
|
14
|
+
import {
|
|
15
|
+
findCarriedCoreDir,
|
|
16
|
+
requireCoreDir,
|
|
17
|
+
} from '../../foundation/fs/paths.mjs';
|
|
14
18
|
import {Project} from '../../foundation/config/project.mjs';
|
|
15
19
|
import {
|
|
16
20
|
BUNDLED_THEME_PACKAGE,
|
|
@@ -41,6 +45,7 @@ import {stripCopyrightHeader} from '../../foundation/text/copyright-header.mjs';
|
|
|
41
45
|
import {loadIntegrations} from '../../foundation/integrations/integrations.mjs';
|
|
42
46
|
import {importThemeArtifact} from '../../foundation/fs/module-loader.mjs';
|
|
43
47
|
import {applyWrites} from '../integration/add-helpers.mjs';
|
|
48
|
+
import {formatCliCommand} from '../../foundation/env/package-manager.mjs';
|
|
44
49
|
|
|
45
50
|
export {BUNDLED_THEME_PACKAGE, THEMES_DIR};
|
|
46
51
|
|
|
@@ -565,7 +570,7 @@ export function resolveRecordedThemes(state, available) {
|
|
|
565
570
|
);
|
|
566
571
|
if (!theme) {
|
|
567
572
|
throw new AstryxError(
|
|
568
|
-
`Added theme "${slug}" from ${owner} is unavailable. Reinstall the package or restore the local theme, then run
|
|
573
|
+
`Added theme "${slug}" from ${owner} is unavailable. Reinstall the package or restore the local theme, then run \`${formatCliCommand(`theme add ${slug} --package ${owner}`, state.projectDir)}\`.`,
|
|
569
574
|
undefined,
|
|
570
575
|
ERROR_CODES.ERR_UNKNOWN_THEME,
|
|
571
576
|
);
|
|
@@ -732,14 +737,14 @@ export async function removeThemeFromApp(slug, options = {}) {
|
|
|
732
737
|
const recordedSlug = recordedThemeSlug(state, slug);
|
|
733
738
|
if (!state.configured || recordedSlug == null) {
|
|
734
739
|
throw new AstryxError(
|
|
735
|
-
`Theme "${slug}" is not added. Run
|
|
740
|
+
`Theme "${slug}" is not added. Run \`${formatCliCommand(`theme add ${slug}`, state.projectDir)}\` first.`,
|
|
736
741
|
undefined,
|
|
737
742
|
ERROR_CODES.ERR_UNKNOWN_THEME,
|
|
738
743
|
);
|
|
739
744
|
}
|
|
740
745
|
if (state.defaultSlug === recordedSlug) {
|
|
741
746
|
throw new AstryxError(
|
|
742
|
-
`Theme "${recordedSlug}" is the default. Run
|
|
747
|
+
`Theme "${recordedSlug}" is the default. Run \`${formatCliCommand('theme use <other-slug>', state.projectDir)}\` before removing it.`,
|
|
743
748
|
undefined,
|
|
744
749
|
ERROR_CODES.ERR_THEME_INVALID,
|
|
745
750
|
);
|
|
@@ -748,7 +753,7 @@ export async function removeThemeFromApp(slug, options = {}) {
|
|
|
748
753
|
delete themes[recordedSlug];
|
|
749
754
|
if (state.defaultSlug == null) {
|
|
750
755
|
throw new AstryxError(
|
|
751
|
-
|
|
756
|
+
`The generated theme module has no default theme. Run \`${formatCliCommand('theme use <slug>', state.projectDir)}\` first.`,
|
|
752
757
|
undefined,
|
|
753
758
|
ERROR_CODES.ERR_THEME_INVALID,
|
|
754
759
|
);
|
|
@@ -776,7 +781,7 @@ export async function useThemeInApp(slug, options = {}) {
|
|
|
776
781
|
const recordedSlug = recordedThemeSlug(state, slug);
|
|
777
782
|
if (!state.configured || recordedSlug == null) {
|
|
778
783
|
throw new AstryxError(
|
|
779
|
-
`Theme "${slug}" is not added. Run
|
|
784
|
+
`Theme "${slug}" is not added. Run \`${formatCliCommand(`theme add ${slug}`, state.projectDir)}\` first.`,
|
|
780
785
|
undefined,
|
|
781
786
|
ERROR_CODES.ERR_UNKNOWN_THEME,
|
|
782
787
|
);
|
|
@@ -792,3 +797,25 @@ export async function useThemeInApp(slug, options = {}) {
|
|
|
792
797
|
available,
|
|
793
798
|
);
|
|
794
799
|
}
|
|
800
|
+
|
|
801
|
+
/**
|
|
802
|
+
* The Core theme targets are read from: the project's, else the release's
|
|
803
|
+
* own, installed into the per-user cache first when needed (a network install
|
|
804
|
+
* and an npm subprocess; spec AST-081 FR3). Throws as requireCoreDir does.
|
|
805
|
+
* @param {string} cwd
|
|
806
|
+
* @returns {string}
|
|
807
|
+
*/
|
|
808
|
+
export function requireThemeCoreDir(cwd) {
|
|
809
|
+
return requireCoreDir(cwd);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
/**
|
|
813
|
+
* The Core a theme build reads outside a project: the one the answering copy
|
|
814
|
+
* carries, installed into the per-user cache first when needed (a network
|
|
815
|
+
* install and an npm subprocess; spec AST-081 FR3); null when there is none.
|
|
816
|
+
* @param {string} cwd
|
|
817
|
+
* @returns {string | null}
|
|
818
|
+
*/
|
|
819
|
+
export function fetchCarriedThemeCoreDir(cwd) {
|
|
820
|
+
return findCarriedCoreDir(cwd, {fetch: true});
|
|
821
|
+
}
|
|
@@ -110,13 +110,14 @@ export function themeBuildForReport(file: string, options?: {
|
|
|
110
110
|
receipt: import("../theme.type.mjs").ThemeBuildResponse | import("../theme.type.mjs").ThemeBuildCheckResponse | null;
|
|
111
111
|
trailer: ThemeBuildTrailer | null;
|
|
112
112
|
}>;
|
|
113
|
-
/** @param {string} file @param {{out?: string, check?: boolean, iconsSpecifier?: string}} [options] @param {{cwd?: string}} [ctx] @returns {Promise<import('../theme.type.mjs').ThemeBuildResponse | import('../theme.type.mjs').ThemeBuildCheckResponse | null>} */
|
|
113
|
+
/** @param {string} file @param {{out?: string, check?: boolean, iconsSpecifier?: string}} [options] @param {{cwd?: string, projectCore?: boolean}} [ctx] `projectCore`: read only the project's installed Core, never the carried one (doctor; spec AST-081 FR3) @returns {Promise<import('../theme.type.mjs').ThemeBuildResponse | import('../theme.type.mjs').ThemeBuildCheckResponse | null>} */
|
|
114
114
|
export function themeBuild(file: string, options?: {
|
|
115
115
|
out?: string;
|
|
116
116
|
check?: boolean;
|
|
117
117
|
iconsSpecifier?: string;
|
|
118
118
|
}, ctx?: {
|
|
119
119
|
cwd?: string;
|
|
120
|
+
projectCore?: boolean;
|
|
120
121
|
}): Promise<import("../theme.type.mjs").ThemeBuildResponse | import("../theme.type.mjs").ThemeBuildCheckResponse | null>;
|
|
121
122
|
/** @param {string[]} files @param {{familyKey: string, check?: boolean, iconsSpecifier?: string, __onPrivateVarError?: () => void}} options @param {{cwd?: string}} [ctx] */
|
|
122
123
|
export function themeBuildFamily(files: string[], options: {
|