@astryxdesign/cli 0.7.2-canary.fdd384f → 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 +169 -149
- 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/kit/kit.mjs +3 -11
- package/api/component/_adapter.d.mts +31 -0
- package/api/component/_adapter.mjs +119 -11
- package/api/component/component.doc.mjs +6 -1
- package/api/component/component.mjs +60 -10
- package/api/component/doc-links.test.mjs +386 -0
- 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 +63 -0
- package/api/docs/_adapter.mjs +312 -18
- 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/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 +16 -3
- 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 +152 -48
- 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/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 +15 -4
- 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 +33 -0
- package/api/integration/_adapter.mjs +58 -0
- package/api/integration/authoring-checks.mjs +100 -5
- package/api/integration/authoring-checks.test.mjs +769 -0
- package/api/integration/authoring-checks.type.d.mts +134 -0
- package/api/integration/authoring-checks.type.mjs +60 -1
- package/api/integration/integrationCheck.doc.mjs +1 -1
- package/api/integration/integrationComponentConflicts.doc.mjs +11 -3
- package/api/integration/integrationDocConflicts.doc.mjs +22 -5
- package/api/integration/pack-check.mjs +303 -13
- package/api/integration/pack-check.test.mjs +371 -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 +55 -9
- package/api/integration/validate-integration.test.mjs +77 -8
- package/api/integration/validate-integration.type.d.mts +8 -0
- package/api/integration/validate-integration.type.mjs +3 -1
- package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
- package/api/integration/validateIntegration.doc.mjs +4 -2
- package/api/search/_adapter.d.mts +11 -0
- package/api/search/_adapter.mjs +25 -0
- package/api/search/search.d.mts +73 -13
- package/api/search/search.doc.mjs +8 -3
- package/api/search/search.domain-priority.test.mjs +108 -18
- package/api/search/search.mjs +541 -52
- package/api/search/search.test.mjs +143 -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 +1 -1
- package/api/template/template-integration.test.mjs +1 -1
- 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.mjs +70 -14
- 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/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/next/index.mjs +1 -11
- package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
- package/assets/discover/official-packages.json +367 -0
- package/assets/docs/author-a-theme.doc.mjs +2 -2
- package/assets/docs/browser-support.doc.mjs +1 -1
- package/assets/docs/getting-started.doc.mjs +23 -3
- package/assets/docs/styling-overview.doc.mjs +1 -1
- package/assets/docs/theme.doc.mjs +1 -1
- package/assets/docs/tree/add-a-component.doc.mjs +12 -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 +6 -18
- 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 +8 -3
- package/assets/docs/tree/check-your-docs.doc.mjs +30 -13
- package/assets/docs/tree/checks.doc.mjs +17 -17
- 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 +3 -5
- package/assets/docs/tree/component-imports.doc.mjs +13 -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 +2 -2
- 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 +6 -5
- package/assets/docs/tree/migration-setup.doc.mjs +3 -2
- package/assets/docs/tree/migration-verification.doc.mjs +0 -1
- package/assets/docs/tree/migration.doc.mjs +0 -1
- package/assets/docs/tree/monorepos.doc.mjs +84 -0
- package/assets/docs/tree/package-and-test.doc.mjs +1 -1
- package/assets/docs/tree/page-template.doc.mjs +3 -7
- 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 +52 -26
- 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 +9 -11
- 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 +14 -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 +22 -14
- 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 +9 -9
- package/assets/docs/tree/who-answers.doc.mjs +119 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +5 -5
- package/assets/docs/working-with-ai.doc.mjs +23 -9
- 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 +29 -26
- package/authoring/doctypes/component/type.ts +15 -5
- 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/template.doc.mjs +2 -2
- package/authoring/doctypes/theme/theme.doc.mjs +2 -2
- package/authoring/gap-report/gap-report.doc.mjs +2 -2
- package/authoring/identity/identity.doc.mjs +3 -3
- package/authoring/index.d.ts +1 -0
- package/authoring/integration/integration.doc.mjs +22 -5
- package/authoring/integration/parse.test.mjs +11 -0
- package/authoring/integration/schema.d.mts +14 -3
- package/authoring/integration/schema.mjs +33 -2
- package/authoring/integration/type.ts +8 -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 +14 -2
- package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
- package/clients/cli/commands/build-theme.mjs +25 -12
- 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 +7 -3
- 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 +13 -2
- package/clients/cli/commands/doctor-integration.test.mjs +52 -4
- package/clients/cli/commands/doctor.doc.mjs +12 -2
- package/clients/cli/commands/doctor.mjs +102 -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 +10 -2
- package/clients/cli/commands/integration-check.test.mjs +175 -1
- 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.mjs +15 -9
- 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/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 +1 -0
- 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 +111 -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 +145 -8
- package/foundation/config/project.test.mjs +66 -0
- package/foundation/config/theme-state.mjs +5 -4
- package/foundation/discovery/authoring-self-docs.mjs +1 -1
- package/foundation/discovery/cli-self-docs.mjs +20 -3
- package/foundation/discovery/cli-self-docs.test.mjs +3 -2
- package/foundation/discovery/component-replacement.mjs +2 -1
- 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 +1 -1
- package/foundation/discovery/doc-types.mjs +15 -8
- package/foundation/discovery/doc-types.test.mjs +94 -2
- package/foundation/discovery/docs-discovery.d.mts +7 -0
- package/foundation/discovery/docs-discovery.mjs +26 -2
- package/foundation/discovery/project-typescript.d.mts +11 -2
- package/foundation/discovery/project-typescript.mjs +32 -4
- package/foundation/discovery/prop-drift.d.mts +26 -7
- package/foundation/discovery/prop-drift.mjs +173 -8
- package/foundation/discovery/prop-drift.test.mjs +120 -2
- 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-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-text.mjs +1 -1
- package/foundation/discovery/type-text.test.mjs +1 -1
- package/foundation/doc-compiler/doc-loads.test.mjs +42 -2
- package/foundation/doc-compiler/inputs.mjs +4 -1
- package/foundation/doc-compiler/links.d.mts +32 -0
- package/foundation/doc-compiler/links.mjs +163 -26
- 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 +50 -2
- 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 +17 -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/package.json +11 -11
- package/scripts/postinstall.mjs +24 -5
- /package/assets/codemods/transforms/{next → v0.7.2}/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +0 -0
- /package/assets/codemods/transforms/{next → v0.7.2}/migrate-list-edge-compensation-to-edge.mjs +0 -0
|
@@ -62,6 +62,10 @@ export const doc = {
|
|
|
62
62
|
code: 'ERR_CORE_NOT_FOUND',
|
|
63
63
|
when: '@astryxdesign/core cannot be resolved from cwd',
|
|
64
64
|
},
|
|
65
|
+
{
|
|
66
|
+
code: 'ERR_VERSIONS_UNAVAILABLE',
|
|
67
|
+
when: 'outside a project, or in a project with nothing installed, the Core of the release that answers is not beside it or cached, and cannot be installed into the per-user cache (offline, a registry without it, or an unwritable cache)',
|
|
68
|
+
},
|
|
65
69
|
{code: 'ERR_UNKNOWN_COMPONENT', when: 'a filter matches no target'},
|
|
66
70
|
],
|
|
67
71
|
examples: [
|
|
@@ -92,7 +92,7 @@ describe('themeUse', () => {
|
|
|
92
92
|
it('names theme add when the slug is not added', async () => {
|
|
93
93
|
await expect(themeUse('missing', {cwd: tmpDir})).rejects.toMatchObject({
|
|
94
94
|
code: 'ERR_UNKNOWN_THEME',
|
|
95
|
-
message: expect.stringContaining('
|
|
95
|
+
message: expect.stringContaining(' theme add missing`'),
|
|
96
96
|
});
|
|
97
97
|
});
|
|
98
98
|
});
|
|
@@ -31,6 +31,43 @@ export function detectInstalledTargetVersion(cwd: string): {
|
|
|
31
31
|
version: string;
|
|
32
32
|
packageName: string;
|
|
33
33
|
} | null;
|
|
34
|
+
/**
|
|
35
|
+
* Whether the installed Core is newer than this CLI, so part of the requested
|
|
36
|
+
* range has no codemods here.
|
|
37
|
+
*
|
|
38
|
+
* Core codemods ship inside the CLI. A CLI older than the installed
|
|
39
|
+
* `@astryxdesign/core` has none for the releases after its own version, so it
|
|
40
|
+
* can find no codemods, or stop partway, while the code still needs those
|
|
41
|
+
* releases' migrations. The returned command repeats this upgrade with the CLI
|
|
42
|
+
* release that matches the installed Core.
|
|
43
|
+
*
|
|
44
|
+
* Where an upgrade runs decides what it finds: the installed Core is read
|
|
45
|
+
* from that folder, and `--path` must stay inside it. So the command first
|
|
46
|
+
* changes to `cwd`, the folder this run used, then names `sourcePath`, the
|
|
47
|
+
* directory this run scanned, as an absolute `--path`. Both are named by their
|
|
48
|
+
* physical paths, with every symbolic link resolved: a shell's `cd` follows a
|
|
49
|
+
* link, but the CLI it starts reads its folder with every link resolved and
|
|
50
|
+
* checks `--path` against that. Pasted from any folder, the command finds the
|
|
51
|
+
* same Core and scans the same directory, even after a package runner moved
|
|
52
|
+
* this run (Yarn 1 runs `yarn astryx` at the project root). It is written for
|
|
53
|
+
* a POSIX shell, or for PowerShell on Windows (cmd.exe is not a target), with
|
|
54
|
+
* every argument quoted for that shell.
|
|
55
|
+
*
|
|
56
|
+
* Returns null when the CLI covers the whole range (`to` is not newer than
|
|
57
|
+
* both the CLI and `from`), when the CLI's own version cannot be read, or when
|
|
58
|
+
* the target is legacy `@xds/core`, which no CLI release shares a version with.
|
|
59
|
+
*
|
|
60
|
+
* @param {{from: string, to: string, packageName: string, options: UpgradeOptions, cwd: string, sourcePath: string}} input
|
|
61
|
+
* @returns {import('./upgrade.type.mjs').CliBehindCore | null}
|
|
62
|
+
*/
|
|
63
|
+
export function detectCliBehindCore({ from, to, packageName, options, cwd, sourcePath, }: {
|
|
64
|
+
from: string;
|
|
65
|
+
to: string;
|
|
66
|
+
packageName: string;
|
|
67
|
+
options: UpgradeOptions;
|
|
68
|
+
cwd: string;
|
|
69
|
+
sourcePath: string;
|
|
70
|
+
}): import("./upgrade.type.mjs").CliBehindCore | null;
|
|
34
71
|
/**
|
|
35
72
|
* @param {(string | null | undefined | false)[] | undefined} files
|
|
36
73
|
* @returns {string[]}
|
|
@@ -104,9 +141,9 @@ export function ensureCodemodDeps({ installDeps }?: {
|
|
|
104
141
|
* Run the CORE registry codemods. Runs BEFORE the config is loaded so a core
|
|
105
142
|
* CONFIG codemod can repair a config the strict loader would otherwise reject.
|
|
106
143
|
* @param {CoreVersionManifest[]} versionManifests
|
|
107
|
-
* @param {{apply: boolean, path: string, codemod?: string, skipCodemods: Set<string>, root?: string, protection?: {root: string, classify: (file: string) => import('../../foundation/fs/file-protection.mjs').FileProtection[]}, silent?: boolean}} options
|
|
144
|
+
* @param {{apply: boolean, path: string, codemod?: string, skipCodemods: Set<string>, root?: string, protection?: {root: string, classify: (file: string) => import('../../foundation/fs/file-protection.mjs').FileProtection[]}, silent?: boolean, coversTarget?: boolean}} options
|
|
108
145
|
*/
|
|
109
|
-
export function runCoreCodemods(versionManifests: CoreVersionManifest[], { apply, path: srcPath, codemod, skipCodemods, root, protection, silent }: {
|
|
146
|
+
export function runCoreCodemods(versionManifests: CoreVersionManifest[], { apply, path: srcPath, codemod, skipCodemods, root, protection, silent, coversTarget, }: {
|
|
110
147
|
apply: boolean;
|
|
111
148
|
path: string;
|
|
112
149
|
codemod?: string;
|
|
@@ -117,6 +154,7 @@ export function runCoreCodemods(versionManifests: CoreVersionManifest[], { apply
|
|
|
117
154
|
classify: (file: string) => import("../../foundation/fs/file-protection.mjs").FileProtection[];
|
|
118
155
|
};
|
|
119
156
|
silent?: boolean;
|
|
157
|
+
coversTarget?: boolean;
|
|
120
158
|
}): Promise<{
|
|
121
159
|
totalFilesChanged: number;
|
|
122
160
|
totalTransformsApplied: number;
|
package/api/upgrade/_adapter.mjs
CHANGED
|
@@ -34,7 +34,15 @@ import {
|
|
|
34
34
|
inspectAgentDocs,
|
|
35
35
|
renderAgentDocsBlock,
|
|
36
36
|
} from '../../foundation/agent-docs/agent-docs.mjs';
|
|
37
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
CLI_PACKAGE,
|
|
39
|
+
commandInFolder,
|
|
40
|
+
formatCliCommand,
|
|
41
|
+
getDlxPrefix,
|
|
42
|
+
quoteCommandArgument,
|
|
43
|
+
} from '../../foundation/env/package-manager.mjs';
|
|
44
|
+
import {isValidSemver, semverGt} from '../../foundation/env/semver.mjs';
|
|
45
|
+
import {CLI_ROOT} from '../../foundation/fs/paths.mjs';
|
|
38
46
|
import {Project, providerLedgerOf} from '../../foundation/config/project.mjs';
|
|
39
47
|
import {loadIntegrations} from '../../foundation/integrations/integrations.mjs';
|
|
40
48
|
import {resolveProviders} from '../../foundation/integrations/provider-resolution.mjs';
|
|
@@ -96,6 +104,99 @@ export function detectInstalledTargetVersion(cwd) {
|
|
|
96
104
|
return null;
|
|
97
105
|
}
|
|
98
106
|
|
|
107
|
+
/**
|
|
108
|
+
* The running CLI's own version, read from its package.json.
|
|
109
|
+
* @returns {string | null} null when it cannot be read or is not semver
|
|
110
|
+
*/
|
|
111
|
+
function readRunningCliVersion() {
|
|
112
|
+
try {
|
|
113
|
+
const pkg = JSON.parse(
|
|
114
|
+
fs.readFileSync(path.join(CLI_ROOT, 'package.json'), 'utf-8'),
|
|
115
|
+
);
|
|
116
|
+
return isValidSemver(pkg.version) ? pkg.version : null;
|
|
117
|
+
} catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Whether the installed Core is newer than this CLI, so part of the requested
|
|
124
|
+
* range has no codemods here.
|
|
125
|
+
*
|
|
126
|
+
* Core codemods ship inside the CLI. A CLI older than the installed
|
|
127
|
+
* `@astryxdesign/core` has none for the releases after its own version, so it
|
|
128
|
+
* can find no codemods, or stop partway, while the code still needs those
|
|
129
|
+
* releases' migrations. The returned command repeats this upgrade with the CLI
|
|
130
|
+
* release that matches the installed Core.
|
|
131
|
+
*
|
|
132
|
+
* Where an upgrade runs decides what it finds: the installed Core is read
|
|
133
|
+
* from that folder, and `--path` must stay inside it. So the command first
|
|
134
|
+
* changes to `cwd`, the folder this run used, then names `sourcePath`, the
|
|
135
|
+
* directory this run scanned, as an absolute `--path`. Both are named by their
|
|
136
|
+
* physical paths, with every symbolic link resolved: a shell's `cd` follows a
|
|
137
|
+
* link, but the CLI it starts reads its folder with every link resolved and
|
|
138
|
+
* checks `--path` against that. Pasted from any folder, the command finds the
|
|
139
|
+
* same Core and scans the same directory, even after a package runner moved
|
|
140
|
+
* this run (Yarn 1 runs `yarn astryx` at the project root). It is written for
|
|
141
|
+
* a POSIX shell, or for PowerShell on Windows (cmd.exe is not a target), with
|
|
142
|
+
* every argument quoted for that shell.
|
|
143
|
+
*
|
|
144
|
+
* Returns null when the CLI covers the whole range (`to` is not newer than
|
|
145
|
+
* both the CLI and `from`), when the CLI's own version cannot be read, or when
|
|
146
|
+
* the target is legacy `@xds/core`, which no CLI release shares a version with.
|
|
147
|
+
*
|
|
148
|
+
* @param {{from: string, to: string, packageName: string, options: UpgradeOptions, cwd: string, sourcePath: string}} input
|
|
149
|
+
* @returns {import('./upgrade.type.mjs').CliBehindCore | null}
|
|
150
|
+
*/
|
|
151
|
+
export function detectCliBehindCore({
|
|
152
|
+
from,
|
|
153
|
+
to,
|
|
154
|
+
packageName,
|
|
155
|
+
options,
|
|
156
|
+
cwd,
|
|
157
|
+
sourcePath,
|
|
158
|
+
}) {
|
|
159
|
+
if (packageName !== '@astryxdesign/core') return null;
|
|
160
|
+
const cliVersion = readRunningCliVersion();
|
|
161
|
+
if (!cliVersion || !semverGt(to, cliVersion) || !semverGt(to, from)) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
const runFolder = path.resolve(cwd);
|
|
165
|
+
const folder = physicalFolder(runFolder);
|
|
166
|
+
const scanned = path.join(folder, path.relative(runFolder, sourcePath));
|
|
167
|
+
const args = ['upgrade', '--from', from, '--path', scanned];
|
|
168
|
+
if (options.codemod) args.push('--codemod', options.codemod);
|
|
169
|
+
for (const name of options.skipCodemod ?? []) {
|
|
170
|
+
args.push('--skip-codemod', name);
|
|
171
|
+
}
|
|
172
|
+
for (const spec of options.integration ?? []) {
|
|
173
|
+
args.push('--integration', spec);
|
|
174
|
+
}
|
|
175
|
+
if (options.force) args.push('--force');
|
|
176
|
+
if (options.installDeps) args.push('--install-deps');
|
|
177
|
+
if (options.apply) args.push('--apply');
|
|
178
|
+
const upgrade = [
|
|
179
|
+
getDlxPrefix(cwd),
|
|
180
|
+
...[`${CLI_PACKAGE}@${to}`, ...args].map(arg => quoteCommandArgument(arg)),
|
|
181
|
+
].join(' ');
|
|
182
|
+
return {cliVersion, command: commandInFolder(folder, upgrade)};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* A folder as the operating system reports it to a process that runs there,
|
|
187
|
+
* with every symbolic link on the way resolved. Falls back to the path as
|
|
188
|
+
* given when it cannot be resolved.
|
|
189
|
+
* @param {string} dir an absolute folder
|
|
190
|
+
* @returns {string}
|
|
191
|
+
*/
|
|
192
|
+
function physicalFolder(dir) {
|
|
193
|
+
try {
|
|
194
|
+
return fs.realpathSync(dir);
|
|
195
|
+
} catch {
|
|
196
|
+
return dir;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
99
200
|
/**
|
|
100
201
|
* @param {(string | null | undefined | false)[] | undefined} files
|
|
101
202
|
* @returns {string[]}
|
|
@@ -332,11 +433,20 @@ export async function ensureCodemodDeps({installDeps} = {}) {
|
|
|
332
433
|
* Run the CORE registry codemods. Runs BEFORE the config is loaded so a core
|
|
333
434
|
* CONFIG codemod can repair a config the strict loader would otherwise reject.
|
|
334
435
|
* @param {CoreVersionManifest[]} versionManifests
|
|
335
|
-
* @param {{apply: boolean, path: string, codemod?: string, skipCodemods: Set<string>, root?: string, protection?: {root: string, classify: (file: string) => import('../../foundation/fs/file-protection.mjs').FileProtection[]}, silent?: boolean}} options
|
|
436
|
+
* @param {{apply: boolean, path: string, codemod?: string, skipCodemods: Set<string>, root?: string, protection?: {root: string, classify: (file: string) => import('../../foundation/fs/file-protection.mjs').FileProtection[]}, silent?: boolean, coversTarget?: boolean}} options
|
|
336
437
|
*/
|
|
337
438
|
export async function runCoreCodemods(
|
|
338
439
|
versionManifests,
|
|
339
|
-
{
|
|
440
|
+
{
|
|
441
|
+
apply,
|
|
442
|
+
path: srcPath,
|
|
443
|
+
codemod,
|
|
444
|
+
skipCodemods,
|
|
445
|
+
root,
|
|
446
|
+
protection,
|
|
447
|
+
silent,
|
|
448
|
+
coversTarget,
|
|
449
|
+
},
|
|
340
450
|
) {
|
|
341
451
|
return runCodemods(versionManifests, {
|
|
342
452
|
apply,
|
|
@@ -346,6 +456,7 @@ export async function runCoreCodemods(
|
|
|
346
456
|
silent: silent ?? logger.silent,
|
|
347
457
|
root,
|
|
348
458
|
protection,
|
|
459
|
+
coversTarget,
|
|
349
460
|
});
|
|
350
461
|
}
|
|
351
462
|
|
|
@@ -367,7 +478,7 @@ export async function loadProjectContext(cwd, extraIntegrationSpecs = []) {
|
|
|
367
478
|
// The CLI debug preflight may already have imported this config before core
|
|
368
479
|
// CONFIG codemods run. Upgrade needs the bytes now on disk, not that module
|
|
369
480
|
// cache entry; ordinary Project discovery remains cached by default.
|
|
370
|
-
const project = await Project.load(cwd, {fresh: true});
|
|
481
|
+
const project = await Project.load(cwd, {fresh: true, core: 'project'});
|
|
371
482
|
const postCodemodHooks = project.config.hooks?.postCodemod ?? [];
|
|
372
483
|
const configuredSpecs = new Set(project.integrations ?? []);
|
|
373
484
|
// Configured packages come from Project, which has already resolved provider
|
|
@@ -411,7 +522,9 @@ export async function loadProjectContext(cwd, extraIntegrationSpecs = []) {
|
|
|
411
522
|
const extras =
|
|
412
523
|
extraSpecs.length === 0
|
|
413
524
|
? []
|
|
414
|
-
:
|
|
525
|
+
: // Resolved from the project, as --integration names a package it
|
|
526
|
+
// installed, not from whichever folder the process started in.
|
|
527
|
+
await loadIntegrations(extraSpecs, {cwd, resolveProviders: false});
|
|
415
528
|
const {integrations, ledger} = resolveProviders(
|
|
416
529
|
[
|
|
417
530
|
...candidates,
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Core codemods ship inside the CLI, so a CLI older than the installed
|
|
5
|
+
* Core has none for the releases after its own version. Every result past the
|
|
6
|
+
* up-to-date exit says so in `cliBehindCore`, with the same upgrade pinned to
|
|
7
|
+
* the CLI release that matches the Core; a CLI that covers the range returns
|
|
8
|
+
* what it always did. The pinned command changes to the folder the run used
|
|
9
|
+
* and names the directory it scanned as an absolute path, both with symbolic
|
|
10
|
+
* links resolved, so a POSIX shell runs it there, with every argument
|
|
11
|
+
* unchanged, wherever it is pasted, even when upgrade() reached the project
|
|
12
|
+
* through a link.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import {describe, it, expect, beforeEach, afterEach, vi} from 'vitest';
|
|
16
|
+
import {execFileSync, spawnSync} from 'node:child_process';
|
|
17
|
+
import * as fs from 'node:fs';
|
|
18
|
+
import * as os from 'node:os';
|
|
19
|
+
import * as path from 'node:path';
|
|
20
|
+
import {upgrade} from '../upgrade.mjs';
|
|
21
|
+
import {logCliBehindCore} from '../status/status.mjs';
|
|
22
|
+
import {logger} from '../../logger.mjs';
|
|
23
|
+
import {CLI_ROOT} from '../../../foundation/fs/paths.mjs';
|
|
24
|
+
import {
|
|
25
|
+
commandInFolder,
|
|
26
|
+
getDlxPrefix,
|
|
27
|
+
quoteCommandArgument,
|
|
28
|
+
} from '../../../foundation/env/package-manager.mjs';
|
|
29
|
+
|
|
30
|
+
const SLOW = 30_000;
|
|
31
|
+
|
|
32
|
+
const CLI_VERSION = JSON.parse(
|
|
33
|
+
fs.readFileSync(path.join(CLI_ROOT, 'package.json'), 'utf8'),
|
|
34
|
+
).version;
|
|
35
|
+
const [MAJOR, MINOR] = CLI_VERSION.split('.').map(Number);
|
|
36
|
+
/** A Core release after this CLI: it has no codemods for it. */
|
|
37
|
+
const NEWER_CORE = `${MAJOR}.${MINOR + 1}.0`;
|
|
38
|
+
|
|
39
|
+
/** A source file a 0.7.0 codemod rewrites (`emptySearchResultsText`). */
|
|
40
|
+
const TYPEAHEAD_SOURCE =
|
|
41
|
+
"import {Typeahead} from '@astryxdesign/core';\n" +
|
|
42
|
+
'export const x = <Typeahead emptySearchResultsText="None" />;\n';
|
|
43
|
+
|
|
44
|
+
let dir;
|
|
45
|
+
|
|
46
|
+
/** @param {string} version @param {string} [packageName] */
|
|
47
|
+
function installCore(version, packageName = '@astryxdesign/core') {
|
|
48
|
+
const core = path.join(dir, 'node_modules', ...packageName.split('/'));
|
|
49
|
+
fs.mkdirSync(core, {recursive: true});
|
|
50
|
+
fs.writeFileSync(
|
|
51
|
+
path.join(core, 'package.json'),
|
|
52
|
+
JSON.stringify({name: packageName, version}),
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** @param {string} rel @param {string} body */
|
|
57
|
+
function write(rel, body) {
|
|
58
|
+
const file = path.join(dir, rel);
|
|
59
|
+
fs.mkdirSync(path.dirname(file), {recursive: true});
|
|
60
|
+
fs.writeFileSync(file, body);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A path in the project as a process running there sees it: every symbolic
|
|
65
|
+
* link resolved.
|
|
66
|
+
* @param {string} rel
|
|
67
|
+
*/
|
|
68
|
+
function inProject(rel) {
|
|
69
|
+
return path.join(fs.realpathSync(dir), rel);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The pinned command for this project, as the CLI prints it.
|
|
74
|
+
* @param {...string} args the arguments after `upgrade`
|
|
75
|
+
*/
|
|
76
|
+
function pinned(...args) {
|
|
77
|
+
return commandInFolder(
|
|
78
|
+
fs.realpathSync(dir),
|
|
79
|
+
[
|
|
80
|
+
getDlxPrefix(dir),
|
|
81
|
+
`@astryxdesign/cli@${NEWER_CORE}`,
|
|
82
|
+
'upgrade',
|
|
83
|
+
...args.map(arg => quoteCommandArgument(arg)),
|
|
84
|
+
].join(' '),
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Stand-ins for the package runners: each prints the folder it runs in and the
|
|
90
|
+
* arguments the shell passed.
|
|
91
|
+
*/
|
|
92
|
+
const RUNNERS = ['npx', 'pnpm', 'yarn', 'bunx']
|
|
93
|
+
.map(
|
|
94
|
+
name =>
|
|
95
|
+
`${name}() { "$0" -e 'process.stdout.write(JSON.stringify({cwd: process.cwd(), argv: process.argv.slice(1)}))' -- "$@"; }`,
|
|
96
|
+
)
|
|
97
|
+
.join('; ');
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* What a POSIX shell runs for `command` pasted in `cwd`: the folder the
|
|
101
|
+
* package runner ran in, and its arguments from the pinned CLI package on.
|
|
102
|
+
* @param {string} command
|
|
103
|
+
* @param {string} cwd the folder the command is pasted in
|
|
104
|
+
* @returns {{cwd: string, args: string[]}}
|
|
105
|
+
*/
|
|
106
|
+
function runInShell(command, cwd) {
|
|
107
|
+
const ran = JSON.parse(
|
|
108
|
+
execFileSync(
|
|
109
|
+
'/bin/sh',
|
|
110
|
+
['-c', `${RUNNERS}; ${command}`, process.execPath],
|
|
111
|
+
{
|
|
112
|
+
cwd,
|
|
113
|
+
encoding: 'utf8',
|
|
114
|
+
},
|
|
115
|
+
),
|
|
116
|
+
);
|
|
117
|
+
return {
|
|
118
|
+
cwd: ran.cwd,
|
|
119
|
+
args: ran.argv.slice(ran.argv.indexOf(`@astryxdesign/cli@${NEWER_CORE}`)),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
beforeEach(() => {
|
|
124
|
+
dir = fs.mkdtempSync(path.join(os.tmpdir(), 'upg-cli-behind-'));
|
|
125
|
+
write('package.json', JSON.stringify({name: 'consumer', version: '1.0.0'}));
|
|
126
|
+
write('src/index.tsx', TYPEAHEAD_SOURCE);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
afterEach(() => fs.rmSync(dir, {recursive: true, force: true}));
|
|
130
|
+
|
|
131
|
+
describe('a CLI older than the installed Core', {timeout: SLOW}, () => {
|
|
132
|
+
// The defect: the range past this CLI has no codemods here, so the run
|
|
133
|
+
// reported `no_codemods` (and "already up to date") and exited 0, while the
|
|
134
|
+
// project still needed the newer releases' migrations.
|
|
135
|
+
it('marks a range this CLI has no codemods for, and names the CLI that does', async () => {
|
|
136
|
+
installCore(NEWER_CORE);
|
|
137
|
+
|
|
138
|
+
const res = await upgrade({from: CLI_VERSION, apply: true}, {cwd: dir});
|
|
139
|
+
|
|
140
|
+
expect(res.type).toBe('upgrade.status');
|
|
141
|
+
expect(res.data.status).toBe('no_codemods');
|
|
142
|
+
expect(res.data.cliBehindCore).toEqual({
|
|
143
|
+
cliVersion: CLI_VERSION,
|
|
144
|
+
command: pinned(
|
|
145
|
+
'--from',
|
|
146
|
+
CLI_VERSION,
|
|
147
|
+
'--path',
|
|
148
|
+
inProject('src'),
|
|
149
|
+
'--apply',
|
|
150
|
+
),
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('runs the codemods it has for a range it covers only in part, and marks the rest', async () => {
|
|
155
|
+
installCore(NEWER_CORE);
|
|
156
|
+
|
|
157
|
+
const res = await upgrade({from: '0.6.8', apply: true}, {cwd: dir});
|
|
158
|
+
|
|
159
|
+
expect(res.type).toBe('upgrade.run');
|
|
160
|
+
expect(res.data.codemods).toBeGreaterThan(0);
|
|
161
|
+
expect(fs.readFileSync(path.join(dir, 'src/index.tsx'), 'utf8')).toContain(
|
|
162
|
+
'emptySearchText="None"',
|
|
163
|
+
);
|
|
164
|
+
expect(res.data.cliBehindCore).toEqual({
|
|
165
|
+
cliVersion: CLI_VERSION,
|
|
166
|
+
command: pinned('--from', '0.6.8', '--path', inProject('src'), '--apply'),
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
it('repeats the invocation in the pinned command', async () => {
|
|
171
|
+
installCore(NEWER_CORE);
|
|
172
|
+
write('my src/index.tsx', TYPEAHEAD_SOURCE);
|
|
173
|
+
// An installed integration the run names, so --integration is repeated.
|
|
174
|
+
write(
|
|
175
|
+
'node_modules/@acme/widgets/package.json',
|
|
176
|
+
JSON.stringify({name: '@acme/widgets', version: '1.0.0'}),
|
|
177
|
+
);
|
|
178
|
+
write(
|
|
179
|
+
'node_modules/@acme/widgets/astryx.integration.mjs',
|
|
180
|
+
'export default {};\n',
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
const res = await upgrade(
|
|
184
|
+
{
|
|
185
|
+
from: CLI_VERSION,
|
|
186
|
+
path: 'my src',
|
|
187
|
+
codemod: 'only-this',
|
|
188
|
+
skipCodemod: ['first', 'second'],
|
|
189
|
+
integration: ['@acme/widgets'],
|
|
190
|
+
force: true,
|
|
191
|
+
installDeps: true,
|
|
192
|
+
},
|
|
193
|
+
{cwd: dir},
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
expect(res.data.cliBehindCore?.command).toBe(
|
|
197
|
+
pinned(
|
|
198
|
+
'--from',
|
|
199
|
+
CLI_VERSION,
|
|
200
|
+
'--path',
|
|
201
|
+
inProject('my src'),
|
|
202
|
+
'--codemod',
|
|
203
|
+
'only-this',
|
|
204
|
+
'--skip-codemod',
|
|
205
|
+
'first',
|
|
206
|
+
'--skip-codemod',
|
|
207
|
+
'second',
|
|
208
|
+
'--integration',
|
|
209
|
+
'@acme/widgets',
|
|
210
|
+
'--force',
|
|
211
|
+
'--install-deps',
|
|
212
|
+
),
|
|
213
|
+
);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Where an upgrade runs decides what it finds: the installed Core is read
|
|
217
|
+
// from that folder, and --path must stay inside it. The command printed
|
|
218
|
+
// without a folder failed when pasted anywhere else: ERR_PATH_TRAVERSAL from
|
|
219
|
+
// a subfolder, ERR_VERSION_DETECT from a parent. A package runner can also
|
|
220
|
+
// move the run: Yarn 1 runs `yarn astryx` at the project root.
|
|
221
|
+
it('changes to the folder the run used and names the directory it scanned as an absolute path', async () => {
|
|
222
|
+
installCore(NEWER_CORE);
|
|
223
|
+
write('app/index.tsx', TYPEAHEAD_SOURCE);
|
|
224
|
+
const project = fs.realpathSync(dir);
|
|
225
|
+
|
|
226
|
+
for (const [given, scanned] of [
|
|
227
|
+
[undefined, inProject('src')],
|
|
228
|
+
['.', project],
|
|
229
|
+
['app', inProject('app')],
|
|
230
|
+
['./app/', inProject('app')],
|
|
231
|
+
]) {
|
|
232
|
+
const res = await upgrade(
|
|
233
|
+
{from: CLI_VERSION, ...(given ? {path: given} : {})},
|
|
234
|
+
{cwd: dir},
|
|
235
|
+
);
|
|
236
|
+
const command = /** @type {string} */ (res.data.cliBehindCore?.command);
|
|
237
|
+
|
|
238
|
+
expect(command).toBe(pinned('--from', CLI_VERSION, '--path', scanned));
|
|
239
|
+
if (process.platform !== 'win32') {
|
|
240
|
+
for (const pastedIn of [
|
|
241
|
+
path.join(dir, 'app'),
|
|
242
|
+
path.dirname(dir),
|
|
243
|
+
path.parse(dir).root,
|
|
244
|
+
]) {
|
|
245
|
+
const ran = runInShell(command, pastedIn);
|
|
246
|
+
expect(ran.cwd).toBe(project);
|
|
247
|
+
expect(ran.args[ran.args.indexOf('--path') + 1]).toBe(scanned);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it.skipIf(process.platform === 'win32')(
|
|
254
|
+
'quotes the command so a POSIX shell enters the folder and passes every argument unchanged',
|
|
255
|
+
async () => {
|
|
256
|
+
fs.rmSync(dir, {recursive: true, force: true});
|
|
257
|
+
dir = fs.mkdtempSync(
|
|
258
|
+
path.join(os.tmpdir(), 'upg cost $5 `date` \'one\' "two" !x -'),
|
|
259
|
+
);
|
|
260
|
+
write(
|
|
261
|
+
'package.json',
|
|
262
|
+
JSON.stringify({name: 'consumer', version: '1.0.0'}),
|
|
263
|
+
);
|
|
264
|
+
write('src/index.tsx', TYPEAHEAD_SOURCE);
|
|
265
|
+
installCore(NEWER_CORE);
|
|
266
|
+
|
|
267
|
+
const res = await upgrade(
|
|
268
|
+
{
|
|
269
|
+
from: CLI_VERSION,
|
|
270
|
+
skipCodemod: ["it's", 'a$b c'],
|
|
271
|
+
apply: true,
|
|
272
|
+
},
|
|
273
|
+
{cwd: dir},
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
const ran = runInShell(
|
|
277
|
+
/** @type {string} */ (res.data.cliBehindCore?.command),
|
|
278
|
+
path.dirname(dir),
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
expect(ran.cwd).toBe(fs.realpathSync(dir));
|
|
282
|
+
expect(ran.args).toEqual([
|
|
283
|
+
`@astryxdesign/cli@${NEWER_CORE}`,
|
|
284
|
+
'upgrade',
|
|
285
|
+
'--from',
|
|
286
|
+
CLI_VERSION,
|
|
287
|
+
'--path',
|
|
288
|
+
inProject('src'),
|
|
289
|
+
'--skip-codemod',
|
|
290
|
+
"it's",
|
|
291
|
+
'--skip-codemod',
|
|
292
|
+
'a$b c',
|
|
293
|
+
'--apply',
|
|
294
|
+
]);
|
|
295
|
+
},
|
|
296
|
+
);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
/** The CLI's own bin, which the stand-in runners below run. */
|
|
300
|
+
const BIN = path.join(CLI_ROOT, 'clients', 'cli', 'bin', 'astryx.mjs');
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Stand-ins for the package runners: each drops its own words and the pinned
|
|
304
|
+
* package, then runs this CLI with the rest of the command.
|
|
305
|
+
*/
|
|
306
|
+
const RUNS_THIS_CLI = /** @type {Array<[string, number]>} */ ([
|
|
307
|
+
['npx', 1],
|
|
308
|
+
['bunx', 1],
|
|
309
|
+
['pnpm', 2],
|
|
310
|
+
['yarn', 2],
|
|
311
|
+
])
|
|
312
|
+
.map(
|
|
313
|
+
([name, words]) =>
|
|
314
|
+
`${name}() { shift ${words}; "$0" ${quoteCommandArgument(BIN)} "$@"; }`,
|
|
315
|
+
)
|
|
316
|
+
.join('; ');
|
|
317
|
+
|
|
318
|
+
// A shell's `cd` follows a symbolic link, but the CLI it starts reads its
|
|
319
|
+
// folder with every link resolved and checks --path against that. A command
|
|
320
|
+
// that kept the link upgrade() was given exited 1 with ERR_PATH_TRAVERSAL.
|
|
321
|
+
describe.skipIf(process.platform === 'win32')(
|
|
322
|
+
'a project upgrade() reaches through a symbolic link',
|
|
323
|
+
{timeout: SLOW},
|
|
324
|
+
() => {
|
|
325
|
+
/** @type {string} */
|
|
326
|
+
let base;
|
|
327
|
+
|
|
328
|
+
beforeEach(() => {
|
|
329
|
+
fs.rmSync(dir, {recursive: true, force: true});
|
|
330
|
+
base = fs.mkdtempSync(path.join(os.tmpdir(), 'upg-link-'));
|
|
331
|
+
dir = path.join(base, 'real', 'my app');
|
|
332
|
+
write(
|
|
333
|
+
'package.json',
|
|
334
|
+
JSON.stringify({name: 'consumer', version: '1.0.0'}),
|
|
335
|
+
);
|
|
336
|
+
write('src/index.tsx', TYPEAHEAD_SOURCE);
|
|
337
|
+
installCore(NEWER_CORE);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
afterEach(() => fs.rmSync(base, {recursive: true, force: true}));
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Run upgrade() from `cwd`, then the command it prints, in /bin/sh, from
|
|
344
|
+
* `cwd` and from the folder above the project.
|
|
345
|
+
* @param {string} cwd
|
|
346
|
+
*/
|
|
347
|
+
async function expectPrintedCommandToRun(cwd) {
|
|
348
|
+
const res = await upgrade({from: CLI_VERSION}, {cwd});
|
|
349
|
+
const command = /** @type {string} */ (res.data.cliBehindCore?.command);
|
|
350
|
+
|
|
351
|
+
for (const pastedIn of [cwd, base]) {
|
|
352
|
+
const ran = spawnSync(
|
|
353
|
+
'/bin/sh',
|
|
354
|
+
['-c', `${RUNS_THIS_CLI}; ${command}`, process.execPath],
|
|
355
|
+
{cwd: pastedIn, encoding: 'utf8'},
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
expect(ran.status, ran.stderr).toBe(0);
|
|
359
|
+
expect(ran.stdout).toContain(`Installed target: ${NEWER_CORE}`);
|
|
360
|
+
expect(ran.stdout).toContain(`Scanning ${inProject('src')} `);
|
|
361
|
+
}
|
|
362
|
+
expect(command).toBe(
|
|
363
|
+
pinned('--from', CLI_VERSION, '--path', inProject('src')),
|
|
364
|
+
);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
it('prints a command that runs, from a folder reached through a link above the project', async () => {
|
|
368
|
+
fs.symlinkSync(path.join(base, 'real'), path.join(base, 'link'), 'dir');
|
|
369
|
+
|
|
370
|
+
await expectPrintedCommandToRun(path.join(base, 'link', 'my app'));
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
it('prints a command that runs, through a project root that is a link', async () => {
|
|
374
|
+
fs.symlinkSync(dir, path.join(base, 'app'), 'dir');
|
|
375
|
+
|
|
376
|
+
await expectPrintedCommandToRun(path.join(base, 'app'));
|
|
377
|
+
});
|
|
378
|
+
},
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
describe('a CLI that covers the range', {timeout: SLOW}, () => {
|
|
382
|
+
it('adds nothing when the installed Core is this CLI release', async () => {
|
|
383
|
+
installCore(CLI_VERSION);
|
|
384
|
+
|
|
385
|
+
const res = await upgrade({from: '0.6.8'}, {cwd: dir});
|
|
386
|
+
|
|
387
|
+
expect(res.type).toBe('upgrade.run');
|
|
388
|
+
expect('cliBehindCore' in res.data).toBe(false);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it('adds nothing when --from is already the installed Core', async () => {
|
|
392
|
+
installCore(NEWER_CORE);
|
|
393
|
+
|
|
394
|
+
const res = await upgrade({from: NEWER_CORE}, {cwd: dir});
|
|
395
|
+
|
|
396
|
+
expect(res.data.status).toBe('up_to_date');
|
|
397
|
+
expect('cliBehindCore' in res.data).toBe(false);
|
|
398
|
+
|
|
399
|
+
const forced = await upgrade({from: NEWER_CORE, force: true}, {cwd: dir});
|
|
400
|
+
|
|
401
|
+
expect(forced.data.status).toBe('no_codemods');
|
|
402
|
+
expect('cliBehindCore' in forced.data).toBe(false);
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
it('adds nothing for legacy @xds/core, which shares no version with a CLI release', async () => {
|
|
406
|
+
installCore(NEWER_CORE, '@xds/core');
|
|
407
|
+
|
|
408
|
+
const res = await upgrade({from: CLI_VERSION}, {cwd: dir});
|
|
409
|
+
|
|
410
|
+
expect(res.data.status).toBe('no_codemods');
|
|
411
|
+
expect('cliBehindCore' in res.data).toBe(false);
|
|
412
|
+
});
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
describe('logCliBehindCore: the warning names the shell its command is written for', () => {
|
|
416
|
+
it.each([
|
|
417
|
+
['win32', 'Run it in PowerShell with the CLI that matches your Core:'],
|
|
418
|
+
['linux', 'Run it with the CLI that matches your Core:'],
|
|
419
|
+
['darwin', 'Run it with the CLI that matches your Core:'],
|
|
420
|
+
])('on %s', (platform, ending) => {
|
|
421
|
+
const warn = vi.spyOn(logger, 'warn').mockImplementation(() => {});
|
|
422
|
+
try {
|
|
423
|
+
logCliBehindCore(
|
|
424
|
+
{cliVersion: '0.7.0', command: 'cd x; npx y'},
|
|
425
|
+
'0.8.0',
|
|
426
|
+
platform,
|
|
427
|
+
);
|
|
428
|
+
expect(warn.mock.calls.map(([line]) => String(line))).toEqual([
|
|
429
|
+
expect.stringMatching(
|
|
430
|
+
new RegExp(`${ending.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&')}$`, 'u'),
|
|
431
|
+
),
|
|
432
|
+
' cd x; npx y',
|
|
433
|
+
]);
|
|
434
|
+
} finally {
|
|
435
|
+
warn.mockRestore();
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
});
|