@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
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Where a runner may stand in front of an Astryx command in Astryx's own
|
|
5
|
+
* docs. Docs write commands bare (`astryx <command>`): the CLI prefixes each
|
|
6
|
+
* one with the reader's command when it prints a doc, and the docsite with
|
|
7
|
+
* `npx @astryxdesign/cli`. A few files show a runner on purpose, and some files
|
|
8
|
+
* are not docs at all. The rules, checked by test/runner-commands.test.mjs:
|
|
9
|
+
*
|
|
10
|
+
* - npx (or another download runner) with the unscoped name `astryx` is never
|
|
11
|
+
* written outside `skip`: it fetches an unrelated npm package.
|
|
12
|
+
* - In a doc (`*.doc.mjs`, and Core's docs.mjs), no runner precedes an Astryx
|
|
13
|
+
* command, except in `runnerExamples`, where `npx @astryxdesign/cli …` and a
|
|
14
|
+
* project's runner may (still never the unscoped name through npx).
|
|
15
|
+
*
|
|
16
|
+
* TODO(doctor-runner-check): the Doctor lane's integration-docs runner check
|
|
17
|
+
* (foundation/discovery/runner-commands.mjs) becomes the single rule; then the
|
|
18
|
+
* repo test runs that check over Core's and the CLI's own docs with this
|
|
19
|
+
* allowlist.
|
|
20
|
+
*
|
|
21
|
+
* @input nothing
|
|
22
|
+
* @output the allowlist
|
|
23
|
+
* @position packages/cli/foundation/discovery — data shared by the repo test
|
|
24
|
+
* and the Doctor runner check
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
export const RUNNER_COMMAND_ALLOWLIST = Object.freeze({
|
|
28
|
+
/** Files never scanned: release notes, tests, and the helpers that build runner forms. */
|
|
29
|
+
skip: Object.freeze([
|
|
30
|
+
/(^|\/)CHANGELOG\.md$/u,
|
|
31
|
+
/\.test\.[cm]?[jt]sx?$/u,
|
|
32
|
+
/(^|\/)__tests__\//u,
|
|
33
|
+
/^packages\/cli\/test\//u,
|
|
34
|
+
/^packages\/cli\/foundation\/env\/package-manager\.mjs$/u,
|
|
35
|
+
]),
|
|
36
|
+
/** Docs that show a runner on purpose, and why. */
|
|
37
|
+
runnerExamples: Object.freeze({
|
|
38
|
+
'packages/core/docs.mjs':
|
|
39
|
+
"Core's setup banner, for a project that has no CLI installed yet",
|
|
40
|
+
'packages/cli/assets/docs/tree/updates.doc.mjs':
|
|
41
|
+
"quotes the CLI's own update notice, which names the project's runner",
|
|
42
|
+
'packages/cli/assets/docs/tree/cli-command.doc.mjs':
|
|
43
|
+
'explains how printed commands start, the pinned `npx @astryxdesign/cli@<version>` among them',
|
|
44
|
+
'packages/cli/assets/docs/tree/who-answers.doc.mjs':
|
|
45
|
+
'explains how printed commands start, the pinned `npx @astryxdesign/cli@<version>` among them',
|
|
46
|
+
'packages/cli/assets/docs/tree/project-global-or-both.doc.mjs':
|
|
47
|
+
'compares running the CLI with npx to installing it, and is found by searching for that command',
|
|
48
|
+
'packages/cli/assets/docs/tree/install-once.doc.mjs':
|
|
49
|
+
'names a pinned release, `npx @astryxdesign/cli@<version>`, which answers as that version',
|
|
50
|
+
'packages/cli/clients/cli/commands/upgrade.doc.mjs':
|
|
51
|
+
'quotes the command upgrade prints when the CLI is older than Core, pinned to the matching release',
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// @generated by scripts/sync-api-types.mjs from the JSDoc in foundation/**/*.mjs.
|
|
2
|
+
// DO NOT EDIT — run `pnpm sync:api-types` to regenerate.
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The strings of a doc the CLI resolves links in (spec:AST-047 FR9). In a
|
|
6
|
+
* topic: its description and summary, then the text of prose and heading
|
|
7
|
+
* blocks, list items, and table cells in each section's content, with the
|
|
8
|
+
* section's title. In a component doc (any doc with no sections): every text
|
|
9
|
+
* field, such as its description, usage, best practices, and each prop's and
|
|
10
|
+
* example's description, with the field's path. Code is never read.
|
|
11
|
+
*
|
|
12
|
+
* @param {unknown} doc an authored doc object
|
|
13
|
+
* @returns {{text: string, section: string | null, field: string | null}[]}
|
|
14
|
+
*/
|
|
15
|
+
export function linkableStrings(doc: unknown): {
|
|
16
|
+
text: string;
|
|
17
|
+
section: string | null;
|
|
18
|
+
field: string | null;
|
|
19
|
+
}[];
|
|
20
|
+
/**
|
|
21
|
+
* Every pointer span in one prose string, in order.
|
|
22
|
+
* @param {string} text
|
|
23
|
+
* @returns {string[]} the doc name each one points at
|
|
24
|
+
*/
|
|
25
|
+
export function pointersIn(text: string): string[];
|
|
26
|
+
/**
|
|
27
|
+
* Each stray pointer in a package's topics and component docs.
|
|
28
|
+
*
|
|
29
|
+
* @param {{records: {name: string, path: string}[], guides?: {name: string, ref?: {topicFile?: string}}[], namespaces?: {doc?: {name?: string}}[], components?: {name: string, file: string}[]}} discovered
|
|
30
|
+
* @returns {Promise<import('../../api/integration/authoring-checks.type.mjs').StrayPointer[]>}
|
|
31
|
+
*/
|
|
32
|
+
export function findStrayPointers(discovered: {
|
|
33
|
+
records: {
|
|
34
|
+
name: string;
|
|
35
|
+
path: string;
|
|
36
|
+
}[];
|
|
37
|
+
guides?: {
|
|
38
|
+
name: string;
|
|
39
|
+
ref?: {
|
|
40
|
+
topicFile?: string;
|
|
41
|
+
};
|
|
42
|
+
}[];
|
|
43
|
+
namespaces?: {
|
|
44
|
+
doc?: {
|
|
45
|
+
name?: string;
|
|
46
|
+
};
|
|
47
|
+
}[];
|
|
48
|
+
components?: {
|
|
49
|
+
name: string;
|
|
50
|
+
file: string;
|
|
51
|
+
}[];
|
|
52
|
+
}): Promise<import("../../api/integration/authoring-checks.type.mjs").StrayPointer[]>;
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @file Stray doc pointers (architecture:cli-surface DEC-8): a code span in
|
|
5
|
+
* prose that is exactly `astryx docs <name>` for a doc that exists. The doc's
|
|
6
|
+
* `{@link}` prints the command that opens the doc and is checked by doctor's
|
|
7
|
+
* link check, so a written command is a pointer nothing checks.
|
|
8
|
+
*
|
|
9
|
+
* @input the docs a package ships, as discoverIntegrationDocs returns them
|
|
10
|
+
* @output each stray pointer, with the link that replaces it
|
|
11
|
+
* @position foundation/discovery, called through api/integration/_adapter.mjs
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import fs from 'node:fs';
|
|
15
|
+
|
|
16
|
+
import {textFields} from '../doc-compiler/links.mjs';
|
|
17
|
+
import {builtinGuideFiles} from './docs-discovery.mjs';
|
|
18
|
+
import {
|
|
19
|
+
fileWords,
|
|
20
|
+
lineAtOffset,
|
|
21
|
+
loadQuietly,
|
|
22
|
+
locateWords,
|
|
23
|
+
textWords,
|
|
24
|
+
} from './copied-passages.mjs';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A code span that is exactly the command opening one doc. A command with
|
|
28
|
+
* more words, a flag, or a route is a walkthrough, not a pointer. A name holds
|
|
29
|
+
* what a topic name may (letters, digits, `_` and `-`), never opening with `-`.
|
|
30
|
+
*/
|
|
31
|
+
const POINTER = /`astryx docs ([A-Za-z0-9_][A-Za-z0-9_-]*)`/g;
|
|
32
|
+
|
|
33
|
+
/** @type {Promise<Map<string, string>> | undefined} */
|
|
34
|
+
let coreKinds;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* The CLI's own docs by name, each with the kind a link names it by: a
|
|
38
|
+
* namespace doc as `namespace`, a topic or guide as `generic`.
|
|
39
|
+
* @returns {Promise<Map<string, string>>}
|
|
40
|
+
*/
|
|
41
|
+
function loadCoreKinds() {
|
|
42
|
+
coreKinds ??= (async () => {
|
|
43
|
+
const kinds = new Map();
|
|
44
|
+
for (const file of builtinGuideFiles()) {
|
|
45
|
+
const doc = await loadQuietly(file);
|
|
46
|
+
if (typeof doc?.name === 'string') {
|
|
47
|
+
kinds.set(doc.name, doc.type === 'namespace' ? 'namespace' : 'generic');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return kinds;
|
|
51
|
+
})();
|
|
52
|
+
return coreKinds;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The strings of a doc the CLI resolves links in (spec:AST-047 FR9). In a
|
|
57
|
+
* topic: its description and summary, then the text of prose and heading
|
|
58
|
+
* blocks, list items, and table cells in each section's content, with the
|
|
59
|
+
* section's title. In a component doc (any doc with no sections): every text
|
|
60
|
+
* field, such as its description, usage, best practices, and each prop's and
|
|
61
|
+
* example's description, with the field's path. Code is never read.
|
|
62
|
+
*
|
|
63
|
+
* @param {unknown} doc an authored doc object
|
|
64
|
+
* @returns {{text: string, section: string | null, field: string | null}[]}
|
|
65
|
+
*/
|
|
66
|
+
export function linkableStrings(doc) {
|
|
67
|
+
/** @type {{text: string, section: string | null, field: string | null}[]} */
|
|
68
|
+
const strings = [];
|
|
69
|
+
if (doc == null || typeof doc !== 'object') return strings;
|
|
70
|
+
const top = /** @type {Record<string, any>} */ (doc);
|
|
71
|
+
if (!Array.isArray(top.sections)) {
|
|
72
|
+
for (const {field, text} of textFields(doc)) {
|
|
73
|
+
strings.push({text, section: null, field});
|
|
74
|
+
}
|
|
75
|
+
return strings;
|
|
76
|
+
}
|
|
77
|
+
for (const field of ['description', 'summary']) {
|
|
78
|
+
if (typeof top[field] === 'string') {
|
|
79
|
+
strings.push({text: top[field], section: null, field});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* @param {unknown} value
|
|
84
|
+
* @param {string | null} section
|
|
85
|
+
*/
|
|
86
|
+
const walk = (value, section) => {
|
|
87
|
+
if (Array.isArray(value)) {
|
|
88
|
+
for (const item of value) walk(item, section);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (value == null || typeof value !== 'object') return;
|
|
92
|
+
const record = /** @type {Record<string, any>} */ (value);
|
|
93
|
+
const title = typeof record.title === 'string' ? record.title : section;
|
|
94
|
+
if (Array.isArray(record.sections)) walk(record.sections, section);
|
|
95
|
+
if (!Array.isArray(record.content)) return;
|
|
96
|
+
for (const block of record.content) {
|
|
97
|
+
const add = (/** @type {unknown} */ text) => {
|
|
98
|
+
if (typeof text === 'string') {
|
|
99
|
+
strings.push({text, section: title, field: null});
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
switch (block?.type) {
|
|
103
|
+
case 'prose':
|
|
104
|
+
case 'heading':
|
|
105
|
+
add(block.text);
|
|
106
|
+
break;
|
|
107
|
+
case 'list':
|
|
108
|
+
(block.items ?? []).forEach(add);
|
|
109
|
+
break;
|
|
110
|
+
case 'table':
|
|
111
|
+
(block.headers ?? []).forEach(add);
|
|
112
|
+
for (const row of block.rows ?? []) row.forEach(add);
|
|
113
|
+
break;
|
|
114
|
+
default:
|
|
115
|
+
walk(block, title);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
walk(doc, null);
|
|
120
|
+
return strings;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Every pointer span in one prose string, in order.
|
|
125
|
+
* @param {string} text
|
|
126
|
+
* @returns {string[]} the doc name each one points at
|
|
127
|
+
*/
|
|
128
|
+
export function pointersIn(text) {
|
|
129
|
+
return [...text.matchAll(POINTER)].map(match => match[1]);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Where a string's words start among a file's words, from `from` on. A
|
|
134
|
+
* one-line string the file holds as a quoted literal is found at that
|
|
135
|
+
* literal, so a list item that is only `astryx docs theme` is not placed at a
|
|
136
|
+
* summary or code block that writes the same words.
|
|
137
|
+
*
|
|
138
|
+
* @param {string[]} lines the file's lines
|
|
139
|
+
* @param {{word: string, line: number}[]} file the file's words
|
|
140
|
+
* @param {string} text
|
|
141
|
+
* @param {{word: string}[]} words the string's words
|
|
142
|
+
* @param {number} from
|
|
143
|
+
* @returns {number}
|
|
144
|
+
*/
|
|
145
|
+
function locateString(lines, file, text, words, from) {
|
|
146
|
+
/** @type {number[]} */
|
|
147
|
+
const starts = [];
|
|
148
|
+
for (let at = locateWords(file, words); at >= 0;) {
|
|
149
|
+
starts.push(at);
|
|
150
|
+
at = locateWords(file, words, at + 1);
|
|
151
|
+
}
|
|
152
|
+
if (starts.length === 0) return -1;
|
|
153
|
+
const literals = text.includes('\n')
|
|
154
|
+
? []
|
|
155
|
+
: [`'${text}'`, `"${text}"`, `'${text.replace(/'/g, "\\'")}'`];
|
|
156
|
+
const quoted = starts.filter(at =>
|
|
157
|
+
literals.some(literal => lines[file[at].line - 1]?.includes(literal)),
|
|
158
|
+
);
|
|
159
|
+
const pool = quoted.length > 0 ? quoted : starts;
|
|
160
|
+
return pool.find(at => at >= from) ?? pool[0];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Each stray pointer in a package's topics and component docs.
|
|
165
|
+
*
|
|
166
|
+
* @param {{records: {name: string, path: string}[], guides?: {name: string, ref?: {topicFile?: string}}[], namespaces?: {doc?: {name?: string}}[], components?: {name: string, file: string}[]}} discovered
|
|
167
|
+
* @returns {Promise<import('../../api/integration/authoring-checks.type.mjs').StrayPointer[]>}
|
|
168
|
+
*/
|
|
169
|
+
export async function findStrayPointers(discovered) {
|
|
170
|
+
/** @type {{name: string, file: string | undefined, kind: 'topic' | 'component'}[]} */
|
|
171
|
+
const topics = [
|
|
172
|
+
...discovered.records.map(record => ({
|
|
173
|
+
name: record.name,
|
|
174
|
+
file: record.path,
|
|
175
|
+
kind: /** @type {const} */ ('topic'),
|
|
176
|
+
})),
|
|
177
|
+
...(discovered.guides ?? []).map(guide => ({
|
|
178
|
+
name: guide.name,
|
|
179
|
+
file: guide.ref?.topicFile,
|
|
180
|
+
kind: /** @type {const} */ ('topic'),
|
|
181
|
+
})),
|
|
182
|
+
];
|
|
183
|
+
/** @type {Map<string, string>} */
|
|
184
|
+
const own = new Map(topics.map(topic => [topic.name, 'generic']));
|
|
185
|
+
for (const namespace of discovered.namespaces ?? []) {
|
|
186
|
+
const name = namespace?.doc?.name;
|
|
187
|
+
if (typeof name === 'string' && !own.has(name)) own.set(name, 'namespace');
|
|
188
|
+
}
|
|
189
|
+
for (const component of discovered.components ?? []) {
|
|
190
|
+
topics.push({
|
|
191
|
+
name: component.name,
|
|
192
|
+
file: component.file,
|
|
193
|
+
kind: 'component',
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
const core = await loadCoreKinds();
|
|
197
|
+
// A topic that extends another has no route of its own: a link to it names
|
|
198
|
+
// the page it shows on, the topic it extends.
|
|
199
|
+
/** @type {Map<string, string>} */
|
|
200
|
+
const extendsOf = new Map();
|
|
201
|
+
for (const topic of topics) {
|
|
202
|
+
if (!topic.file) continue;
|
|
203
|
+
const doc = /** @type {any} */ (await loadQuietly(topic.file));
|
|
204
|
+
if (typeof doc?.extends === 'string')
|
|
205
|
+
extendsOf.set(topic.name, doc.extends);
|
|
206
|
+
}
|
|
207
|
+
/** @param {string} target */
|
|
208
|
+
const linkFor = target => {
|
|
209
|
+
const page = extendsOf.get(target);
|
|
210
|
+
if (page != null) {
|
|
211
|
+
if (own.has(page) && !extendsOf.has(page)) {
|
|
212
|
+
return `{@link ${own.get(page)}:${page}}`;
|
|
213
|
+
}
|
|
214
|
+
return core.has(page)
|
|
215
|
+
? `{@link @astryxdesign/cli:${core.get(page)}:${page}}`
|
|
216
|
+
: null;
|
|
217
|
+
}
|
|
218
|
+
return own.has(target)
|
|
219
|
+
? `{@link ${own.get(target)}:${target}}`
|
|
220
|
+
: core.has(target)
|
|
221
|
+
? `{@link @astryxdesign/cli:${core.get(target)}:${target}}`
|
|
222
|
+
: null;
|
|
223
|
+
};
|
|
224
|
+
/** @type {import('../../api/integration/authoring-checks.type.mjs').StrayPointer[]} */
|
|
225
|
+
const found = [];
|
|
226
|
+
for (const topic of topics) {
|
|
227
|
+
if (!topic.file) continue;
|
|
228
|
+
const doc = await loadQuietly(topic.file);
|
|
229
|
+
if (!doc) continue;
|
|
230
|
+
/** @type {{word: string, line: number}[]} */
|
|
231
|
+
let source = [];
|
|
232
|
+
/** @type {string[]} */
|
|
233
|
+
let lines = [];
|
|
234
|
+
try {
|
|
235
|
+
const raw = fs.readFileSync(topic.file, 'utf8');
|
|
236
|
+
source = fileWords(raw);
|
|
237
|
+
lines = raw.split('\n');
|
|
238
|
+
} catch {
|
|
239
|
+
// No line numbers; the finding still names the section.
|
|
240
|
+
}
|
|
241
|
+
// A component doc is named by its own name: a family doc by the family.
|
|
242
|
+
const name =
|
|
243
|
+
topic.kind === 'component' && typeof doc.name === 'string'
|
|
244
|
+
? doc.name
|
|
245
|
+
: topic.name;
|
|
246
|
+
const label =
|
|
247
|
+
topic.kind === 'component' ? `component "${name}"` : `"${name}"`;
|
|
248
|
+
// Each string is found by its whole run of words, from where the last
|
|
249
|
+
// one was found, so two strings that open alike keep their own lines.
|
|
250
|
+
let cursor = 0;
|
|
251
|
+
for (const {text, section, field} of linkableStrings(doc)) {
|
|
252
|
+
const words = textWords(text);
|
|
253
|
+
const index = locateString(lines, source, text, words, cursor);
|
|
254
|
+
if (index >= 0) cursor = index + words.length;
|
|
255
|
+
for (const match of text.matchAll(POINTER)) {
|
|
256
|
+
const target = match[1];
|
|
257
|
+
const link = linkFor(target);
|
|
258
|
+
if (!link) continue;
|
|
259
|
+
const command = `astryx docs ${target}`;
|
|
260
|
+
const line =
|
|
261
|
+
index < 0
|
|
262
|
+
? null
|
|
263
|
+
: lineAtOffset(
|
|
264
|
+
source,
|
|
265
|
+
index,
|
|
266
|
+
words,
|
|
267
|
+
/** @type {number} */ (match.index) + 1,
|
|
268
|
+
);
|
|
269
|
+
const where = [
|
|
270
|
+
section ? `section "${section}"` : null,
|
|
271
|
+
field ? `field ${field}` : null,
|
|
272
|
+
line == null ? null : `line ${line}`,
|
|
273
|
+
]
|
|
274
|
+
.filter(Boolean)
|
|
275
|
+
.join(', ');
|
|
276
|
+
found.push({
|
|
277
|
+
topic: name,
|
|
278
|
+
kind: topic.kind,
|
|
279
|
+
section,
|
|
280
|
+
field,
|
|
281
|
+
file: topic.file,
|
|
282
|
+
line,
|
|
283
|
+
pointer: command,
|
|
284
|
+
link,
|
|
285
|
+
message:
|
|
286
|
+
`${label}${where ? ` (${where})` : ''} points at a doc with the written command \`${command}\`. ` +
|
|
287
|
+
`Replace \`${command}\`, code ticks included, with ${link}: the CLI prints the command that opens the doc, and doctor checks the link.`,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return found;
|
|
293
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
import {describe, expect, it} from 'vitest';
|
|
4
|
+
|
|
5
|
+
import {linkableStrings, pointersIn} from './stray-pointers.mjs';
|
|
6
|
+
|
|
7
|
+
describe('pointersIn', () => {
|
|
8
|
+
it('finds a code span that is exactly the command opening one doc', () => {
|
|
9
|
+
expect(
|
|
10
|
+
pointersIn(
|
|
11
|
+
'Read `astryx docs theme`, then `astryx docs layout-spacing`.',
|
|
12
|
+
),
|
|
13
|
+
).toEqual(['theme', 'layout-spacing']);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('leaves a walkthrough alone: more words, a flag, or a route', () => {
|
|
17
|
+
expect(
|
|
18
|
+
pointersIn(
|
|
19
|
+
'Run `astryx docs theme overview`, `astryx docs --json`, `astryx docs cli/integrations`, or `astryx docs`.',
|
|
20
|
+
),
|
|
21
|
+
).toEqual([]);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('leaves the bare name and a runner-written command alone', () => {
|
|
25
|
+
expect(
|
|
26
|
+
pointersIn('See astryx docs theme, or `pnpm astryx docs theme`.'),
|
|
27
|
+
).toEqual([]);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
describe('linkableStrings', () => {
|
|
32
|
+
it("reads a topic's description and summary, then prose, headings, list items and table cells, not code", () => {
|
|
33
|
+
const strings = linkableStrings({
|
|
34
|
+
name: 'acme',
|
|
35
|
+
description: 'Read `astryx docs theme`.',
|
|
36
|
+
summary: 'In short.',
|
|
37
|
+
sections: [
|
|
38
|
+
{
|
|
39
|
+
title: 'Use it',
|
|
40
|
+
content: [
|
|
41
|
+
{type: 'prose', text: 'prose'},
|
|
42
|
+
{type: 'heading', level: 3, text: 'heading'},
|
|
43
|
+
{type: 'list', style: 'unordered', items: ['item']},
|
|
44
|
+
{type: 'table', headers: ['head'], rows: [['cell']]},
|
|
45
|
+
{type: 'code', lang: 'bash', code: 'astryx docs theme'},
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
});
|
|
50
|
+
expect(strings).toEqual([
|
|
51
|
+
{text: 'Read `astryx docs theme`.', section: null, field: 'description'},
|
|
52
|
+
{text: 'In short.', section: null, field: 'summary'},
|
|
53
|
+
{text: 'prose', section: 'Use it', field: null},
|
|
54
|
+
{text: 'heading', section: 'Use it', field: null},
|
|
55
|
+
{text: 'item', section: 'Use it', field: null},
|
|
56
|
+
{text: 'head', section: 'Use it', field: null},
|
|
57
|
+
{text: 'cell', section: 'Use it', field: null},
|
|
58
|
+
]);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("reads a component doc's text fields, not its names, types, defaults, or code", () => {
|
|
62
|
+
const strings = linkableStrings({
|
|
63
|
+
type: 'component',
|
|
64
|
+
name: 'AcmeButton',
|
|
65
|
+
displayName: 'Acme Button',
|
|
66
|
+
usage: {
|
|
67
|
+
description: 'usage',
|
|
68
|
+
bestPractices: [{guidance: true, description: 'practice'}],
|
|
69
|
+
},
|
|
70
|
+
props: [
|
|
71
|
+
{name: 'tone', type: 'string', default: "'a'", description: 'prop'},
|
|
72
|
+
],
|
|
73
|
+
examples: [{label: 'example', code: 'astryx docs theme'}],
|
|
74
|
+
});
|
|
75
|
+
expect(strings).toEqual([
|
|
76
|
+
{text: 'usage', section: null, field: 'usage.description'},
|
|
77
|
+
{
|
|
78
|
+
text: 'practice',
|
|
79
|
+
section: null,
|
|
80
|
+
field: 'usage.bestPractices[0].description',
|
|
81
|
+
},
|
|
82
|
+
{text: 'prop', section: null, field: 'props[0].description'},
|
|
83
|
+
{text: 'example', section: null, field: 'examples[0].label'},
|
|
84
|
+
]);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -20,7 +20,10 @@ import * as path from 'node:path';
|
|
|
20
20
|
import module from 'node:module';
|
|
21
21
|
import {CLI_ROOT} from '../fs/paths.mjs';
|
|
22
22
|
import {detectStylingSystem} from '../agent-docs/agent-docs.mjs';
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
decidePackageManagerIn,
|
|
25
|
+
formatCliCommand,
|
|
26
|
+
} from '../env/package-manager.mjs';
|
|
24
27
|
|
|
25
28
|
// ── Known packages that a template may import without the user installing them.
|
|
26
29
|
// react and react-dom are the framework; @astryxdesign/* is the design system
|
|
@@ -230,7 +233,7 @@ export function analyzeTemplateNeeds(source, cwd) {
|
|
|
230
233
|
}
|
|
231
234
|
if (stylexCompilerNeeded) {
|
|
232
235
|
notes.push(
|
|
233
|
-
|
|
236
|
+
`This template uses StyleX. Your project needs a StyleX compiler plugin \u2014 see \`${formatCliCommand('docs styling-overview')}\` for setup steps.`,
|
|
234
237
|
);
|
|
235
238
|
}
|
|
236
239
|
|
|
@@ -19,6 +19,7 @@ import {moduleExportsName} from './module-exports.mjs';
|
|
|
19
19
|
import {inspectPackageExport} from './package-exports.mjs';
|
|
20
20
|
import {themeImportPackage} from './theme-discovery.mjs';
|
|
21
21
|
import {isLocalThemeOwner, projectPath} from '../config/theme-state.mjs';
|
|
22
|
+
import {formatCliCommand} from '../env/package-manager.mjs';
|
|
22
23
|
|
|
23
24
|
export class ThemeImportError extends Error {}
|
|
24
25
|
|
|
@@ -59,7 +60,7 @@ function resolveLocalTheme(theme, cwd) {
|
|
|
59
60
|
path.relative(cwd, path.join(theme.sourceDir, theme.entry)),
|
|
60
61
|
);
|
|
61
62
|
throw new ThemeImportError(
|
|
62
|
-
`Local theme "${theme.slug}" is not built. Run
|
|
63
|
+
`Local theme "${theme.slug}" is not built. Run \`${formatCliCommand(`theme build ${source}`, cwd)}\` and try again. Missing: ${missing
|
|
63
64
|
.map(file => projectPath(path.relative(cwd, file)))
|
|
64
65
|
.join(', ')}.`,
|
|
65
66
|
);
|
|
@@ -68,8 +69,11 @@ function resolveLocalTheme(theme, cwd) {
|
|
|
68
69
|
throw new ThemeImportError(
|
|
69
70
|
`Local theme "${theme.slug}" built module ${projectPath(
|
|
70
71
|
path.relative(cwd, moduleFile),
|
|
71
|
-
)} does not export "${theme.exportName}". Rebuild it with
|
|
72
|
-
|
|
72
|
+
)} does not export "${theme.exportName}". Rebuild it with \`${formatCliCommand(
|
|
73
|
+
`theme build ${projectPath(
|
|
74
|
+
path.relative(cwd, path.join(theme.sourceDir, theme.entry)),
|
|
75
|
+
)}`,
|
|
76
|
+
cwd,
|
|
73
77
|
)}\`.`,
|
|
74
78
|
);
|
|
75
79
|
}
|
|
@@ -130,7 +134,7 @@ function resolvePackageTheme(theme, cwd, ownerThemeCount) {
|
|
|
130
134
|
findInstalledPackage(cwd, importPackage);
|
|
131
135
|
if (!packageDir) {
|
|
132
136
|
throw new ThemeImportError(
|
|
133
|
-
`Theme package "${importPackage}" is not installed. Run \`npm install ${importPackage}\` (or yarn/pnpm/bun), then run
|
|
137
|
+
`Theme package "${importPackage}" is not installed. Run \`npm install ${importPackage}\` (or yarn/pnpm/bun), then run \`${formatCliCommand(`theme add ${theme.slug}`, cwd)}\`.`,
|
|
134
138
|
);
|
|
135
139
|
}
|
|
136
140
|
const pkg = readPackage(path.join(packageDir, 'package.json'));
|
|
@@ -148,7 +148,7 @@ describe('resolveThemeImports', () => {
|
|
|
148
148
|
});
|
|
149
149
|
|
|
150
150
|
expect(() => resolveThemeImports(theme, {cwd: dir})).toThrow(
|
|
151
|
-
/
|
|
151
|
+
/ theme build src\/themes\/ocean\/oceanTheme\.ts`/i,
|
|
152
152
|
);
|
|
153
153
|
fs.writeFileSync(
|
|
154
154
|
path.join(sourceDir, 'ocean.js'),
|
|
@@ -46,7 +46,7 @@ export function typeTextTooOld(ts) {
|
|
|
46
46
|
const [major, minor] = String(ts.version).split('.').map(Number);
|
|
47
47
|
return major > 4 || (major === 4 && minor >= 8)
|
|
48
48
|
? null
|
|
49
|
-
: `TypeScript ${ts.version} is older than 4.8, the oldest the type comparison reads`;
|
|
49
|
+
: `TypeScript ${ts.version} is older than 4.8, the oldest the type comparison reads; install TypeScript 5.0 through 6 (\`npm install -D typescript@6\`), or on TypeScript 7 add \`@typescript/typescript6\`, to judge them`;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/** How tightly a printed type binds: a slot needs at least its level. */
|
|
@@ -176,7 +176,7 @@ describe('normalizeTypeText', () => {
|
|
|
176
176
|
'string[]',
|
|
177
177
|
]);
|
|
178
178
|
expect(typeTextTooOld({version: '4.7.4'})).toBe(
|
|
179
|
-
'TypeScript 4.7.4 is older than 4.8, the oldest the type comparison reads',
|
|
179
|
+
'TypeScript 4.7.4 is older than 4.8, the oldest the type comparison reads; install TypeScript 5.0 through 6 (`npm install -D typescript@6`), or on TypeScript 7 add `@typescript/typescript6`, to judge them',
|
|
180
180
|
);
|
|
181
181
|
for (const version of ['4.8.4', '5.0.4', '6.0.3', ts.version]) {
|
|
182
182
|
expect(typeTextTooOld({version})).toBeNull();
|
|
@@ -248,17 +248,41 @@ const RUNNERS = {
|
|
|
248
248
|
runs: 'astryx.config, through the config parser',
|
|
249
249
|
sites: ['loadModuleWithParser(..., parseConfig)'],
|
|
250
250
|
},
|
|
251
|
+
'foundation/fs/file-protection.mjs': {
|
|
252
|
+
runs: 'the ignore matcher (CommonJS), loaded when a resolver first reads an ignore file',
|
|
253
|
+
sites: ['require(ignore)'],
|
|
254
|
+
},
|
|
251
255
|
'foundation/discovery/component-discovery.mjs': {
|
|
252
256
|
runs: '@babel/parser, on first use, to read the members a family doc lists in its components without running the doc',
|
|
253
257
|
sites: ['require(@babel/parser)'],
|
|
254
258
|
},
|
|
259
|
+
'foundation/discovery/copied-passages.mjs': {
|
|
260
|
+
runs: "the CLI's own guides and the package's topics, to compare their prose for passages two topics repeat",
|
|
261
|
+
sites: ['builtinGuideFiles', 'loadTopicModule'],
|
|
262
|
+
},
|
|
263
|
+
'foundation/discovery/doc-consistency.mjs': {
|
|
264
|
+
runs: "a package's component docs and topics, to read the props, overlays, sections, and replaces/extends they declare",
|
|
265
|
+
sites: ['importDocModule ×2'],
|
|
266
|
+
},
|
|
267
|
+
'foundation/discovery/doc-fluff.mjs': {
|
|
268
|
+
runs: "the CLI's own guides, to measure the median share of content words a topic's density is compared with",
|
|
269
|
+
sites: ['builtinGuideFiles'],
|
|
270
|
+
},
|
|
255
271
|
'foundation/discovery/docs-discovery.mjs': {
|
|
256
272
|
runs: 'a contributed topic, for its catalog fields: name, title, description, category, and relationships',
|
|
257
273
|
sites: ['importDocModule'],
|
|
258
274
|
},
|
|
275
|
+
'foundation/discovery/stray-pointers.mjs': {
|
|
276
|
+
runs: "the CLI's own guides, for their names, to tell which written `astryx docs <name>` points at a doc that exists",
|
|
277
|
+
sites: ['builtinGuideFiles'],
|
|
278
|
+
},
|
|
259
279
|
'foundation/discovery/project-typescript.mjs': {
|
|
260
|
-
runs: "the project's own typescript, for the author checks that read source and docs with it, and its package.json for the version of one they cannot use",
|
|
261
|
-
sites: [
|
|
280
|
+
runs: "the project's own typescript, for the author checks that read source and docs with it, and its package.json for the version of one they cannot use; beside TypeScript 7, which has no compiler API, the TypeScript 6 API package @typescript/typescript6",
|
|
281
|
+
sites: [
|
|
282
|
+
'require(<computed>)',
|
|
283
|
+
'require(typescript)',
|
|
284
|
+
'require(typescript/package.json)',
|
|
285
|
+
],
|
|
262
286
|
},
|
|
263
287
|
'foundation/discovery/template-adapter.mjs': {
|
|
264
288
|
runs: '@babel/parser, to find the fixture references and page-local bindings in template source; and a template doc that does not validate, to read the replacement it declares',
|
|
@@ -299,6 +323,22 @@ const RUNNERS = {
|
|
|
299
323
|
runs: "each installed integration's manifest",
|
|
300
324
|
sites: ['importUserModule'],
|
|
301
325
|
},
|
|
326
|
+
'foundation/release/cache.mjs': {
|
|
327
|
+
runs: 'npm (under npm-guard.mjs), to install and look up CLI releases in the per-user cache; each installed release once, to check it starts and reports its version; and ps (tasklist on Windows), to confirm the process a stale lock records is node or npm before ending it',
|
|
328
|
+
sites: ['child_process.spawnSync ×5'],
|
|
329
|
+
},
|
|
330
|
+
'foundation/release/npm-guard.mjs': {
|
|
331
|
+
runs: 'npm, in a process group of its own that it ends at the time limit, on Ctrl-C, or when the run that started it goes away',
|
|
332
|
+
sites: ['child_process.spawn'],
|
|
333
|
+
},
|
|
334
|
+
'foundation/release/global-state.mjs': {
|
|
335
|
+
runs: "the background check of the registry's `latest` release, the agent-text step, and the step that installs the global copy's own Core into the release cache, each detached",
|
|
336
|
+
sites: ['child_process.spawn'],
|
|
337
|
+
},
|
|
338
|
+
'foundation/release/handoff.mjs': {
|
|
339
|
+
runs: "the CLI release that answers a project's run, when it is not this copy",
|
|
340
|
+
sites: ['child_process.spawn'],
|
|
341
|
+
},
|
|
302
342
|
'scripts/generate-cli-readme.mjs': {
|
|
303
343
|
runs: '`astryx manifest` and the error-code and response-type docs, to write the README tables (build time, not shipped)',
|
|
304
344
|
sites: ['child_process.spawnSync', 'import(<computed>)'],
|
|
@@ -109,7 +109,10 @@ export async function collectDocInputs(project) {
|
|
|
109
109
|
list.add('components', record.name, record.package, record.docPath);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
-
const coreDir =
|
|
112
|
+
const coreDir =
|
|
113
|
+
typeof project.coreDir === 'function'
|
|
114
|
+
? project.coreDir()
|
|
115
|
+
: findCoreDir(project.cwd);
|
|
113
116
|
if (coreDir != null) {
|
|
114
117
|
for (const name of Object.values(discoverHooks(coreDir)).flat()) {
|
|
115
118
|
const file = findHookDoc(coreDir, name);
|