@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
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file `astryx upgrade` with a CLI older than the installed Core: the human
|
|
5
|
+
* output never says the code is up to date, warns once with the same upgrade
|
|
6
|
+
* pinned to the CLI release that matches the Core, and keeps the exit status;
|
|
7
|
+
* `--json` carries the same facts in `cliBehindCore`. Pasted anywhere, the
|
|
8
|
+
* printed command runs that upgrade in the same project.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {describe, it, expect, beforeEach, afterEach} from 'vitest';
|
|
12
|
+
import {spawnSync} from 'node:child_process';
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as os from 'node:os';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
import {runCli} from '../../../test-utils/run-cli.mjs';
|
|
17
|
+
import {CLI_ROOT} from '../../../foundation/fs/paths.mjs';
|
|
18
|
+
import {
|
|
19
|
+
commandInFolder,
|
|
20
|
+
getDlxPrefix,
|
|
21
|
+
quoteCommandArgument,
|
|
22
|
+
} from '../../../foundation/env/package-manager.mjs';
|
|
23
|
+
|
|
24
|
+
const CLI_VERSION = JSON.parse(
|
|
25
|
+
fs.readFileSync(path.join(CLI_ROOT, 'package.json'), 'utf8'),
|
|
26
|
+
).version;
|
|
27
|
+
const [MAJOR, MINOR] = CLI_VERSION.split('.').map(Number);
|
|
28
|
+
const NEWER_CORE = `${MAJOR}.${MINOR + 1}.0`;
|
|
29
|
+
const NON_ASCII = /[\u0080-\uFFFF]/;
|
|
30
|
+
|
|
31
|
+
let tmpDir;
|
|
32
|
+
|
|
33
|
+
/** @param {string} rel @param {string} body */
|
|
34
|
+
function write(rel, body) {
|
|
35
|
+
const file = path.join(tmpDir, rel);
|
|
36
|
+
fs.mkdirSync(path.dirname(file), {recursive: true});
|
|
37
|
+
fs.writeFileSync(file, body);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'astryx-upgrade-older-cli-'));
|
|
42
|
+
write('package.json', JSON.stringify({name: 'consumer', private: true}));
|
|
43
|
+
write(
|
|
44
|
+
'node_modules/@astryxdesign/core/package.json',
|
|
45
|
+
JSON.stringify({name: '@astryxdesign/core', version: NEWER_CORE}),
|
|
46
|
+
);
|
|
47
|
+
write('src/index.ts', 'export const x = 1;\n');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
afterEach(() => {
|
|
51
|
+
fs.rmSync(tmpDir, {recursive: true, force: true});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The pinned command the CLI prints for this project. It names the folder the
|
|
56
|
+
* CLI ran in and the source directory as the CLI resolved them.
|
|
57
|
+
* @param {...string} rest the arguments after `--path <dir>`
|
|
58
|
+
*/
|
|
59
|
+
function pinned(...rest) {
|
|
60
|
+
const project = fs.realpathSync(tmpDir);
|
|
61
|
+
return commandInFolder(
|
|
62
|
+
project,
|
|
63
|
+
[
|
|
64
|
+
getDlxPrefix(tmpDir),
|
|
65
|
+
`@astryxdesign/cli@${NEWER_CORE}`,
|
|
66
|
+
'upgrade',
|
|
67
|
+
'--from',
|
|
68
|
+
CLI_VERSION,
|
|
69
|
+
'--path',
|
|
70
|
+
quoteCommandArgument(path.join(project, 'src')),
|
|
71
|
+
...rest,
|
|
72
|
+
].join(' '),
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Stand-ins for the package runners: each drops its own words and the pinned
|
|
78
|
+
* package, then runs this CLI with the rest of the command.
|
|
79
|
+
*/
|
|
80
|
+
const RUNS_THIS_CLI = [
|
|
81
|
+
['npx', 1],
|
|
82
|
+
['bunx', 1],
|
|
83
|
+
['pnpm', 2],
|
|
84
|
+
['yarn', 2],
|
|
85
|
+
]
|
|
86
|
+
.map(
|
|
87
|
+
([name, words]) =>
|
|
88
|
+
`${name}() { shift ${words}; "$0" ${quoteCommandArgument(path.join(CLI_ROOT, 'clients', 'cli', 'bin', 'astryx.mjs'))} "$@"; }`,
|
|
89
|
+
)
|
|
90
|
+
.join('; ');
|
|
91
|
+
|
|
92
|
+
describe('astryx upgrade with a CLI older than the installed Core', () => {
|
|
93
|
+
it('says it cannot finish and prints the upgrade pinned to the matching CLI', async () => {
|
|
94
|
+
const r = await runCli(['upgrade', '--from', CLI_VERSION, '--apply'], {
|
|
95
|
+
cwd: tmpDir,
|
|
96
|
+
});
|
|
97
|
+
const output = `${r.stdout}\n${r.stderr}`;
|
|
98
|
+
|
|
99
|
+
expect(r.status).toBe(0);
|
|
100
|
+
expect(output).not.toMatch(/up to date/i);
|
|
101
|
+
expect(output).not.toContain('No codemods available');
|
|
102
|
+
expect(r.stderr).toContain(
|
|
103
|
+
`This CLI (${CLI_VERSION}) is older than the installed @astryxdesign/core (${NEWER_CORE})`,
|
|
104
|
+
);
|
|
105
|
+
// The command has a line of its own, so it copies exactly.
|
|
106
|
+
expect(r.stderr).toContain(
|
|
107
|
+
`the CLI that matches your Core:\n ${pinned('--apply')}\n`,
|
|
108
|
+
);
|
|
109
|
+
expect(r.stdout.trim().split('\n').at(-1)).toBe('Upgrade incomplete');
|
|
110
|
+
expect(output.split('\n').filter(line => NON_ASCII.test(line))).toEqual([]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('carries cliBehindCore in --json with the same exit status', async () => {
|
|
114
|
+
const r = await runCli(['--json', 'upgrade', '--from', CLI_VERSION], {
|
|
115
|
+
cwd: tmpDir,
|
|
116
|
+
});
|
|
117
|
+
const parsed = JSON.parse(r.stdout);
|
|
118
|
+
|
|
119
|
+
expect(r.status).toBe(0);
|
|
120
|
+
expect(parsed.type).toBe('upgrade.status');
|
|
121
|
+
expect(parsed.data.status).toBe('no_codemods');
|
|
122
|
+
expect(parsed.data.cliBehindCore).toEqual({
|
|
123
|
+
cliVersion: CLI_VERSION,
|
|
124
|
+
command: pinned(),
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Where an upgrade runs decides what it finds: the installed Core is read
|
|
129
|
+
// from that folder, and --path must stay inside it. Printed without its
|
|
130
|
+
// folder, the command exited 1 when pasted in a subfolder
|
|
131
|
+
// (ERR_PATH_TRAVERSAL) or in the folder above (ERR_VERSION_DETECT).
|
|
132
|
+
it.skipIf(process.platform === 'win32')(
|
|
133
|
+
'prints a command that upgrades the same project wherever it is pasted',
|
|
134
|
+
async () => {
|
|
135
|
+
write('src/deep/index.ts', 'export const y = 2;\n');
|
|
136
|
+
const r = await runCli(['--json', 'upgrade', '--from', CLI_VERSION], {
|
|
137
|
+
cwd: tmpDir,
|
|
138
|
+
});
|
|
139
|
+
const {command} = JSON.parse(r.stdout).data.cliBehindCore;
|
|
140
|
+
|
|
141
|
+
for (const pastedIn of [
|
|
142
|
+
path.join(tmpDir, 'src', 'deep'),
|
|
143
|
+
path.dirname(tmpDir),
|
|
144
|
+
]) {
|
|
145
|
+
const ran = spawnSync(
|
|
146
|
+
'/bin/sh',
|
|
147
|
+
['-c', `${RUNS_THIS_CLI}; ${command}`, process.execPath],
|
|
148
|
+
{cwd: pastedIn, encoding: 'utf8'},
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
expect(ran.status, ran.stderr).toBe(0);
|
|
152
|
+
expect(ran.stdout).toContain(`Installed target: ${NEWER_CORE}`);
|
|
153
|
+
expect(ran.stdout).toContain(
|
|
154
|
+
`Scanning ${path.join(fs.realpathSync(tmpDir), 'src')} `,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
30_000,
|
|
159
|
+
);
|
|
160
|
+
});
|
package/clients/cli/index.mjs
CHANGED
|
@@ -16,8 +16,14 @@ import {Command, Option} from 'commander';
|
|
|
16
16
|
import {fileURLToPath} from 'node:url';
|
|
17
17
|
import * as fs from 'node:fs';
|
|
18
18
|
import * as path from 'node:path';
|
|
19
|
-
import {getCliInvocation} from '../../foundation/env/package-manager.mjs';
|
|
19
|
+
import {formatCliCommand, getCliInvocation} from '../../foundation/env/package-manager.mjs';
|
|
20
|
+
import {hasRecordedProject} from '../../foundation/env/cli-command.mjs';
|
|
21
|
+
import {isOutsideProject} from '../../foundation/env/project-scope.mjs';
|
|
20
22
|
import {API_VERSION, setJsonMode} from '../../foundation/response/json.mjs';
|
|
23
|
+
import {answeredBy, runChoice} from '../../foundation/release/run-context.mjs';
|
|
24
|
+
import {addCliCommand} from '../../foundation/release/notices.mjs';
|
|
25
|
+
import {projectRootOf} from '../../foundation/release/choose.mjs';
|
|
26
|
+
import {readReleaseFacts} from '../../foundation/release/project.mjs';
|
|
21
27
|
import {buildManifest} from './lib/manifest.mjs';
|
|
22
28
|
import {cliError} from './lib/cli-error.mjs';
|
|
23
29
|
import {emit, section, text, records} from './formatters/index.mjs';
|
|
@@ -26,7 +32,9 @@ import {levenshteinDistance} from '../../foundation/text/string-utils.mjs';
|
|
|
26
32
|
import {installJsonShim} from './lib/json-shim.mjs';
|
|
27
33
|
import {addDocHelp, markReportsResult} from './lib/define-command.mjs';
|
|
28
34
|
import {doc as manifestDoc} from './commands/manifest.doc.mjs';
|
|
29
|
-
import {isAstryxInitialized} from '../../foundation/agent-docs/agent-docs.mjs';
|
|
35
|
+
import {isAstryxInitialized, isAstryxPromptInReach} from '../../foundation/agent-docs/agent-docs.mjs';
|
|
36
|
+
import {CLI_ROOT} from '../../foundation/fs/paths.mjs';
|
|
37
|
+
import {setupNudge} from '../../foundation/agent-docs/agent-doc-state.mjs';
|
|
30
38
|
import * as debug from '../../foundation/debug/index.mjs';
|
|
31
39
|
|
|
32
40
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -63,7 +71,7 @@ export function handleVersionJsonPreflight(argv = process.argv.slice(2)) {
|
|
|
63
71
|
// reports the same shape Commander's own `--version` path does.
|
|
64
72
|
debug.recordCommandResult(debug.NO_RESULT_SET);
|
|
65
73
|
debug.setOutcome('ok', {exitCode: 0});
|
|
66
|
-
console.log(JSON.stringify({apiVersion: API_VERSION, type: 'version', data: {version: pkg.version}}, null, 2));
|
|
74
|
+
console.log(JSON.stringify({apiVersion: API_VERSION, type: 'version', data: {version: pkg.version}, meta: {answeredBy: answeredBy()}}, null, 2));
|
|
67
75
|
process.exit(0);
|
|
68
76
|
}
|
|
69
77
|
|
|
@@ -98,6 +106,7 @@ export const JSON_SUPPORTED = new Set([
|
|
|
98
106
|
'theme targets',
|
|
99
107
|
'theme palette generate',
|
|
100
108
|
'integration add',
|
|
109
|
+
'integration check',
|
|
101
110
|
'integration verify',
|
|
102
111
|
'integration pack',
|
|
103
112
|
'upgrade',
|
|
@@ -184,6 +193,31 @@ export async function loadProjectDebugHandler() {
|
|
|
184
193
|
}
|
|
185
194
|
}
|
|
186
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Load the project's integrations before a help run, so help prints commands
|
|
198
|
+
* with the `cliCommand` they declare (spec:AST-081 FR5). Help is printed while
|
|
199
|
+
* Commander parses, before any hook, so the preAction load cannot reach it.
|
|
200
|
+
* `Project.load` reads astryx.config and each integration's manifest; it does
|
|
201
|
+
* no discovery. Skipped when the debug preload already loaded the project, and
|
|
202
|
+
* outside a package. Called from the bin before Commander parses.
|
|
203
|
+
*
|
|
204
|
+
* @param {string[]} [argv] arguments after the binary.
|
|
205
|
+
* @returns {Promise<void>}
|
|
206
|
+
*/
|
|
207
|
+
export async function loadProjectForHelp(argv = process.argv.slice(2)) {
|
|
208
|
+
const help =
|
|
209
|
+
argv.includes('--help') || argv.includes('-h') || argv[0] === 'help';
|
|
210
|
+
if (!help) return;
|
|
211
|
+
try {
|
|
212
|
+
const cwd = process.cwd();
|
|
213
|
+
if (hasRecordedProject(cwd)) return;
|
|
214
|
+
const {Project} = await import('../../foundation/config/project.mjs');
|
|
215
|
+
await Project.load(cwd);
|
|
216
|
+
} catch {
|
|
217
|
+
// Help prints with the package-manager guess.
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
187
221
|
/**
|
|
188
222
|
* Hand the whole invocation to the debug recorder: which command ran, its
|
|
189
223
|
* positional arguments by name, its options and where each value came from,
|
|
@@ -276,6 +310,26 @@ const commands = [
|
|
|
276
310
|
];
|
|
277
311
|
|
|
278
312
|
const SETUP_NUDGE_EXEMPT = new Set(['init', 'agent-docs']);
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Is `cwd` inside the CLI's own source checkout while the CLI runs from it?
|
|
316
|
+
* An installed CLI always lives under `node_modules`; a CLI running from source
|
|
317
|
+
* does not, and its checkout is the pnpm workspace that holds it. Developing
|
|
318
|
+
* Astryx is not an app to set up, so the setup nudge stays quiet there.
|
|
319
|
+
* @param {string} cwd
|
|
320
|
+
* @returns {boolean}
|
|
321
|
+
*/
|
|
322
|
+
function inOwnSourceCheckout(cwd) {
|
|
323
|
+
if (CLI_ROOT.split(path.sep).includes('node_modules')) return false;
|
|
324
|
+
let checkout = CLI_ROOT;
|
|
325
|
+
while (!fs.existsSync(path.join(checkout, 'pnpm-workspace.yaml'))) {
|
|
326
|
+
const parent = path.dirname(checkout);
|
|
327
|
+
if (parent === checkout) return false;
|
|
328
|
+
checkout = parent;
|
|
329
|
+
}
|
|
330
|
+
const rel = path.relative(checkout, path.resolve(cwd));
|
|
331
|
+
return rel !== '..' && !rel.startsWith(`..${path.sep}`) && !path.isAbsolute(rel);
|
|
332
|
+
}
|
|
279
333
|
/** An integration package's manifest: the package is not an app to set up. */
|
|
280
334
|
const INTEGRATION_MANIFEST_FILES = [
|
|
281
335
|
'astryx.integration.ts',
|
|
@@ -307,7 +361,8 @@ export async function createProgram() {
|
|
|
307
361
|
// kit in clients/cli/formatters.
|
|
308
362
|
program.addHelpText(
|
|
309
363
|
'after',
|
|
310
|
-
|
|
364
|
+
// A function, so the example names the invocation when help is printed.
|
|
365
|
+
() => '\n' +
|
|
311
366
|
[
|
|
312
367
|
section(
|
|
313
368
|
'Output format',
|
|
@@ -330,9 +385,13 @@ export async function createProgram() {
|
|
|
330
385
|
{fields: ['block', 'shape']},
|
|
331
386
|
),
|
|
332
387
|
text(
|
|
333
|
-
|
|
388
|
+
`Grep a field across records, e.g. ${formatCliCommand('search button')} | grep "^command:". ` +
|
|
334
389
|
'Errors/warnings go to stderr; use --json for structured parsing.',
|
|
335
390
|
),
|
|
391
|
+
text(
|
|
392
|
+
"Global mode: in a project, the project's own CLI answers (this copy hands the run to it); a copy installed for the computer checks for updates once a day and keeps an agent skill in your home folder. " +
|
|
393
|
+
`See ${formatCliCommand('docs global')}.`,
|
|
394
|
+
),
|
|
336
395
|
]
|
|
337
396
|
.map(block => block.toString())
|
|
338
397
|
.join('\n\n'),
|
|
@@ -429,6 +488,7 @@ export async function createProgram() {
|
|
|
429
488
|
// Enriched, self-describing surface (the full manifest payload).
|
|
430
489
|
manifest,
|
|
431
490
|
},
|
|
491
|
+
meta: {answeredBy: answeredBy()},
|
|
432
492
|
}, null, 2));
|
|
433
493
|
debug.recordCommandResult(
|
|
434
494
|
debug.resultSet({
|
|
@@ -525,10 +585,29 @@ export async function createProgram() {
|
|
|
525
585
|
process.exit(1);
|
|
526
586
|
});
|
|
527
587
|
|
|
588
|
+
/**
|
|
589
|
+
* Load the project's integrations before any command runs, so every command
|
|
590
|
+
* it prints starts with the `cliCommand` they declare (the picker reads them
|
|
591
|
+
* synchronously; see foundation/env/cli-command.mjs). Skipped when this
|
|
592
|
+
* process already loaded the project, such as the bin's debug preload. A
|
|
593
|
+
* project that cannot load is the command's to report, never this hook's.
|
|
594
|
+
*/
|
|
595
|
+
program.hook('preAction', async () => {
|
|
596
|
+
try {
|
|
597
|
+
const cwd = process.cwd();
|
|
598
|
+
if (hasRecordedProject(cwd)) return;
|
|
599
|
+
const {Project} = await import('../../foundation/config/project.mjs');
|
|
600
|
+
await Project.load(cwd);
|
|
601
|
+
} catch {
|
|
602
|
+
// Best-effort: the picker falls back to its package-manager guess.
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
|
|
528
606
|
/**
|
|
529
607
|
* Enforcement layer 3 — setup nudge. If this project hasn't run `astryx init`
|
|
530
|
-
* yet (no Astryx marker in any agent-doc file
|
|
531
|
-
* the user/agent that
|
|
608
|
+
* yet (no Astryx marker in any agent-doc file between the project and its
|
|
609
|
+
* repository root — see isAstryxPromptInReach), remind the user/agent that
|
|
610
|
+
* setup is missing.
|
|
532
611
|
*
|
|
533
612
|
* Uses `preAction` (not postAction) so it fires for EVERY valid command — even
|
|
534
613
|
* ones whose action errors or calls process.exit (postAction is skipped then).
|
|
@@ -538,7 +617,9 @@ export async function createProgram() {
|
|
|
538
617
|
* consumers parse stdout, not stderr — a stderr nudge would not reach them anyway.
|
|
539
618
|
* The core/cli postinstall layers already nudge at install time regardless of
|
|
540
619
|
* --json; a machine-readable nudge could later be an envelope field. Also skipped
|
|
541
|
-
* for the installer commands themselves
|
|
620
|
+
* for the installer commands themselves, outside a project (no package.json,
|
|
621
|
+
* or one that neither installs nor declares Astryx), and inside the CLI's own
|
|
622
|
+
* source checkout when it runs from there.
|
|
542
623
|
*/
|
|
543
624
|
program.hook('preAction', (thisCommand, actionCommand) => {
|
|
544
625
|
try {
|
|
@@ -546,15 +627,30 @@ export async function createProgram() {
|
|
|
546
627
|
if (SETUP_NUDGE_EXEMPT.has(actionCommand.name())) return;
|
|
547
628
|
const cwd = process.cwd();
|
|
548
629
|
if (!fs.existsSync(path.join(cwd, 'package.json'))) return; // not a project
|
|
630
|
+
// A package.json that neither installs nor declares Astryx is outside a
|
|
631
|
+
// project: `init` would set up a project the folder does not have
|
|
632
|
+
// (spec AST-081 FR3).
|
|
633
|
+
if (isOutsideProject(cwd)) return;
|
|
549
634
|
// An integration package is not an app: `init` is not its next step.
|
|
550
635
|
if (INTEGRATION_MANIFEST_FILES.some(file => fs.existsSync(path.join(cwd, file)))) return;
|
|
551
|
-
if (
|
|
552
|
-
|
|
553
|
-
//
|
|
554
|
-
//
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
636
|
+
if (inOwnSourceCheckout(cwd)) return; // developing Astryx itself, not an app
|
|
637
|
+
if (isAstryxPromptInReach(cwd)) return; // already set up — stay quiet
|
|
638
|
+
// Same wording as the core/cli postinstall nudges. getCliInvocation()
|
|
639
|
+
// renders the correct form for THIS project — an integration's cliCommand,
|
|
640
|
+
// scoped `npx @astryxdesign/cli` one-off, or `<pm> astryx` when installed —
|
|
641
|
+
// never npx with the unscoped name, which fetches an unrelated package.
|
|
642
|
+
// A project with no CLI of its own, answered by another release than its
|
|
643
|
+
// Core's: add the CLI at Core's version first, as the daily hint says,
|
|
644
|
+
// then run that CLI's init (spec AST-081 FR2).
|
|
645
|
+
const choice = runChoice(cwd);
|
|
646
|
+
if (choice.copy === 'starting' && choice.coreVersion && choice.coreVersion !== choice.version) {
|
|
647
|
+
const root = projectRootOf(readReleaseFacts(cwd)) ?? cwd;
|
|
648
|
+
console.error(
|
|
649
|
+
setupNudge(getCliInvocation(root, {installed: true}), {before: addCliCommand(root, choice.coreVersion)}).trimEnd(),
|
|
650
|
+
);
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
console.error(setupNudge(getCliInvocation(cwd)).trimEnd());
|
|
558
654
|
} catch {
|
|
559
655
|
// Never let the nudge break a command.
|
|
560
656
|
}
|
|
@@ -607,7 +703,7 @@ export async function createProgram() {
|
|
|
607
703
|
);
|
|
608
704
|
if (program.opts().json) {
|
|
609
705
|
process.__xdsJsonHandled = true;
|
|
610
|
-
console.log(JSON.stringify({apiVersion: API_VERSION, type: 'manifest', data: manifest}, null, 2));
|
|
706
|
+
console.log(JSON.stringify({apiVersion: API_VERSION, type: 'manifest', data: manifest, meta: {answeredBy: answeredBy()}}, null, 2));
|
|
611
707
|
return;
|
|
612
708
|
}
|
|
613
709
|
// Human-readable summary as greppable records (agents should use --json).
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
import {isJsonMode, jsonError as _jsonError, humanWarn} from '../../../foundation/response/json.mjs';
|
|
54
54
|
import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
|
|
55
55
|
import {setOutcome} from '../../../foundation/debug/index.mjs';
|
|
56
|
+
import {formatCliCommand} from '../../../foundation/env/package-manager.mjs';
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
59
|
* Suggestion object — matches the shape used by API errors and the JSON
|
|
@@ -122,7 +123,9 @@ export function cliError(message, options = {}) {
|
|
|
122
123
|
if (suggestions?.length) {
|
|
123
124
|
console.error('');
|
|
124
125
|
for (const s of suggestions) {
|
|
125
|
-
|
|
126
|
+
// A suggested command stays bare in JSON and is prefixed here.
|
|
127
|
+
const name = /^astryx(\s|$)/.test(s.name) ? formatCliCommand(s.name) : s.name;
|
|
128
|
+
const tag = s.reason ? ` ${name} (${s.reason})` : ` ${name}`;
|
|
126
129
|
console.error(tag);
|
|
127
130
|
}
|
|
128
131
|
}
|
|
@@ -67,7 +67,7 @@ describe('formatFull sub-component rendering', () => {
|
|
|
67
67
|
expect(out).not.toContain('undefined');
|
|
68
68
|
// Points the reader at the sub-component's own docs instead of a blank.
|
|
69
69
|
expect(out).toMatch(
|
|
70
|
-
/(?:astryx|@astryxdesign\/cli) component XDSRadioListItem/,
|
|
70
|
+
/(?:astryx|@astryxdesign\/cli(?:@\S+)?) component XDSRadioListItem/,
|
|
71
71
|
);
|
|
72
72
|
});
|
|
73
73
|
|
|
@@ -180,8 +180,8 @@ export function defineCommand(parent, doc, {fn, action} = {}) {
|
|
|
180
180
|
*/
|
|
181
181
|
export function addDocHelp(cmd, doc) {
|
|
182
182
|
addExitCodesHelp(cmd, doc.exitCodes);
|
|
183
|
-
// Rendered when help is shown, so the run prefix (
|
|
184
|
-
// ...) is looked up then, not on every start.
|
|
183
|
+
// Rendered when help is shown, so the run prefix (pnpm exec astryx, yarn
|
|
184
|
+
// astryx, ...) is looked up then, not on every start.
|
|
185
185
|
cmd.addHelpText('after', () => {
|
|
186
186
|
const examples = (doc.examples ?? []).flatMap(({label, cli}) => [
|
|
187
187
|
...(label ? [` # ${label}`] : []),
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
*/
|
|
43
43
|
|
|
44
44
|
import {API_VERSION, isJsonMode, toErrorEnvelope} from '../../../foundation/response/json.mjs';
|
|
45
|
+
import {answeredBy} from '../../../foundation/release/run-context.mjs';
|
|
45
46
|
import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
|
|
46
47
|
import {setCommand, setOutcome, recordHelp} from '../../../foundation/debug/index.mjs';
|
|
47
48
|
|
|
@@ -84,7 +85,7 @@ function jsonActive() {
|
|
|
84
85
|
* subcommand (e.g. `astryx component --help --json`).
|
|
85
86
|
*
|
|
86
87
|
* @param {import('commander').Command} cmd
|
|
87
|
-
* @returns {{apiVersion: number, type: 'help', data: object}}
|
|
88
|
+
* @returns {{apiVersion: number, type: 'help', data: object, meta: {answeredBy: {cli: string, core: string | null, copy: 'project' | 'starting' | 'matched' | 'carried' | 'fallback'}}}}
|
|
88
89
|
*/
|
|
89
90
|
export function buildHelpEnvelope(cmd) {
|
|
90
91
|
// Reconstruct the fully-qualified command name (e.g. "astryx theme build").
|
|
@@ -119,6 +120,7 @@ export function buildHelpEnvelope(cmd) {
|
|
|
119
120
|
options,
|
|
120
121
|
subcommands,
|
|
121
122
|
},
|
|
123
|
+
meta: {answeredBy: answeredBy()},
|
|
122
124
|
};
|
|
123
125
|
}
|
|
124
126
|
|
|
@@ -50,6 +50,13 @@ export interface ManifestCommand {
|
|
|
50
50
|
examples?: string[];
|
|
51
51
|
/** Documented exit codes: the process exit status and when it occurs. */
|
|
52
52
|
exitCodes?: {code: number; when: string}[];
|
|
53
|
+
/**
|
|
54
|
+
* What the command does in a folder outside any project: `same` gives the
|
|
55
|
+
* answer it gives in a new project; `refuse` writes nothing and fails, naming
|
|
56
|
+
* the app project or integration package it needs; `own` does something
|
|
57
|
+
* else, which its docs state. Absent on a group that only holds subcommands.
|
|
58
|
+
*/
|
|
59
|
+
outsideProject?: 'same' | 'refuse' | 'own';
|
|
53
60
|
/** Nested subcommands (e.g. `theme build` under `theme`). */
|
|
54
61
|
subcommands?: ManifestCommand[];
|
|
55
62
|
}
|
|
@@ -64,6 +71,8 @@ export interface CLIManifest {
|
|
|
64
71
|
commands: ManifestCommand[];
|
|
65
72
|
/** Sorted list of fully-qualified command names that support `--json`. */
|
|
66
73
|
jsonSupported: string[];
|
|
74
|
+
/** What a run may do beyond its command (the hand-off, the daily update check, the agent skill), and the docs topic that explains it. */
|
|
75
|
+
globalMode: {docs: string; summary: string};
|
|
67
76
|
/** Flat index of response `type` discriminators keyed by command name. */
|
|
68
77
|
responseTypes: Record<string, string[]>;
|
|
69
78
|
}
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
*
|
|
10
10
|
* Its per-command facts come from the command's own definitions: names,
|
|
11
11
|
* arguments and options from Commander metadata (program.commands, cmd.options,
|
|
12
|
-
* cmd.registeredArguments, cmd.description()); examples
|
|
12
|
+
* cmd.registeredArguments, cmd.description()); examples, exit codes, and what
|
|
13
|
+
* it does outside a project from its CommandDoc;
|
|
13
14
|
* response `type` discriminators from the returns of the FunctionDoc it wraps
|
|
14
15
|
* (both attached by `defineCommand`); `--json` support from the JSON_SUPPORTED
|
|
15
16
|
* allowlist in index.mjs. The hand-kept lists are CLI_LAYER_RESPONSE_TYPES,
|
|
@@ -39,6 +40,16 @@ import {API_VERSION} from '../../../foundation/response/json.mjs';
|
|
|
39
40
|
import {commandDocsOf} from './define-command.mjs';
|
|
40
41
|
import {doc as manifestDoc} from '../commands/manifest.doc.mjs';
|
|
41
42
|
|
|
43
|
+
/**
|
|
44
|
+
* What a run may do beyond the command it was asked for (spec AST-081;
|
|
45
|
+
* `spec:AST-017` FR14), and where it is explained.
|
|
46
|
+
*/
|
|
47
|
+
export const GLOBAL_MODE = Object.freeze({
|
|
48
|
+
docs: 'astryx docs global',
|
|
49
|
+
summary:
|
|
50
|
+
"In a folder that belongs to a project, the project's own CLI answers: this copy hands the run to it. In a project with no CLI of its own, and outside any project, this copy answers. A copy installed for the computer checks the registry for a newer release once a day in the background, and keeps one agent skill file in the home folder.",
|
|
51
|
+
});
|
|
52
|
+
|
|
42
53
|
/**
|
|
43
54
|
* Envelopes the CLI layer builds itself, so the wrapped FunctionDoc cannot
|
|
44
55
|
* declare them: `manifest` wraps no API function, `theme build` batches several
|
|
@@ -194,6 +205,10 @@ function describeCommand(cmd, root, jsonSupported) {
|
|
|
194
205
|
}));
|
|
195
206
|
if (exitCodes.length > 0) entry.exitCodes = exitCodes;
|
|
196
207
|
|
|
208
|
+
// What the command does outside a project (spec AST-081 FR4). Every command
|
|
209
|
+
// declares it in its CommandDoc; a group that only holds subcommands does not.
|
|
210
|
+
if (docs?.doc.outsideProject) entry.outsideProject = docs.doc.outsideProject;
|
|
211
|
+
|
|
197
212
|
// Sort subcommands by name for a stable, agent-facing contract — the same
|
|
198
213
|
// guarantee the top-level command list makes. Otherwise Commander
|
|
199
214
|
// registration order leaks into the manifest and a pure reorder of
|
|
@@ -265,6 +280,7 @@ export function buildManifest(program, opts = {}) {
|
|
|
265
280
|
globalOptions: describeGlobalOptions(program),
|
|
266
281
|
commands,
|
|
267
282
|
jsonSupported: [...jsonSupported].sort(),
|
|
283
|
+
globalMode: GLOBAL_MODE,
|
|
268
284
|
// Flat index of every response `type` discriminator the CLI can emit,
|
|
269
285
|
// keyed by command — lets an agent know what to expect back per call.
|
|
270
286
|
responseTypes: Object.fromEntries(
|
|
@@ -307,3 +307,28 @@ describe('manifest: text projection', () => {
|
|
|
307
307
|
for (const key of textKeys) expect(jsonKeys).toContain(key);
|
|
308
308
|
});
|
|
309
309
|
});
|
|
310
|
+
|
|
311
|
+
describe('global mode is discoverable (spec:AST-017 FR14)', () => {
|
|
312
|
+
it('the manifest names what a run may do beyond its command, and the docs topic that explains it', () => {
|
|
313
|
+
expect(manifest.globalMode.docs).toBe('astryx docs global');
|
|
314
|
+
for (const word of ['hands the run', 'once a day', 'agent skill']) {
|
|
315
|
+
expect(manifest.globalMode.summary).toContain(word);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
it('--help carries one line pointing to the global mode docs', () => {
|
|
320
|
+
const help = program.helpInformation() + '';
|
|
321
|
+
let after = '';
|
|
322
|
+
program.emit('afterHelp', {
|
|
323
|
+
error: false,
|
|
324
|
+
write: (/** @type {string} */ s) => {
|
|
325
|
+
after += s;
|
|
326
|
+
},
|
|
327
|
+
});
|
|
328
|
+
const lines = `${help}${after}`
|
|
329
|
+
.split('\n')
|
|
330
|
+
.filter(line => line.startsWith('Global mode:'));
|
|
331
|
+
expect(lines).toHaveLength(1);
|
|
332
|
+
expect(lines[0]).toMatch(/docs global\.$/u);
|
|
333
|
+
});
|
|
334
|
+
});
|
|
@@ -20,6 +20,34 @@ export function discoverAgentDocs(targetDir: string): string[];
|
|
|
20
20
|
* @returns {boolean}
|
|
21
21
|
*/
|
|
22
22
|
export function isAstryxInitialized(targetDir?: string): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Does an agent working in `startDir` already have the Astryx prompt in reach?
|
|
25
|
+
*
|
|
26
|
+
* Coding agents read the agent docs between the repository root and the folder
|
|
27
|
+
* they work in. So inside a git repository, init's block in any folder from
|
|
28
|
+
* `startDir` up to the repository root counts: a workspace package of a
|
|
29
|
+
* monorepo initialized at its root is set up. Outside a repository only
|
|
30
|
+
* `startDir` itself is checked, as {@link isAstryxInitialized} does. Both the
|
|
31
|
+
* per-command nudge and the postinstall nudges ask this.
|
|
32
|
+
*
|
|
33
|
+
* @param {string} [startDir=process.cwd()]
|
|
34
|
+
* @returns {boolean}
|
|
35
|
+
*/
|
|
36
|
+
export function isAstryxPromptInReach(startDir?: string): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* The one-line next-step every setup layer prints. Kept here so layer 1
|
|
39
|
+
* (core), layer 2 (cli postinstall) and layer 3 (each command) can never word
|
|
40
|
+
* it differently. Each layer passes the stem from the CLI's picker when it can
|
|
41
|
+
* load it.
|
|
42
|
+
*
|
|
43
|
+
* @param {string} [invocation] the CLI invocation stem, e.g. `pnpm exec astryx`
|
|
44
|
+
* @param {{before?: string | null}} [options] `before`: a command to run
|
|
45
|
+
* first, such as the one that adds the CLI to a project that has none
|
|
46
|
+
* @returns {string}
|
|
47
|
+
*/
|
|
48
|
+
export function setupNudge(invocation?: string, { before }?: {
|
|
49
|
+
before?: string | null;
|
|
50
|
+
}): string;
|
|
23
51
|
/**
|
|
24
52
|
* Pure decision: should a postinstall print the setup nudge? Shared by BOTH
|
|
25
53
|
* postinstall layers, so the matrix cannot drift between them, and unit-testable
|
|
@@ -61,11 +89,12 @@ export const AGENT_DOC_PATHS: string[];
|
|
|
61
89
|
*/
|
|
62
90
|
export const INIT_MARKERS: string[];
|
|
63
91
|
/**
|
|
64
|
-
* The
|
|
65
|
-
* (
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* the CLI is installed. Bare `npx astryx` would fetch an unrelated look-alike
|
|
92
|
+
* The invocation the setup nudge falls back to when the CLI's picker
|
|
93
|
+
* (`getCliInvocation`) cannot be loaded. Scoped package form
|
|
94
|
+
* (`@astryxdesign/cli`) — always resolves to us, even before the CLI is
|
|
95
|
+
* installed. npx with the unscoped name would fetch an unrelated look-alike
|
|
69
96
|
* package (see PR #4151).
|
|
70
97
|
*/
|
|
71
|
-
export const
|
|
98
|
+
export const SETUP_INVOCATION: "npx @astryxdesign/cli";
|
|
99
|
+
/** The nudge with the fallback invocation. */
|
|
100
|
+
export const SETUP_NUDGE: string;
|