@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
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
* contract: a topic returns its whole doc, and `--index` its sections.
|
|
11
11
|
* Supports --detail (full|compact|brief) and --lang (en|zh|dense). A code
|
|
12
12
|
* block's label prints above its fence, and table cells escape their pipes.
|
|
13
|
+
* Docs write commands as bare `astryx ...`; text output prefixes them with the
|
|
14
|
+
* project's invocation (prefixCliCommands, in formatBlock and the summaries),
|
|
15
|
+
* and JSON keeps them bare.
|
|
13
16
|
*
|
|
14
17
|
* Usage:
|
|
15
18
|
* astryx docs List available topics
|
|
@@ -25,6 +28,7 @@
|
|
|
25
28
|
import {
|
|
26
29
|
formatCliCommand,
|
|
27
30
|
getCliInvocation,
|
|
31
|
+
prefixCliCommands,
|
|
28
32
|
} from '../../../foundation/env/package-manager.mjs';
|
|
29
33
|
import {jsonOut} from '../../../foundation/response/json.mjs';
|
|
30
34
|
import {
|
|
@@ -96,12 +100,17 @@ function formatTableCompact(headers, rows) {
|
|
|
96
100
|
* @returns {string | null}
|
|
97
101
|
*/
|
|
98
102
|
export function formatBlock(block, detail) {
|
|
103
|
+
// Docs write commands as bare `astryx ...`; show them the way this project
|
|
104
|
+
// runs the CLI.
|
|
105
|
+
const stem = getCliInvocation();
|
|
106
|
+
/** @param {string} value */
|
|
107
|
+
const shown = value => prefixCliCommands(value, stem);
|
|
99
108
|
switch (block.type) {
|
|
100
109
|
case 'prose':
|
|
101
|
-
return block.text;
|
|
110
|
+
return shown(block.text);
|
|
102
111
|
|
|
103
112
|
case 'heading':
|
|
104
|
-
return `${'#'.repeat(block.level || 3)} ${block.text}`;
|
|
113
|
+
return `${'#'.repeat(block.level || 3)} ${shown(block.text)}`;
|
|
105
114
|
|
|
106
115
|
case 'code':
|
|
107
116
|
if (detail === 'compact' || detail === 'brief') return null;
|
|
@@ -112,19 +121,29 @@ export function formatBlock(block, detail) {
|
|
|
112
121
|
const label = block.label
|
|
113
122
|
? `${block.label.replace(/:\s*$/, '')}:\n`
|
|
114
123
|
: '';
|
|
115
|
-
|
|
124
|
+
const body = prefixCliCommands(block.code, stem, block.lang);
|
|
125
|
+
return `${label}\`\`\`${block.lang}\n${body}\n\`\`\``;
|
|
116
126
|
}
|
|
117
127
|
|
|
118
|
-
case 'table':
|
|
128
|
+
case 'table': {
|
|
129
|
+
// A cell that is a whole command, such as `astryx theme add neutral`
|
|
130
|
+
// written without backticks, is prefixed too.
|
|
131
|
+
/** @param {string} cell */
|
|
132
|
+
const shownCell = cell =>
|
|
133
|
+
/^astryx(\s|$)/.test(cell ?? '')
|
|
134
|
+
? `${stem}${cell.slice('astryx'.length)}`
|
|
135
|
+
: shown(cell ?? '');
|
|
136
|
+
const rows = block.rows.map(row => row.map(shownCell));
|
|
119
137
|
if (detail === 'brief') {
|
|
120
|
-
return
|
|
138
|
+
return rows
|
|
121
139
|
.map(r => r.slice(0, 2).map(tableCell).join('='))
|
|
122
140
|
.join(' | ');
|
|
123
141
|
}
|
|
124
142
|
if (detail === 'compact') {
|
|
125
|
-
return formatTableCompact(block.headers,
|
|
143
|
+
return formatTableCompact(block.headers, rows);
|
|
126
144
|
}
|
|
127
|
-
return formatTable(block.headers,
|
|
145
|
+
return formatTable(block.headers, rows);
|
|
146
|
+
}
|
|
128
147
|
|
|
129
148
|
case 'list': {
|
|
130
149
|
const prefix =
|
|
@@ -135,7 +154,9 @@ export function formatBlock(block, detail) {
|
|
|
135
154
|
: block.style === 'do'
|
|
136
155
|
? () => '+ '
|
|
137
156
|
: () => '- ';
|
|
138
|
-
return block.items
|
|
157
|
+
return block.items
|
|
158
|
+
.map((item, i) => `${prefix(i)}${shown(item)}`)
|
|
159
|
+
.join('\n');
|
|
139
160
|
}
|
|
140
161
|
|
|
141
162
|
default:
|
|
@@ -289,7 +310,7 @@ function formatTreeChild(child, detail, level, root, run, owner) {
|
|
|
289
310
|
child.summary &&
|
|
290
311
|
(child.kind === 'namespace' || child.kind === 'generic')
|
|
291
312
|
) {
|
|
292
|
-
parts.push(child.summary);
|
|
313
|
+
parts.push(prefixCliCommands(child.summary, run));
|
|
293
314
|
}
|
|
294
315
|
const content = formatTreeBlocks(child.content ?? [], detail, level - 2);
|
|
295
316
|
if (content.length > 0) parts.push(content.join('\n\n'));
|
|
@@ -341,7 +362,7 @@ function emitTree(node, detail, childDetail, run) {
|
|
|
341
362
|
.every(route => route.startsWith(`${node.route}/`));
|
|
342
363
|
const root = allBelow ? node.route : '';
|
|
343
364
|
emit(
|
|
344
|
-
section(node.title, wrapText(node.summary)),
|
|
365
|
+
section(node.title, wrapText(prefixCliCommands(node.summary, run))),
|
|
345
366
|
record({package: node.package}),
|
|
346
367
|
...(node.content?.length
|
|
347
368
|
? [
|
|
@@ -427,9 +448,12 @@ function emitIndex(index, owner, run) {
|
|
|
427
448
|
// Summaries wrap rather than being cut: the summary is how a reader picks
|
|
428
449
|
// the one section to open. A section another package wrote says which one.
|
|
429
450
|
records(
|
|
430
|
-
index.sections.map(s =>
|
|
431
|
-
|
|
432
|
-
|
|
451
|
+
index.sections.map(s => {
|
|
452
|
+
const shown = {...s, summary: prefixCliCommands(s.summary ?? '', run)};
|
|
453
|
+
return s.package === owner
|
|
454
|
+
? shown
|
|
455
|
+
: {...shown, title: `${s.title} (${s.package})`};
|
|
456
|
+
}),
|
|
433
457
|
{
|
|
434
458
|
fields: ['id', 'title', 'summary'],
|
|
435
459
|
layout: 'inline',
|
|
@@ -462,9 +486,10 @@ function childRow(child, owner) {
|
|
|
462
486
|
return {
|
|
463
487
|
// A child another package owns says which one.
|
|
464
488
|
name: child.package === owner ? child.name : `${child.name} (${child.package})`,
|
|
465
|
-
summary:
|
|
466
|
-
? `${child.title}: ${child.summary}`
|
|
467
|
-
|
|
489
|
+
summary: prefixCliCommands(
|
|
490
|
+
titleAddsIdentity ? `${child.title}: ${child.summary}` : child.summary,
|
|
491
|
+
getCliInvocation(),
|
|
492
|
+
),
|
|
468
493
|
};
|
|
469
494
|
}
|
|
470
495
|
|
|
@@ -479,14 +504,19 @@ function childRow(child, owner) {
|
|
|
479
504
|
function emitNode(node, detail, run) {
|
|
480
505
|
if (node.kind === 'namespace') {
|
|
481
506
|
emit(
|
|
482
|
-
section(node.title, wrapText(node.summary)),
|
|
507
|
+
section(node.title, wrapText(prefixCliCommands(node.summary, run))),
|
|
483
508
|
record({package: node.package}),
|
|
484
|
-
// A namespace may author intro `blocks`; they render above its children
|
|
509
|
+
// A namespace may author intro `blocks`; they render above its children,
|
|
510
|
+
// prose wrapped like the summary.
|
|
485
511
|
...(node.content?.length
|
|
486
512
|
? [
|
|
487
513
|
text(
|
|
488
514
|
node.content
|
|
489
|
-
.map(b =>
|
|
515
|
+
.map(b =>
|
|
516
|
+
b.type === 'prose'
|
|
517
|
+
? wrapText(formatBlock(b, detail) ?? '')
|
|
518
|
+
: formatBlock(b, detail),
|
|
519
|
+
)
|
|
490
520
|
.filter(Boolean)
|
|
491
521
|
.join('\n\n'),
|
|
492
522
|
),
|
|
@@ -113,7 +113,7 @@ describe('progressive reads', () => {
|
|
|
113
113
|
expect(stdout).toMatch(/^principles +\S/m);
|
|
114
114
|
expect(widest(stdout)).toBeLessThanOrEqual(120);
|
|
115
115
|
// The repo root has no `astryx` bin, so the CLI names the scoped package.
|
|
116
|
-
expect(stdout).toMatch(/Usage: \S+(?: dlx)? (?:astryx|@astryxdesign\/cli) docs <topic>/);
|
|
116
|
+
expect(stdout).toMatch(/Usage: \S+(?: dlx)? (?:astryx|@astryxdesign\/cli(?:@\S+)?) docs <topic>/);
|
|
117
117
|
}, SLOW);
|
|
118
118
|
|
|
119
119
|
it("prints a topic's section index with the keys to read by", async () => {
|
|
@@ -255,7 +255,7 @@ describe('the docs tree, one level at a time', () => {
|
|
|
255
255
|
const {status, stdout} = await runCli(['docs', 'cli/api/functions/search']);
|
|
256
256
|
expect(status).toBe(0);
|
|
257
257
|
expect(stdout).toMatch(/^## search\(\)/m);
|
|
258
|
-
expect(stdout).
|
|
258
|
+
expect(stdout).toMatch(/Read it with `.+ docs cli\/commands\/search`\./);
|
|
259
259
|
expect(stdout).toMatch(/Up: .*docs cli\/api\/functions$/m);
|
|
260
260
|
}, SLOW);
|
|
261
261
|
|
|
@@ -20,12 +20,15 @@ export const doc = {
|
|
|
20
20
|
'Core component is an error. In a package without that range they are warnings, ' +
|
|
21
21
|
'with a warning for each such component, naming the range to declare. ' +
|
|
22
22
|
"Then it compares each component doc's props with the component's TypeScript " +
|
|
23
|
-
"props, using the project's own `typescript
|
|
23
|
+
"props, using the project's own `typescript` (or, where `typescript` is missing or " +
|
|
24
|
+
'has no JavaScript compiler API, as TypeScript 7 does, the `@typescript/typescript6` ' +
|
|
25
|
+
'it installs), and warns about a documented prop ' +
|
|
24
26
|
'the code lacks, a prop the package declares that the doc omits, a wrong ' +
|
|
25
27
|
'`required`, and a type that does not match where both sides read exactly ' +
|
|
26
28
|
'(it lists every other documented type as not compared, with the reason). ' +
|
|
27
29
|
'Without TypeScript it prints one ' +
|
|
28
|
-
'line saying the comparison was skipped.'
|
|
30
|
+
'line saying the comparison was skipped. It also warns on each `{@link}` in ' +
|
|
31
|
+
"a component doc's text that names no doc.",
|
|
29
32
|
fn: 'integrationComponentConflicts',
|
|
30
33
|
args: [
|
|
31
34
|
{
|
|
@@ -46,10 +49,11 @@ export const doc = {
|
|
|
46
49
|
cli: 'astryx doctor integration components @acme/widgets --json',
|
|
47
50
|
},
|
|
48
51
|
],
|
|
52
|
+
outsideProject: 'same',
|
|
49
53
|
exitCodes: [
|
|
50
54
|
{
|
|
51
55
|
code: 0,
|
|
52
|
-
when: 'the check completed; component name conflicts, replaces findings for a package without the CLI range,
|
|
56
|
+
when: 'the check completed; component name conflicts, replaces findings for a package without the CLI range, props that differ from the code, and links that name no doc are warnings',
|
|
53
57
|
},
|
|
54
58
|
{
|
|
55
59
|
code: 1,
|
|
@@ -8,12 +8,17 @@ export const doc = {
|
|
|
8
8
|
name: 'doctor integration docs',
|
|
9
9
|
displayName: 'astryx doctor integration docs',
|
|
10
10
|
namespace: 'cli/commands',
|
|
11
|
-
summary:
|
|
11
|
+
summary:
|
|
12
|
+
"Check an integration's docs: the docs tree they add, every link, and overlaps with Core topics",
|
|
12
13
|
description:
|
|
13
14
|
'Checks the docs tree the package adds, every link in its docs, and overlaps with Core topics. ' +
|
|
14
15
|
'Intentional replacements and extensions are information. ' +
|
|
15
16
|
'A same-name topic without `replaces` or `extends` is an accidental conflict ' +
|
|
16
|
-
'and fails until the author declares the relationship or renames it.
|
|
17
|
+
'and fails until the author declares the relationship or renames it. ' +
|
|
18
|
+
'It also lists each pair of topics (two of the package, or one of them and a Core topic other than the one it replaces) ' +
|
|
19
|
+
'that repeat 10 or more words of prose word for word, each padding phrase and low-density topic, ' +
|
|
20
|
+
'and each written `astryx docs <name>` that should be a link, ' +
|
|
21
|
+
'each as a warning (`copied_passage`, `doc_fluff`, `stray_doc_pointer`; exit 0, and `integration check --strict` fails on it). See {@link generic:check-your-docs}.',
|
|
17
22
|
fn: 'integrationDocConflicts',
|
|
18
23
|
args: [
|
|
19
24
|
{
|
|
@@ -25,15 +30,25 @@ export const doc = {
|
|
|
25
30
|
},
|
|
26
31
|
],
|
|
27
32
|
examples: [
|
|
28
|
-
{
|
|
33
|
+
{
|
|
34
|
+
label: 'Check the local integration',
|
|
35
|
+
cli: 'astryx doctor integration docs',
|
|
36
|
+
},
|
|
29
37
|
{
|
|
30
38
|
label: 'Check an installed integration',
|
|
31
39
|
cli: 'astryx doctor integration docs @acme/widgets --json',
|
|
32
40
|
},
|
|
33
41
|
],
|
|
42
|
+
outsideProject: 'same',
|
|
34
43
|
exitCodes: [
|
|
35
|
-
{
|
|
36
|
-
|
|
44
|
+
{
|
|
45
|
+
code: 0,
|
|
46
|
+
when: 'all Core overlaps are explicitly declared or no overlap exists',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
code: 1,
|
|
50
|
+
when: 'an overlap is accidental, a doc is invalid, a namespace or placement fails, or a reference block cannot include what it names. A link that names no doc is a warning, and does not change the exit code',
|
|
51
|
+
},
|
|
37
52
|
],
|
|
38
53
|
related: ['doctor integration validate', 'docs'],
|
|
39
54
|
};
|
|
@@ -16,11 +16,15 @@ export const doc = {
|
|
|
16
16
|
'installed package resolved by name. It schema-checks the manifest, verifies ' +
|
|
17
17
|
'every declared contribution root, and reports every finding. Safe as a CI gate. ' +
|
|
18
18
|
'It then checks every doc the package ships under its roots against the ' +
|
|
19
|
-
"published authoring type for its kind, with the project's own `typescript
|
|
19
|
+
"published authoring type for its kind, with the project's own `typescript` (or, " +
|
|
20
|
+
'where `typescript` is missing or has no JavaScript compiler API, as TypeScript 7 ' +
|
|
21
|
+
'does, the `@typescript/typescript6` it installs), and ' +
|
|
20
22
|
'warns about each field that does not match, naming the field and a fix. A doc ' +
|
|
21
23
|
'it cannot fully check is listed with the reason, and test fixtures under ' +
|
|
22
24
|
'`__tests__` in the components or docs root are counted, not checked. Without ' +
|
|
23
|
-
'TypeScript it prints one line saying the docs were not type-checked.'
|
|
25
|
+
'TypeScript it prints one line saying the docs were not type-checked. ' +
|
|
26
|
+
'Outside a package, with no package name it writes nothing and reports one no_package issue (exit 1); ' +
|
|
27
|
+
'a package name is looked up as it is in a project.',
|
|
24
28
|
fn: 'validateIntegration',
|
|
25
29
|
args: [
|
|
26
30
|
{
|
|
@@ -41,6 +45,7 @@ export const doc = {
|
|
|
41
45
|
cli: 'astryx doctor integration validate @acme/widgets --json',
|
|
42
46
|
},
|
|
43
47
|
],
|
|
48
|
+
outsideProject: 'own',
|
|
44
49
|
exitCodes: [
|
|
45
50
|
{
|
|
46
51
|
code: 0,
|
|
@@ -49,4 +54,10 @@ export const doc = {
|
|
|
49
54
|
{code: 1, when: 'one or more error-severity issues'},
|
|
50
55
|
],
|
|
51
56
|
related: ['doctor integration templates', 'template'],
|
|
57
|
+
notes: [
|
|
58
|
+
{
|
|
59
|
+
type: 'prose',
|
|
60
|
+
text: "In global mode: outside a package, with no package named, it writes nothing, reports one `no_package` issue, and exits 1; a package name is looked up as it is in a project. In a project, the project's version of Astryx runs it, whichever astryx command you start. See {@link namespace:global} and {@link generic:global-integrations}.",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
52
63
|
};
|
|
@@ -19,7 +19,7 @@ import {Command} from 'commander';
|
|
|
19
19
|
import {discoverCoreTemplates} from '../../../foundation/discovery/template-adapter.mjs';
|
|
20
20
|
import {discoverOwnedComponents} from '../../../foundation/discovery/component-discovery.mjs';
|
|
21
21
|
import {discoverBuiltinTopics} from '../../../foundation/discovery/docs-discovery.mjs';
|
|
22
|
-
import {findCoreDir} from '../../../foundation/fs/paths.mjs';
|
|
22
|
+
import {findCoreDir, findProjectCoreDir} from '../../../foundation/fs/paths.mjs';
|
|
23
23
|
import {registerDoctor} from './doctor.mjs';
|
|
24
24
|
import {expectRecordsCarry} from '../../../test-utils/text-projection.mjs';
|
|
25
25
|
|
|
@@ -185,7 +185,7 @@ describe('doctor integration — command', () => {
|
|
|
185
185
|
]);
|
|
186
186
|
|
|
187
187
|
expect(logCalls.join('\n')).toContain(
|
|
188
|
-
'
|
|
188
|
+
' doctor integration templates <package>',
|
|
189
189
|
);
|
|
190
190
|
expect(process.exitCode).toBeUndefined();
|
|
191
191
|
});
|
|
@@ -210,6 +210,51 @@ describe('doctor integration — command', () => {
|
|
|
210
210
|
expect(process.exitCode).toBeUndefined();
|
|
211
211
|
});
|
|
212
212
|
|
|
213
|
+
it('validate prints the fix and the file an issue carries, and JSON carries the same issue', async () => {
|
|
214
|
+
writeDocIntegration({name: 'deploying'});
|
|
215
|
+
fs.writeFileSync(
|
|
216
|
+
path.join(tmpDir, 'docs', 'ghost.doc.zh.mjs'),
|
|
217
|
+
"export default {title: 'ghost'};\n",
|
|
218
|
+
);
|
|
219
|
+
process.chdir(tmpDir);
|
|
220
|
+
|
|
221
|
+
await createProgram().parseAsync([
|
|
222
|
+
'node',
|
|
223
|
+
'astryx',
|
|
224
|
+
'doctor',
|
|
225
|
+
'integration',
|
|
226
|
+
'validate',
|
|
227
|
+
]);
|
|
228
|
+
const output = logCalls.join('\n');
|
|
229
|
+
expect(output).toContain('orphan_doc_overlay');
|
|
230
|
+
expect(output).toMatch(
|
|
231
|
+
/fix:\s+Delete docs\/ghost\.doc\.zh\.mjs, or add the topic it translates/,
|
|
232
|
+
);
|
|
233
|
+
expect(output).toMatch(/file:\s+docs\/ghost\.doc\.zh\.mjs/);
|
|
234
|
+
expect(output).toMatch(/line:\s+1\b/);
|
|
235
|
+
|
|
236
|
+
logCalls = [];
|
|
237
|
+
await createProgram().parseAsync([
|
|
238
|
+
'node',
|
|
239
|
+
'astryx',
|
|
240
|
+
'--json',
|
|
241
|
+
'doctor',
|
|
242
|
+
'integration',
|
|
243
|
+
'validate',
|
|
244
|
+
]);
|
|
245
|
+
const parsed = JSON.parse(logCalls.join('\n'));
|
|
246
|
+
expect(parsed.data.issues).toEqual([
|
|
247
|
+
{
|
|
248
|
+
code: 'orphan_doc_overlay',
|
|
249
|
+
severity: 'warning',
|
|
250
|
+
message: expect.stringContaining('docs/ghost.doc.zh.mjs'),
|
|
251
|
+
fix: expect.stringContaining('Delete docs/ghost.doc.zh.mjs'),
|
|
252
|
+
file: 'docs/ghost.doc.zh.mjs',
|
|
253
|
+
line: 1,
|
|
254
|
+
},
|
|
255
|
+
]);
|
|
256
|
+
});
|
|
257
|
+
|
|
213
258
|
it('validate warns about each doc field that does not match its authoring type, and still exits 0', async () => {
|
|
214
259
|
writeIntegration({id: 'hero', name: 'Hero', type: 'block'});
|
|
215
260
|
process.chdir(tmpDir);
|
|
@@ -772,7 +817,8 @@ describe('doctor integration — command', () => {
|
|
|
772
817
|
tmpDir = outside;
|
|
773
818
|
try {
|
|
774
819
|
writeComponentIntegration('AcmeCarousel');
|
|
775
|
-
|
|
820
|
+
// Doctor judges the project's own Core, never the one a copy carries.
|
|
821
|
+
expect(findProjectCoreDir(outside)).toBeNull();
|
|
776
822
|
process.chdir(outside);
|
|
777
823
|
|
|
778
824
|
await createProgram().parseAsync([
|
|
@@ -1060,12 +1106,13 @@ describe('doctor integration — command', () => {
|
|
|
1060
1106
|
"{name: 'elevation', type: 'number', description: 'Shadow.'}",
|
|
1061
1107
|
"{name: 'size', type: 'string', description: 'Size.'}",
|
|
1062
1108
|
"{name: 'meta', type: '{id: string; extra?: number}', description: 'Data.'}",
|
|
1109
|
+
"{name: 'gap', type: 'number', description: 'Gap.', default: '8'}",
|
|
1063
1110
|
].join(', ')}]};\n`,
|
|
1064
1111
|
);
|
|
1065
1112
|
// `key` is a prop a doc never needs, though the component declares it.
|
|
1066
1113
|
fs.writeFileSync(
|
|
1067
1114
|
path.join(tmpDir, 'components', 'AcmeBadge.tsx'),
|
|
1068
|
-
"export function AcmeBadge(
|
|
1115
|
+
"export function AcmeBadge({gap = 4}: {label: string; tone?: 'neutral' | 'info'; size?: number; meta?: {id: string}; gap?: number; key?: string}) { return null; }\n",
|
|
1069
1116
|
);
|
|
1070
1117
|
fs.writeFileSync(
|
|
1071
1118
|
path.join(tmpDir, 'components', 'AcmeLonely.doc.mjs'),
|
|
@@ -1094,6 +1141,7 @@ describe('doctor integration — command', () => {
|
|
|
1094
1141
|
|
|
1095
1142
|
expect(report.findings.map(f => `${f.prop} ${f.kind}`)).toEqual([
|
|
1096
1143
|
'elevation not_in_code',
|
|
1144
|
+
'gap default_mismatch',
|
|
1097
1145
|
'label required_mismatch',
|
|
1098
1146
|
'size type_mismatch',
|
|
1099
1147
|
'tone not_in_doc',
|
|
@@ -18,8 +18,11 @@ export const doc = {
|
|
|
18
18
|
'Runs read-only project health diagnostics by default: Node version, @astryxdesign/core ' +
|
|
19
19
|
'install and version alignment, theme packages, generated app themes when present, earlier copied-theme migration, config, integrations (every one astryx.config names must load, linked without a config entry, ' +
|
|
20
20
|
'provider identity, contribution issues), agent docs, core peer dependencies, package manager, ' +
|
|
21
|
-
"and the
|
|
22
|
-
'The `integration` subcommands provide authoring checks for one integration package.'
|
|
21
|
+
"the docs the CLI reads, the newest release the computer knows of, with the install and upgrade commands when the project's release is older, and every `astryx` command on the search path, warning when the first one is not the Astryx CLI or predates the hand-off. It writes nothing, but loading astryx.config runs that file's code. " +
|
|
22
|
+
'The `integration` subcommands provide authoring checks for one integration package. ' +
|
|
23
|
+
'Outside a project it checks the computer instead: the Node version, the release that answered, ' +
|
|
24
|
+
'the newest release this computer knows of, with the command that upgrades the CLI installed for the computer when it is older, the astryx commands on the search path, the integrations installed for the computer (warning about one it skips), and whether the computer-level agent text (`astryx init --user`) is present, matches this release, was edited, or is turned off (info only). ' +
|
|
25
|
+
'It never fails a check because the folder has no project.',
|
|
23
26
|
fn: 'doctor',
|
|
24
27
|
subcommands: ['integration'],
|
|
25
28
|
examples: [
|
|
@@ -42,9 +45,16 @@ export const doc = {
|
|
|
42
45
|
cli: 'astryx doctor integration docs @acme/widgets',
|
|
43
46
|
},
|
|
44
47
|
],
|
|
48
|
+
outsideProject: 'own',
|
|
45
49
|
exitCodes: [
|
|
46
50
|
{code: 0, when: 'no checks failed (warnings are allowed)'},
|
|
47
51
|
{code: 1, when: 'one or more checks failed'},
|
|
48
52
|
],
|
|
49
53
|
related: ['init', 'upgrade'],
|
|
54
|
+
notes: [
|
|
55
|
+
{
|
|
56
|
+
type: 'prose',
|
|
57
|
+
text: "In global mode: outside a project, doctor checks your computer instead of a folder: `node-version`, `answering-release` (the version that answered), `newest-release`, `cli-on-path` (every astryx command on your PATH), `computer-integrations` (integrations installed globally), and `computer-agent-text` (the agent guide). It never fails a check because the folder has no project. In a project, the project's version of Astryx runs it, whichever astryx command you start. See {@link namespace:global} and {@link generic:who-answers}.",
|
|
58
|
+
},
|
|
59
|
+
],
|
|
50
60
|
};
|
|
@@ -38,6 +38,8 @@ import {doc as integrationDocConflictsFn} from '../../../api/integration/integra
|
|
|
38
38
|
import {NO_RESULT_SET} from '../../../foundation/debug/index.mjs';
|
|
39
39
|
import {cliError} from '../lib/cli-error.mjs';
|
|
40
40
|
import {ERROR_CODES} from '../../../foundation/response/error-codes.mjs';
|
|
41
|
+
import {formatCliCommand} from '../../../foundation/env/package-manager.mjs';
|
|
42
|
+
import {isOutsideProject} from '../../../foundation/env/project-scope.mjs';
|
|
41
43
|
|
|
42
44
|
const STATUS = {
|
|
43
45
|
pass: '[ok]',
|
|
@@ -92,7 +94,7 @@ function issueBlocks(issues) {
|
|
|
92
94
|
return [
|
|
93
95
|
section('Integration issues'),
|
|
94
96
|
records(issues, {
|
|
95
|
-
fields: ['severity', 'code', 'message'],
|
|
97
|
+
fields: ['severity', 'code', 'message', 'fix', 'file', 'line'],
|
|
96
98
|
format: {severity: statusToken},
|
|
97
99
|
}),
|
|
98
100
|
];
|
|
@@ -189,11 +191,14 @@ function printIntegrationValidation(data) {
|
|
|
189
191
|
...(data.issues.length > 0
|
|
190
192
|
? [
|
|
191
193
|
records(data.issues, {
|
|
192
|
-
fields: ['severity', 'code', 'message'],
|
|
194
|
+
fields: ['severity', 'code', 'message', 'fix', 'file', 'line'],
|
|
193
195
|
format: {severity: statusToken},
|
|
194
196
|
}),
|
|
195
197
|
]
|
|
196
198
|
: [text('[ok] No integration issues found.')]),
|
|
199
|
+
...(data.notes ?? []).map(note =>
|
|
200
|
+
text(`note (${note.code}): ${note.message}`),
|
|
201
|
+
),
|
|
197
202
|
text(
|
|
198
203
|
`Summary: ${errors} error${errors === 1 ? '' : 's'}, ` +
|
|
199
204
|
`${warnings} warning${warnings === 1 ? '' : 's'}`,
|
|
@@ -287,6 +292,9 @@ function propDriftBlocks(report, failed) {
|
|
|
287
292
|
'codeType',
|
|
288
293
|
'docRequired',
|
|
289
294
|
'codeRequired',
|
|
295
|
+
'docDefault',
|
|
296
|
+
'codeDefault',
|
|
297
|
+
'fix',
|
|
290
298
|
],
|
|
291
299
|
format: {severity: statusToken},
|
|
292
300
|
}),
|
|
@@ -358,7 +366,8 @@ function printComponentConflicts(data) {
|
|
|
358
366
|
// An [ok] after a failed check reads as a pass: say nothing it could not check.
|
|
359
367
|
const failed = data.issues.some(issue => issue.severity === 'error');
|
|
360
368
|
if (data.conflicts.length === 0) {
|
|
361
|
-
if (!failed)
|
|
369
|
+
if (!failed)
|
|
370
|
+
output.push(text('[ok] No component names conflict with Core.'));
|
|
362
371
|
} else {
|
|
363
372
|
output.push(
|
|
364
373
|
records(data.conflicts, {
|
|
@@ -389,7 +398,16 @@ function printDocConflicts(data) {
|
|
|
389
398
|
section(
|
|
390
399
|
`Checking integration docs: ${integrationLabel(data) ?? '(local package)'}`,
|
|
391
400
|
),
|
|
392
|
-
|
|
401
|
+
// A copied passage or fluff is listed below with its detail, so its
|
|
402
|
+
// issue is not printed twice.
|
|
403
|
+
...issueBlocks(
|
|
404
|
+
data.issues.filter(
|
|
405
|
+
issue =>
|
|
406
|
+
issue.code !== 'copied_passage' &&
|
|
407
|
+
issue.code !== 'doc_fluff' &&
|
|
408
|
+
issue.code !== 'stray_doc_pointer',
|
|
409
|
+
),
|
|
410
|
+
),
|
|
393
411
|
];
|
|
394
412
|
if (
|
|
395
413
|
!data.issues.some(
|
|
@@ -412,6 +430,79 @@ function printDocConflicts(data) {
|
|
|
412
430
|
}),
|
|
413
431
|
);
|
|
414
432
|
}
|
|
433
|
+
const copied = data.copiedPassages ?? [];
|
|
434
|
+
if (copied.length === 0) {
|
|
435
|
+
if (!data.issues.some(issue => issue.severity === 'error')) {
|
|
436
|
+
output.push(text('[ok] No topic copies a passage from another.'));
|
|
437
|
+
}
|
|
438
|
+
} else {
|
|
439
|
+
output.push(
|
|
440
|
+
text(
|
|
441
|
+
`[warn] ${copied.length} copied passage(s) (copied_passage): two topics say the same thing word for word. Keep the text in one and link to it from the other.`,
|
|
442
|
+
),
|
|
443
|
+
records(copied, {
|
|
444
|
+
fields: [
|
|
445
|
+
'topic',
|
|
446
|
+
'section',
|
|
447
|
+
'line',
|
|
448
|
+
'otherTopic',
|
|
449
|
+
'otherOwner',
|
|
450
|
+
'owner',
|
|
451
|
+
'text',
|
|
452
|
+
'words',
|
|
453
|
+
'passages',
|
|
454
|
+
'message',
|
|
455
|
+
],
|
|
456
|
+
}),
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
const fluff = data.fluff ?? [];
|
|
460
|
+
if (fluff.length === 0) {
|
|
461
|
+
if (!data.issues.some(issue => issue.severity === 'error')) {
|
|
462
|
+
output.push(text('[ok] No filler phrases or low-density topics.'));
|
|
463
|
+
}
|
|
464
|
+
} else {
|
|
465
|
+
output.push(
|
|
466
|
+
text(
|
|
467
|
+
`[warn] ${fluff.length} fluff finding(s) (doc_fluff): words that add length, not meaning. Cut each one.`,
|
|
468
|
+
),
|
|
469
|
+
records(fluff, {
|
|
470
|
+
fields: [
|
|
471
|
+
'topic',
|
|
472
|
+
'kind',
|
|
473
|
+
'phrase',
|
|
474
|
+
'section',
|
|
475
|
+
'file',
|
|
476
|
+
'line',
|
|
477
|
+
'density',
|
|
478
|
+
'message',
|
|
479
|
+
],
|
|
480
|
+
}),
|
|
481
|
+
);
|
|
482
|
+
}
|
|
483
|
+
const stray = data.strayPointers ?? [];
|
|
484
|
+
if (stray.length === 0) {
|
|
485
|
+
if (!data.issues.some(issue => issue.severity === 'error')) {
|
|
486
|
+
output.push(text('[ok] Every pointer to a doc is a link.'));
|
|
487
|
+
}
|
|
488
|
+
} else {
|
|
489
|
+
output.push(
|
|
490
|
+
text(
|
|
491
|
+
`[warn] ${stray.length} stray doc pointer(s) (stray_doc_pointer): a written \`astryx docs <name>\` where a link would be checked. Replace each with the link shown.`,
|
|
492
|
+
),
|
|
493
|
+
records(stray, {
|
|
494
|
+
fields: [
|
|
495
|
+
'topic',
|
|
496
|
+
'section',
|
|
497
|
+
'file',
|
|
498
|
+
'line',
|
|
499
|
+
'pointer',
|
|
500
|
+
'link',
|
|
501
|
+
'message',
|
|
502
|
+
],
|
|
503
|
+
}),
|
|
504
|
+
);
|
|
505
|
+
}
|
|
415
506
|
emit(...output);
|
|
416
507
|
}
|
|
417
508
|
|
|
@@ -455,7 +546,7 @@ async function runIntegrationValidation(program, pkg) {
|
|
|
455
546
|
noPackage
|
|
456
547
|
? 'Nothing was validated: no package.json found. Run this command inside a package directory.'
|
|
457
548
|
: 'Nothing was validated: no astryx.integration.* found next to package.json. ' +
|
|
458
|
-
|
|
549
|
+
`To validate an installed integration: ${formatCliCommand('doctor integration validate <package>')}`,
|
|
459
550
|
),
|
|
460
551
|
);
|
|
461
552
|
} else printIntegrationValidation(result.data);
|
|
@@ -478,10 +569,14 @@ async function runAuthoringCheck(program, pkg, kind) {
|
|
|
478
569
|
|
|
479
570
|
if (program.opts().json) jsonOut(result);
|
|
480
571
|
else if (!result.data.validated) {
|
|
572
|
+
// Outside a project no integration is installed to check by name
|
|
573
|
+
// (spec AST-081 FR3).
|
|
481
574
|
emit(
|
|
482
575
|
text(
|
|
483
|
-
|
|
484
|
-
|
|
576
|
+
isOutsideProject()
|
|
577
|
+
? 'Nothing was checked: no astryx.integration.* found next to package.json, and this folder is outside a project.'
|
|
578
|
+
: 'Nothing was checked: no astryx.integration.* found next to package.json. ' +
|
|
579
|
+
`To check an installed integration: ${formatCliCommand(`doctor integration ${kind} <package>`)}`,
|
|
485
580
|
),
|
|
486
581
|
);
|
|
487
582
|
} else if (kind === 'templates') {
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
checkPackageManager,
|
|
21
21
|
} from '../../../api/doctor/doctor.mjs';
|
|
22
22
|
import {MIN_NODE_VERSION} from '../../../foundation/env/node-version.mjs';
|
|
23
|
+
import {CLI_VERSION, linkThisCliAsProjectCli} from '../../../test-utils/release-fixtures.mjs';
|
|
23
24
|
|
|
24
25
|
let tmpDir;
|
|
25
26
|
let logCalls;
|
|
@@ -101,7 +102,7 @@ describe('doctor — individual checks', () => {
|
|
|
101
102
|
});
|
|
102
103
|
|
|
103
104
|
it('app themes: reports unmanaged state as one INFO check', async () => {
|
|
104
|
-
fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"app"}\n');
|
|
105
|
+
fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"app","dependencies":{"@astryxdesign/core":"*"}}\n');
|
|
105
106
|
const result = await runChecks({cwd: tmpDir});
|
|
106
107
|
const themeChecks = result.checks.filter(check =>
|
|
107
108
|
check.id.startsWith('theme-'),
|
|
@@ -176,13 +177,16 @@ describe('doctor — individual checks', () => {
|
|
|
176
177
|
it('agent-docs: the fix names the scoped package when the project has no local CLI', () => {
|
|
177
178
|
fs.writeFileSync(path.join(tmpDir, 'package-lock.json'), '{}');
|
|
178
179
|
const res = checkAgentDocs({cwd: tmpDir});
|
|
179
|
-
expect(res.fix).toContain(
|
|
180
|
+
expect(res.fix).toContain(
|
|
181
|
+
`\`npx @astryxdesign/cli@${CLI_VERSION} init --features agents\``,
|
|
182
|
+
);
|
|
180
183
|
});
|
|
181
184
|
|
|
182
185
|
it('agent-docs: the fix keeps `npx astryx` when the project has a local CLI', () => {
|
|
183
186
|
fs.writeFileSync(path.join(tmpDir, 'package-lock.json'), '{}');
|
|
184
187
|
fs.mkdirSync(path.join(tmpDir, 'node_modules', '.bin'), {recursive: true});
|
|
185
188
|
fs.writeFileSync(path.join(tmpDir, 'node_modules', '.bin', 'astryx'), '');
|
|
189
|
+
linkThisCliAsProjectCli(tmpDir);
|
|
186
190
|
const res = checkAgentDocs({cwd: tmpDir});
|
|
187
191
|
expect(res.fix).toContain('`npx astryx init --features agents`');
|
|
188
192
|
});
|
|
@@ -301,7 +305,8 @@ describe('doctor — runChecks / report', () => {
|
|
|
301
305
|
expect(total).toBe(report.checks.length);
|
|
302
306
|
});
|
|
303
307
|
|
|
304
|
-
it('reports a FAIL for core
|
|
308
|
+
it('reports a FAIL for core in a project that declares Core but installs none', async () => {
|
|
309
|
+
fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"app","dependencies":{"@astryxdesign/core":"*"}}\n');
|
|
305
310
|
const report = await runChecks({cwd: tmpDir});
|
|
306
311
|
expect(find(report.checks, 'core-installed').status).toBe('fail');
|
|
307
312
|
expect(report.summary.fail).toBeGreaterThan(0);
|
|
@@ -346,7 +351,8 @@ describe('doctor — command', () => {
|
|
|
346
351
|
process.exitCode = prevExit;
|
|
347
352
|
});
|
|
348
353
|
|
|
349
|
-
it('sets exit code 1 when a check FAILs (
|
|
354
|
+
it('sets exit code 1 when a check FAILs (Core declared, not installed)', async () => {
|
|
355
|
+
fs.writeFileSync(path.join(tmpDir, 'package.json'), '{"name":"app","dependencies":{"@astryxdesign/core":"*"}}\n');
|
|
350
356
|
const prevCwd = process.cwd();
|
|
351
357
|
const prevExit = process.exitCode;
|
|
352
358
|
process.exitCode = undefined;
|