@astryxdesign/cli 0.7.2-canary.fe2c655 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +119 -0
- package/README.md +175 -154
- package/api/build/_adapter.d.mts +8 -0
- package/api/build/_adapter.mjs +12 -1
- package/api/build/build.doc.mjs +4 -0
- package/api/build/help/help.mjs +1 -1
- package/api/build/kit/kit.mjs +3 -11
- package/api/component/_adapter.d.mts +72 -1
- package/api/component/_adapter.mjs +212 -18
- package/api/component/component.doc.mjs +6 -1
- package/api/component/component.mjs +82 -15
- package/api/component/component.test.mjs +80 -0
- package/api/component/doc-links.test.mjs +386 -0
- package/api/component/integration-export-name.test.mjs +644 -0
- package/api/component/list/list.mjs +42 -4
- package/api/discover/_adapter.d.mts +132 -12
- package/api/discover/_adapter.mjs +488 -27
- package/api/discover/_adapter.test.mjs +599 -17
- package/api/discover/_catalog-view.d.mts +16 -5
- package/api/discover/_catalog-view.mjs +32 -8
- package/api/discover/detail/doc/doc.mjs +9 -1
- package/api/discover/discover.d.mts +11 -0
- package/api/discover/discover.doc.mjs +9 -7
- package/api/discover/discover.mjs +121 -19
- package/api/discover/discover.type.d.mts +20 -7
- package/api/discover/discover.type.mjs +17 -7
- package/api/discover/list/list.d.mts +4 -3
- package/api/discover/list/list.mjs +17 -10
- package/api/docs/_adapter.d.mts +74 -0
- package/api/docs/_adapter.mjs +553 -16
- package/api/docs/docs.doc.mjs +2 -1
- package/api/docs/docs.mjs +2 -1
- package/api/docs/docs.test.mjs +5 -2
- package/api/docs/integration-tree.test.mjs +22 -0
- package/api/docs/integrationDocs.test.mjs +124 -0
- package/api/docs/list/list.mjs +12 -2
- package/api/docs/reference-blocks.test.mjs +1 -3
- package/api/doctor/_adapter.d.mts +108 -0
- package/api/doctor/_adapter.mjs +223 -4
- package/api/doctor/doctor.d.mts +199 -0
- package/api/doctor/doctor.doc.mjs +3 -2
- package/api/doctor/doctor.mjs +530 -34
- package/api/doctor/doctor.test.mjs +180 -14
- package/api/doctor/release-checks.test.mjs +156 -0
- package/api/doctor/theme-checks.mjs +17 -4
- package/api/doctor/theme-checks.test.mjs +223 -7
- package/api/error.d.mts +10 -0
- package/api/error.mjs +25 -0
- package/api/gap-report/gap-report.d.mts +3 -0
- package/api/gap-report/gap-report.doc.mjs +11 -3
- package/api/gap-report/gap-report.mjs +219 -52
- package/api/gap-report/gap-report.test.mjs +233 -0
- package/api/gap-report/gap-report.type.d.mts +41 -0
- package/api/gap-report/gap-report.type.mjs +18 -0
- package/api/hook/_adapter.mjs +3 -11
- package/api/hook/hook.doc.mjs +4 -0
- package/api/hook/list/list.d.mts +1 -1
- package/api/index.d.mts +2 -0
- package/api/index.mjs +2 -0
- package/api/init/_adapter.d.mts +22 -0
- package/api/init/_adapter.mjs +59 -0
- package/api/init/init.d.mts +7 -5
- package/api/init/init.doc.mjs +28 -7
- package/api/init/init.mjs +28 -4
- package/api/init/init.type.d.mts +48 -3
- package/api/init/init.type.mjs +37 -3
- package/api/init/run/run.d.mts +1 -1
- package/api/init/run/run.mjs +17 -6
- package/api/init/user/user.d.mts +14 -0
- package/api/init/user/user.mjs +87 -0
- package/api/init/user/user.test.mjs +232 -0
- package/api/integration/_adapter.d.mts +45 -0
- package/api/integration/_adapter.mjs +112 -0
- package/api/integration/add-contribution.component-names.test.mjs +66 -0
- package/api/integration/add-contribution.mjs +8 -4
- package/api/integration/add-contribution.test.mjs +4 -2
- package/api/integration/authoring-checks.mjs +110 -6
- package/api/integration/authoring-checks.test.mjs +808 -0
- package/api/integration/authoring-checks.type.d.mts +143 -0
- package/api/integration/authoring-checks.type.mjs +74 -2
- package/api/integration/check/check.d.mts +96 -0
- package/api/integration/check/check.mjs +357 -0
- package/api/integration/check/check.test.mjs +489 -0
- package/api/integration/integration-check.type.d.mts +118 -0
- package/api/integration/integration-check.type.mjs +84 -0
- package/api/integration/integrationCheck.doc.d.mts +10 -0
- package/api/integration/integrationCheck.doc.mjs +73 -0
- package/api/integration/integrationComponentConflicts.doc.mjs +45 -6
- package/api/integration/integrationDocConflicts.doc.mjs +22 -5
- package/api/integration/pack-check.mjs +364 -120
- package/api/integration/pack-check.test.mjs +730 -10
- package/api/integration/validate-integration-fixes.test.mjs +67 -0
- package/api/integration/validate-integration.d.mts +8 -0
- package/api/integration/validate-integration.mjs +63 -9
- package/api/integration/validate-integration.test.mjs +88 -8
- package/api/integration/validate-integration.type.d.mts +16 -0
- package/api/integration/validate-integration.type.mjs +14 -1
- package/api/integration/validate-unread-theme-folders.test.mjs +3 -2
- package/api/integration/validateIntegration.doc.mjs +19 -3
- package/api/search/_adapter.d.mts +11 -0
- package/api/search/_adapter.mjs +25 -0
- package/api/search/search.d.mts +82 -13
- package/api/search/search.doc.mjs +8 -3
- package/api/search/search.domain-priority.test.mjs +108 -18
- package/api/search/search.integration-check.test.mjs +24 -0
- package/api/search/search.mjs +645 -64
- package/api/search/search.test.mjs +179 -1
- package/api/search/search.type.d.mts +14 -1
- package/api/search/search.type.mjs +6 -1
- package/api/swizzle/_adapter.mjs +2 -2
- package/api/swizzle/copy/copy.mjs +29 -15
- package/api/template/template-integration.test.mjs +1 -1
- package/api/template/template.test.mjs +120 -3
- package/api/theme/_adapter.d.mts +16 -0
- package/api/theme/_adapter.mjs +32 -5
- package/api/theme/build/build.d.mts +2 -1
- package/api/theme/build/build.family.test.mjs +64 -0
- package/api/theme/build/build.mjs +250 -38
- package/api/theme/build/build.packed-old-core.test.mjs +20 -3
- package/api/theme/build/font-warning.mjs +5 -3
- package/api/theme/build/font-warning.test.mjs +2 -1
- package/api/theme/remove/remove.test.mjs +2 -2
- package/api/theme/targets/targets.mjs +3 -10
- package/api/theme/themeBuild.doc.mjs +4 -4
- package/api/theme/themeTargets.doc.mjs +4 -0
- package/api/theme/use/use.test.mjs +1 -1
- package/api/upgrade/_adapter.d.mts +40 -2
- package/api/upgrade/_adapter.mjs +118 -5
- package/api/upgrade/run/cli-behind-core.test.mjs +438 -0
- package/api/upgrade/run/run.mjs +35 -2
- package/api/upgrade/status/status.d.mts +21 -5
- package/api/upgrade/status/status.mjs +45 -8
- package/api/upgrade/upgrade.doc.mjs +6 -3
- package/api/upgrade/upgrade.mjs +5 -1
- package/api/upgrade/upgrade.type.d.mts +23 -0
- package/api/upgrade/upgrade.type.mjs +16 -1
- package/assets/codemods/__tests__/registry.test.mjs +1 -0
- package/assets/codemods/registry.mjs +1 -0
- package/assets/codemods/runner.mjs +7 -1
- package/assets/codemods/transforms/v0.7.2/__tests__/migrate-list-edge-compensation-to-edge.test.mjs +120 -0
- package/assets/codemods/transforms/v0.7.2/index.mjs +20 -0
- package/assets/codemods/transforms/v0.7.2/migrate-list-edge-compensation-to-edge.mjs +198 -0
- package/assets/discover/official-packages.json +367 -0
- package/assets/docs/README.md +10 -0
- package/assets/docs/author-a-theme.doc.mjs +3 -3
- package/assets/docs/browser-support.doc.mjs +1 -1
- package/assets/docs/getting-started.doc.mjs +26 -6
- package/assets/docs/styling-overview.doc.mjs +1 -1
- package/assets/docs/theme.doc.dense.mjs +1 -1
- package/assets/docs/theme.doc.mjs +2 -2
- package/assets/docs/theme.doc.zh.mjs +1 -1
- package/assets/docs/tree/add-a-component.doc.mjs +22 -2
- package/assets/docs/tree/add-a-theme.doc.mjs +13 -3
- package/assets/docs/tree/add-a-topic.doc.mjs +54 -9
- package/assets/docs/tree/agent-guidance.doc.mjs +19 -5
- package/assets/docs/tree/block-template.doc.mjs +8 -20
- package/assets/docs/tree/build-the-template.doc.mjs +1 -1
- package/assets/docs/tree/building-blocks.doc.mjs +4 -0
- package/assets/docs/tree/check-the-props.doc.mjs +201 -0
- package/assets/docs/tree/check-your-docs.doc.mjs +69 -11
- package/assets/docs/tree/checks.doc.mjs +32 -24
- package/assets/docs/tree/ci-and-containers.doc.mjs +88 -0
- package/assets/docs/tree/cli-command.doc.mjs +142 -0
- package/assets/docs/tree/cli.doc.mjs +6 -0
- package/assets/docs/tree/codemods.doc.mjs +17 -7
- package/assets/docs/tree/commands.doc.mjs +7 -1
- package/assets/docs/tree/component-family.doc.mjs +8 -6
- package/assets/docs/tree/component-imports.doc.mjs +21 -3
- package/assets/docs/tree/components.doc.mjs +7 -1
- package/assets/docs/tree/computer-agent-guide.doc.mjs +160 -0
- package/assets/docs/tree/computer-integrations.doc.mjs +93 -0
- package/assets/docs/tree/configuration.doc.mjs +7 -3
- package/assets/docs/tree/debug-and-gap-reports.doc.mjs +41 -22
- package/assets/docs/tree/define-the-theme.doc.mjs +6 -5
- package/assets/docs/tree/describe-the-component.doc.mjs +3 -3
- package/assets/docs/tree/docs.doc.mjs +9 -3
- package/assets/docs/tree/document-the-template.doc.mjs +1 -1
- package/assets/docs/tree/document-the-theme.doc.mjs +3 -3
- package/assets/docs/tree/export-template-assets.doc.mjs +1 -1
- package/assets/docs/tree/extend-or-replace.doc.mjs +19 -9
- package/assets/docs/tree/fonts-and-assets.doc.mjs +2 -2
- package/assets/docs/tree/generate-a-palette.doc.mjs +7 -5
- package/assets/docs/tree/global-integrations.doc.mjs +124 -0
- package/assets/docs/tree/global.doc.mjs +131 -0
- package/assets/docs/tree/grade-template-with-agent.doc.mjs +5 -5
- package/assets/docs/tree/install-once.doc.mjs +105 -0
- package/assets/docs/tree/integrations.doc.mjs +13 -1
- package/assets/docs/tree/layout-spacing.doc.mjs +2 -3
- package/assets/docs/tree/layout.doc.mjs +6 -6
- package/assets/docs/tree/links.doc.mjs +7 -6
- package/assets/docs/tree/migration-setup.doc.mjs +3 -2
- package/assets/docs/tree/migration-verification.doc.mjs +0 -1
- package/assets/docs/tree/migration.doc.mjs +0 -1
- package/assets/docs/tree/monorepos.doc.mjs +84 -0
- package/assets/docs/tree/package-and-test.doc.mjs +1 -1
- package/assets/docs/tree/page-template.doc.mjs +4 -8
- package/assets/docs/tree/problems.doc.mjs +205 -0
- package/assets/docs/tree/project-global-or-both.doc.mjs +131 -0
- package/assets/docs/tree/publishing.doc.mjs +6 -6
- package/assets/docs/tree/quick-start.doc.mjs +53 -27
- package/assets/docs/tree/reference.doc.mjs +192 -0
- package/assets/docs/tree/replace-a-core-component.doc.mjs +15 -7
- package/assets/docs/tree/replace-a-core-template.doc.mjs +10 -12
- package/assets/docs/tree/scaffold.doc.mjs +1 -1
- package/assets/docs/tree/sections-and-placement.doc.mjs +9 -11
- package/assets/docs/tree/see-it-in-an-app.doc.mjs +17 -5
- package/assets/docs/tree/short-and-findable.doc.mjs +9 -8
- package/assets/docs/tree/single-component.doc.mjs +15 -6
- package/assets/docs/tree/start-a-template.doc.mjs +18 -8
- package/assets/docs/tree/subcomponent.doc.mjs +6 -6
- package/assets/docs/tree/template-assets.doc.mjs +2 -2
- package/assets/docs/tree/template-doc-overview.doc.mjs +6 -17
- package/assets/docs/tree/template-fonts.doc.mjs +1 -1
- package/assets/docs/tree/template-icons.doc.mjs +1 -1
- package/assets/docs/tree/template-images-media.doc.mjs +1 -1
- package/assets/docs/tree/template-styles.doc.mjs +2 -2
- package/assets/docs/tree/templates.doc.mjs +7 -1
- package/assets/docs/tree/test-in-an-app.doc.mjs +7 -7
- package/assets/docs/tree/test-template-in-app.doc.mjs +5 -5
- package/assets/docs/tree/themes.doc.mjs +4 -0
- package/assets/docs/tree/tokens-and-setup.doc.mjs +19 -15
- package/assets/docs/tree/troubleshooting.doc.mjs +29 -13
- package/assets/docs/tree/type-scale.doc.mjs +3 -3
- package/assets/docs/tree/uninstall.doc.mjs +109 -0
- package/assets/docs/tree/updates.doc.mjs +92 -0
- package/assets/docs/tree/upgrading.doc.mjs +6 -6
- package/assets/docs/tree/use-a-theme-in-an-app.doc.mjs +14 -2
- package/assets/docs/tree/verify-packed-template.doc.mjs +3 -3
- package/assets/docs/tree/versioning.doc.mjs +10 -9
- package/assets/docs/tree/who-answers.doc.mjs +119 -0
- package/assets/docs/tree/write-the-template-file.doc.mjs +7 -6
- package/assets/docs/use-a-theme.doc.mjs +2 -2
- package/assets/docs/working-with-ai.doc.mjs +66 -13
- package/assets/theme.template.ts +1 -1
- package/authoring/codemod/codemod.doc.mjs +7 -3
- package/authoring/config/config.doc.mjs +9 -6
- package/authoring/config/type.ts +4 -2
- package/authoring/debug/parse.d.mts +5 -5
- package/authoring/discover/discover.doc.mjs +7 -1
- package/authoring/doctypes/_schema.d.mts +8 -3
- package/authoring/doctypes/_schema.mjs +1 -0
- package/authoring/doctypes/base/graph-fields.doc.mjs +6 -4
- package/authoring/doctypes/command/command.doc.mjs +20 -12
- package/authoring/doctypes/command/type.ts +14 -0
- package/authoring/doctypes/component/component.doc.mjs +30 -27
- package/authoring/doctypes/component/type.ts +21 -8
- package/authoring/doctypes/enum/enum.doc.mjs +7 -4
- package/authoring/doctypes/function/function.doc.mjs +9 -8
- package/authoring/doctypes/hook/hook.doc.mjs +5 -4
- package/authoring/doctypes/hook/type.ts +4 -0
- package/authoring/doctypes/namespace/namespace.doc.mjs +7 -6
- package/authoring/doctypes/reference/reference.doc.mjs +12 -11
- package/authoring/doctypes/schema/schema.doc.mjs +9 -9
- package/authoring/doctypes/template/integration-template.doc.d.mts +11 -0
- package/authoring/doctypes/template/integration-template.doc.mjs +49 -0
- package/authoring/doctypes/template/parse.d.mts +6 -2
- package/authoring/doctypes/template/parse.mjs +3 -1
- package/authoring/doctypes/template/template.doc.mjs +3 -3
- package/authoring/doctypes/template/type.ts +22 -0
- package/authoring/doctypes/theme/theme.doc.mjs +2 -2
- package/authoring/gap-report/gap-report.doc.mjs +2 -2
- package/authoring/identity/identity.doc.mjs +3 -3
- package/authoring/index.d.ts +2 -0
- package/authoring/integration/integration.doc.mjs +30 -6
- package/authoring/integration/parse.test.mjs +21 -0
- package/authoring/integration/schema.d.mts +16 -3
- package/authoring/integration/schema.mjs +34 -2
- package/authoring/integration/type.ts +12 -0
- package/clients/cli/bin/astryx.mjs +20 -3
- package/clients/cli/cli-command.test.mjs +166 -0
- package/clients/cli/commands/blog.doc.mjs +1 -0
- package/clients/cli/commands/build-theme.batch-report.test.mjs +17 -3
- package/clients/cli/commands/build-theme.font-warning.test.mjs +3 -3
- package/clients/cli/commands/build-theme.mjs +26 -13
- package/clients/cli/commands/build-theme.path-safety.test.mjs +224 -6
- package/clients/cli/commands/build-theme.registry.test.mjs +5 -2
- package/clients/cli/commands/build.doc.mjs +1 -0
- package/clients/cli/commands/build.exit-codes-doc.test.mjs +4 -0
- package/clients/cli/commands/cli-postinstall.test.mjs +49 -1
- package/clients/cli/commands/component.doc.mjs +1 -0
- package/clients/cli/commands/discover.broken-integration.test.mjs +11 -7
- package/clients/cli/commands/discover.doc.mjs +9 -1
- package/clients/cli/commands/discover.mjs +144 -93
- package/clients/cli/commands/discover.no-source.test.mjs +448 -33
- package/clients/cli/commands/discover.sources.test.mjs +20 -1
- package/clients/cli/commands/docs.doc.mjs +1 -0
- package/clients/cli/commands/docs.mjs +49 -19
- package/clients/cli/commands/docs.test.mjs +2 -2
- package/clients/cli/commands/doctor-integration-components.doc.mjs +19 -4
- package/clients/cli/commands/doctor-integration-docs.doc.mjs +20 -5
- package/clients/cli/commands/doctor-integration-templates.doc.mjs +1 -0
- package/clients/cli/commands/doctor-integration-validate.doc.mjs +22 -2
- package/clients/cli/commands/doctor-integration.test.mjs +888 -3
- package/clients/cli/commands/doctor.doc.mjs +12 -2
- package/clients/cli/commands/doctor.mjs +292 -7
- package/clients/cli/commands/doctor.test.mjs +10 -4
- package/clients/cli/commands/gap-report.doc.mjs +15 -2
- package/clients/cli/commands/gap-report.mjs +24 -2
- package/clients/cli/commands/gap-report.test.mjs +79 -0
- package/clients/cli/commands/hook.doc.mjs +1 -0
- package/clients/cli/commands/init.behavior.test.mjs +5 -0
- package/clients/cli/commands/init.doc.mjs +29 -3
- package/clients/cli/commands/integration-add.doc.mjs +7 -0
- package/clients/cli/commands/integration-authoring.test.mjs +49 -3
- package/clients/cli/commands/integration-check.doc.mjs +93 -0
- package/clients/cli/commands/integration-check.test.mjs +441 -0
- package/clients/cli/commands/integration-pack.doc.mjs +8 -1
- package/clients/cli/commands/integration-verify.doc.mjs +8 -1
- package/clients/cli/commands/integration.doc.mjs +6 -2
- package/clients/cli/commands/integration.mjs +119 -7
- package/clients/cli/commands/json-contract.test.mjs +11 -2
- package/clients/cli/commands/manifest.doc.mjs +1 -0
- package/clients/cli/commands/outside-project.test.mjs +774 -0
- package/clients/cli/commands/search.doc.mjs +1 -0
- package/clients/cli/commands/search.mjs +16 -11
- package/clients/cli/commands/search.test.mjs +429 -296
- package/clients/cli/commands/setup-nudge.test.mjs +102 -2
- package/clients/cli/commands/swizzle.doc.mjs +7 -0
- package/clients/cli/commands/swizzle.mjs +5 -3
- package/clients/cli/commands/swizzle.routing.test.mjs +19 -2
- package/clients/cli/commands/template.doc.mjs +1 -0
- package/clients/cli/commands/text-json-parity.test.mjs +5 -0
- package/clients/cli/commands/theme-add-lifecycle.test.mjs +3 -3
- package/clients/cli/commands/theme-add.doc.mjs +8 -1
- package/clients/cli/commands/theme-build.doc.mjs +3 -2
- package/clients/cli/commands/theme-eject.doc.mjs +1 -0
- package/clients/cli/commands/theme-list.behavior.test.mjs +6 -0
- package/clients/cli/commands/theme-list.doc.mjs +1 -0
- package/clients/cli/commands/theme-palette-generate.doc.mjs +1 -0
- package/clients/cli/commands/theme-remove.doc.mjs +7 -0
- package/clients/cli/commands/theme-targets.doc.mjs +1 -0
- package/clients/cli/commands/theme-template.doc.mjs +1 -0
- package/clients/cli/commands/theme-use.doc.mjs +7 -0
- package/clients/cli/commands/upgrade.config-ordering.test.mjs +2 -1
- package/clients/cli/commands/upgrade.doc.mjs +22 -1
- package/clients/cli/commands/upgrade.file-protection.test.mjs +3 -2
- package/clients/cli/commands/upgrade.hook-output.test.mjs +2 -1
- package/clients/cli/commands/upgrade.older-cli.test.mjs +160 -0
- package/clients/cli/index.mjs +112 -16
- package/clients/cli/lib/cli-error.mjs +4 -1
- package/clients/cli/lib/component-format.test.mjs +1 -1
- package/clients/cli/lib/define-command.mjs +2 -2
- package/clients/cli/lib/json-shim.mjs +3 -1
- package/clients/cli/lib/manifest.d.ts +9 -0
- package/clients/cli/lib/manifest.mjs +17 -1
- package/clients/cli/lib/manifest.test.mjs +25 -0
- package/foundation/agent-docs/agent-doc-state.d.mts +35 -6
- package/foundation/agent-docs/agent-doc-state.mjs +66 -6
- package/foundation/agent-docs/agent-docs.d.mts +4 -3
- package/foundation/agent-docs/agent-docs.mjs +11 -9
- package/foundation/agent-docs/computer-agent-text.d.mts +133 -0
- package/foundation/agent-docs/computer-agent-text.mjs +623 -0
- package/foundation/agent-docs/computer-agent-text.test.mjs +602 -0
- package/foundation/config/project.d.mts +35 -3
- package/foundation/config/project.mjs +226 -7
- package/foundation/config/project.test.mjs +66 -0
- package/foundation/config/theme-state.mjs +5 -4
- package/foundation/discovery/authoring-self-docs.mjs +2 -1
- package/foundation/discovery/cli-self-docs.mjs +20 -3
- package/foundation/discovery/cli-self-docs.test.mjs +3 -2
- package/foundation/discovery/component-discovery.d.mts +190 -10
- package/foundation/discovery/component-discovery.export-names.test.mjs +760 -0
- package/foundation/discovery/component-discovery.mjs +864 -56
- package/foundation/discovery/component-discovery.test.mjs +96 -0
- package/foundation/discovery/component-replacement.mjs +20 -1
- package/foundation/discovery/component-replacement.test.mjs +40 -0
- package/foundation/discovery/copied-passages.d.mts +216 -0
- package/foundation/discovery/copied-passages.mjs +720 -0
- package/foundation/discovery/copied-passages.test.mjs +124 -0
- package/foundation/discovery/doc-consistency.d.mts +34 -0
- package/foundation/discovery/doc-consistency.mjs +513 -0
- package/foundation/discovery/doc-consistency.test.mjs +347 -0
- package/foundation/discovery/doc-fluff.d.mts +112 -0
- package/foundation/discovery/doc-fluff.mjs +328 -0
- package/foundation/discovery/doc-fluff.test.mjs +142 -0
- package/foundation/discovery/doc-types.d.mts +157 -0
- package/foundation/discovery/doc-types.mjs +1231 -0
- package/foundation/discovery/doc-types.test.mjs +744 -0
- package/foundation/discovery/docs-discovery.d.mts +88 -0
- package/foundation/discovery/docs-discovery.mjs +83 -2
- package/foundation/discovery/integration-doc-files.d.mts +22 -0
- package/foundation/discovery/integration-doc-files.mjs +231 -0
- package/foundation/discovery/integration-doc-files.test.mjs +246 -0
- package/foundation/discovery/module-exports.d.mts +27 -0
- package/foundation/discovery/module-exports.mjs +356 -31
- package/foundation/discovery/module-exports.test.mjs +172 -0
- package/foundation/discovery/package-tsconfig.d.mts +14 -0
- package/foundation/discovery/package-tsconfig.mjs +228 -0
- package/foundation/discovery/package-tsconfig.test.mjs +210 -0
- package/foundation/discovery/project-typescript.d.mts +32 -0
- package/foundation/discovery/project-typescript.mjs +89 -0
- package/foundation/discovery/prop-drift.d.mts +297 -0
- package/foundation/discovery/prop-drift.mjs +2428 -0
- package/foundation/discovery/prop-drift.test.mjs +2337 -0
- package/foundation/discovery/runner-allowlist.d.mts +40 -0
- package/foundation/discovery/runner-allowlist.mjs +53 -0
- package/foundation/discovery/stray-pointers.d.mts +52 -0
- package/foundation/discovery/stray-pointers.mjs +293 -0
- package/foundation/discovery/stray-pointers.test.mjs +86 -0
- package/foundation/discovery/template-adapter.mjs +74 -5
- package/foundation/discovery/template-needs.mjs +5 -2
- package/foundation/discovery/theme-imports.mjs +8 -4
- package/foundation/discovery/theme-imports.test.mjs +1 -1
- package/foundation/discovery/type-match.d.mts +53 -0
- package/foundation/discovery/type-match.mjs +660 -0
- package/foundation/discovery/type-match.test.mjs +169 -0
- package/foundation/discovery/type-text.d.mts +68 -0
- package/foundation/discovery/type-text.mjs +658 -0
- package/foundation/discovery/type-text.test.mjs +196 -0
- package/foundation/discovery/unresolved-references.d.mts +62 -0
- package/foundation/discovery/unresolved-references.mjs +790 -0
- package/foundation/discovery/unresolved-references.test.mjs +567 -0
- package/foundation/doc-compiler/doc-loads.test.mjs +51 -1
- package/foundation/doc-compiler/inputs.mjs +27 -1
- package/foundation/doc-compiler/inputs.test.mjs +0 -1
- package/foundation/doc-compiler/links.d.mts +41 -5
- package/foundation/doc-compiler/links.mjs +167 -28
- package/foundation/doc-compiler/links.test.mjs +97 -4
- package/foundation/doc-compiler/read.d.mts +1 -1
- package/foundation/doc-compiler/tree.mjs +30 -1
- package/foundation/doc-compiler/tree.test.mjs +8 -1
- package/foundation/env/cli-command.d.mts +83 -0
- package/foundation/env/cli-command.mjs +152 -0
- package/foundation/env/cli-command.test.mjs +129 -0
- package/foundation/env/node-version.test.mjs +15 -3
- package/foundation/env/package-manager.d.mts +93 -9
- package/foundation/env/package-manager.global.test.mjs +66 -0
- package/foundation/env/package-manager.mjs +184 -13
- package/foundation/env/package-manager.test.mjs +341 -15
- package/foundation/env/project-scope.d.mts +9 -0
- package/foundation/env/project-scope.mjs +33 -0
- package/foundation/env/search-path.d.mts +42 -0
- package/foundation/env/search-path.mjs +205 -0
- package/foundation/env/search-path.test.mjs +122 -0
- package/foundation/env/user-dirs.d.mts +39 -0
- package/foundation/env/user-dirs.mjs +93 -0
- package/foundation/env/user-dirs.test.mjs +72 -0
- package/foundation/env/user-settings.d.mts +46 -0
- package/foundation/env/user-settings.mjs +106 -0
- package/foundation/env/user-settings.test.mjs +64 -0
- package/foundation/fs/file-protection.mjs +15 -1
- package/foundation/fs/module-loader.d.mts +2 -1
- package/foundation/fs/module-loader.mjs +60 -4
- package/foundation/fs/module-loader.stdout.test.mjs +3 -2
- package/foundation/fs/module-loader.test.mjs +194 -0
- package/foundation/fs/path-compare.d.mts +33 -0
- package/foundation/fs/path-compare.mjs +73 -0
- package/foundation/fs/paths.d.mts +57 -1
- package/foundation/fs/paths.mjs +131 -3
- package/foundation/fs/paths.test.mjs +10 -1
- package/foundation/integrations/computer-integrations.d.mts +78 -0
- package/foundation/integrations/computer-integrations.mjs +316 -0
- package/foundation/integrations/computer-integrations.test.mjs +292 -0
- package/foundation/integrations/contribution-inventory.d.mts +11 -0
- package/foundation/integrations/contribution-inventory.mjs +56 -3
- package/foundation/integrations/integration-warnings.mjs +3 -2
- package/foundation/integrations/integration-warnings.test.mjs +8 -9
- package/foundation/integrations/integrations.d.mts +25 -1
- package/foundation/integrations/integrations.mjs +46 -3
- package/foundation/integrations/issue.ts +6 -0
- package/foundation/integrations/validate-contributions.d.mts +2 -0
- package/foundation/integrations/validate-contributions.mjs +41 -1
- package/foundation/release/agent-text-worker.d.mts +4 -0
- package/foundation/release/agent-text-worker.mjs +52 -0
- package/foundation/release/cache.d.mts +310 -0
- package/foundation/release/cache.mjs +1216 -0
- package/foundation/release/cache.test.mjs +920 -0
- package/foundation/release/choose.d.mts +207 -0
- package/foundation/release/choose.mjs +677 -0
- package/foundation/release/choose.test.mjs +427 -0
- package/foundation/release/core-worker.d.mts +4 -0
- package/foundation/release/core-worker.mjs +38 -0
- package/foundation/release/global-state.d.mts +259 -0
- package/foundation/release/global-state.mjs +472 -0
- package/foundation/release/global-state.test.mjs +381 -0
- package/foundation/release/handoff.d.mts +60 -0
- package/foundation/release/handoff.e2e.test.mjs +278 -0
- package/foundation/release/handoff.mjs +357 -0
- package/foundation/release/lock-lease.d.mts +23 -0
- package/foundation/release/lock-lease.mjs +80 -0
- package/foundation/release/notices.d.mts +253 -0
- package/foundation/release/notices.mjs +596 -0
- package/foundation/release/notices.test.mjs +565 -0
- package/foundation/release/npm-guard.d.mts +4 -0
- package/foundation/release/npm-guard.mjs +126 -0
- package/foundation/release/project.d.mts +141 -0
- package/foundation/release/project.mjs +466 -0
- package/foundation/release/project.test.mjs +288 -0
- package/foundation/release/refresh-worker.d.mts +4 -0
- package/foundation/release/refresh-worker.mjs +27 -0
- package/foundation/release/run-context.d.mts +47 -0
- package/foundation/release/run-context.mjs +149 -0
- package/foundation/release/update-notice-env.d.mts +28 -0
- package/foundation/release/update-notice-env.mjs +39 -0
- package/foundation/response/base.d.ts +26 -3
- package/foundation/response/error-codes.d.mts +3 -1
- package/foundation/response/error-codes.doc.mjs +12 -0
- package/foundation/response/error-codes.mjs +17 -0
- package/foundation/response/error-codes.test.mjs +2 -0
- package/foundation/response/json-contract.test.mjs +7 -2
- package/foundation/response/json.mjs +4 -1
- package/foundation/response/response-types.doc.mjs +22 -11
- package/foundation/response/response-types.doc.test.mjs +46 -0
- package/foundation/response/response.doc.mjs +3 -3
- package/foundation/xle/browser-imports.test.mjs +74 -0
- package/foundation/xle/registry.mjs +4 -0
- package/foundation/xle/registry.test.mjs +28 -0
- package/package.json +11 -11
- package/scripts/postinstall.mjs +24 -5
|
@@ -17,7 +17,18 @@
|
|
|
17
17
|
import {Worker} from 'node:worker_threads';
|
|
18
18
|
import {AstryxError} from '../error.mjs';
|
|
19
19
|
import {Project} from '../../foundation/config/project.mjs';
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
CORE_PACKAGE,
|
|
22
|
+
discoverIntegrationComponents,
|
|
23
|
+
docStem,
|
|
24
|
+
findComponentReadme,
|
|
25
|
+
findIntegrationComponent,
|
|
26
|
+
integrationRecordHold,
|
|
27
|
+
isIntegrationMember,
|
|
28
|
+
unscopedComponentOwners,
|
|
29
|
+
} from '../../foundation/discovery/component-discovery.mjs';
|
|
30
|
+
import {legacyExternalKeeps} from '../component/_adapter.mjs';
|
|
31
|
+
import {findCoreDir} from '../../foundation/fs/paths.mjs';
|
|
21
32
|
import {captureEnv} from '../../foundation/debug/event.mjs';
|
|
22
33
|
import {ERROR_CODES} from '../../foundation/response/error-codes.mjs';
|
|
23
34
|
import {parseGapReportReceipt} from '../../authoring/gap-report/parse.mjs';
|
|
@@ -44,6 +55,14 @@ export const GAP_REPORT_CATEGORIES = Object.freeze([
|
|
|
44
55
|
export const PUBLIC_CONFIRMATION_MESSAGE =
|
|
45
56
|
'Rerun with --confirm-public to file this report.';
|
|
46
57
|
|
|
58
|
+
/** What an agent does when more than one destination exists. */
|
|
59
|
+
export const ASK_DESTINATION_MESSAGE =
|
|
60
|
+
'Ask the person where to file this report, then pass their choice with --to <package>. Never pick a package destination yourself; leave --to out to use the default.';
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @typedef {import('./gap-report.type.mjs').GapReportDestination} GapReportDestination
|
|
64
|
+
*/
|
|
65
|
+
|
|
47
66
|
/**
|
|
48
67
|
* @typedef {object} ReportTarget
|
|
49
68
|
* @property {string} package
|
|
@@ -178,13 +197,65 @@ async function selectTarget(project, component, packageName) {
|
|
|
178
197
|
coreName,
|
|
179
198
|
);
|
|
180
199
|
if (replacement) return targetForPackage(project, replacement.package);
|
|
200
|
+
// The owner rule runs over every owner discovery finds, loadable or not
|
|
201
|
+
// (a doc recorded under another export still answers to its file's name);
|
|
202
|
+
// then only owners whose docs load route a report.
|
|
203
|
+
const wanted = bareComponent.toLowerCase();
|
|
204
|
+
const loads = new Set(records.map(r => `${r.package}\0${r.docPath}`));
|
|
205
|
+
const recorded = project.loadedIntegrations.flatMap(integration =>
|
|
206
|
+
discoverIntegrationComponents(integration).flatMap(r =>
|
|
207
|
+
r.name.toLowerCase() === wanted
|
|
208
|
+
? [{...r, hold: integrationRecordHold(r)}]
|
|
209
|
+
: docStem(r.docPath).toLowerCase() === wanted && !isIntegrationMember(r)
|
|
210
|
+
? [{...r, hold: 'doc'}]
|
|
211
|
+
: [],
|
|
212
|
+
),
|
|
213
|
+
);
|
|
214
|
+
// The checks below find files by name, so they run on every spelling the
|
|
215
|
+
// case-blind match above found, as well as the one typed.
|
|
216
|
+
const spellings = new Set([
|
|
217
|
+
bareComponent,
|
|
218
|
+
...recorded.flatMap(r =>
|
|
219
|
+
[r.name, docStem(r.docPath)].filter(n => n.toLowerCase() === wanted),
|
|
220
|
+
),
|
|
221
|
+
]);
|
|
222
|
+
// Core also holds a name only its doc lookup finds, as in detail: a name a
|
|
223
|
+
// doc records yields to it, though it routes no report itself.
|
|
224
|
+
const coreDir = findCoreDir(project.cwd);
|
|
225
|
+
const coreDocs =
|
|
226
|
+
coreDir != null &&
|
|
227
|
+
[...spellings].some(name => findComponentReadme(coreDir, name) != null);
|
|
228
|
+
const ruled = unscopedComponentOwners([
|
|
229
|
+
...records
|
|
230
|
+
.filter(
|
|
231
|
+
r => r.package === CORE_PACKAGE && r.name.toLowerCase() === wanted,
|
|
232
|
+
)
|
|
233
|
+
.map(r => ({...r, hold: 'core'})),
|
|
234
|
+
...recorded,
|
|
235
|
+
// A hidden doc named after its file still holds that name, as the
|
|
236
|
+
// component lookup finds it; it routes no report.
|
|
237
|
+
...project.loadedIntegrations.flatMap(integration =>
|
|
238
|
+
[...spellings].flatMap(spelling => {
|
|
239
|
+
const found = findIntegrationComponent(integration, spelling);
|
|
240
|
+
return found?.hold === 'file'
|
|
241
|
+
? [{...found, package: integration.name}]
|
|
242
|
+
: [];
|
|
243
|
+
}),
|
|
244
|
+
),
|
|
245
|
+
]).filter(r => !coreDocs || r.hold !== 'doc');
|
|
246
|
+
// A legacy docs package keeps an export name a doc records, as in detail.
|
|
181
247
|
const owners = [
|
|
182
248
|
...new Set(
|
|
183
|
-
|
|
249
|
+
([...spellings].some(name =>
|
|
250
|
+
legacyExternalKeeps(project.cwd, name, ruled),
|
|
251
|
+
)
|
|
252
|
+
? []
|
|
253
|
+
: ruled
|
|
254
|
+
)
|
|
184
255
|
.filter(
|
|
185
|
-
|
|
256
|
+
r => r.hold === 'core' || loads.has(`${r.package}\0${r.docPath}`),
|
|
186
257
|
)
|
|
187
|
-
.map(
|
|
258
|
+
.map(r => r.package),
|
|
188
259
|
),
|
|
189
260
|
];
|
|
190
261
|
|
|
@@ -474,15 +545,14 @@ function githubRoute(issuesUrl) {
|
|
|
474
545
|
}
|
|
475
546
|
|
|
476
547
|
/**
|
|
477
|
-
*
|
|
478
|
-
* Requires confirmPublic.
|
|
548
|
+
* File a report on GitHub with `gh` — for the zero-handler fallback and for a
|
|
549
|
+
* destination the caller names. Requires confirmPublic.
|
|
479
550
|
*
|
|
480
|
-
* @param {ReportTarget} target
|
|
481
551
|
* @param {{component: string, categoryLabel: string, intention: string, detail?: string, source: string, timestamp: string}} report
|
|
482
552
|
* @param {{repo: string}} github
|
|
483
553
|
* @returns {Promise<Pick<import('./gap-report.type.mjs').GapReportDelivery, 'status'|'url'|'message'>>}
|
|
484
554
|
*/
|
|
485
|
-
async function runGithubFallback(
|
|
555
|
+
async function runGithubFallback(report, github) {
|
|
486
556
|
const {execFile} = await import('node:child_process');
|
|
487
557
|
const title = `[gap] ${report.component}: ${report.intention.slice(0, 70)}`;
|
|
488
558
|
const body = [
|
|
@@ -544,6 +614,87 @@ async function runGithubFallback(target, report, github) {
|
|
|
544
614
|
}
|
|
545
615
|
}
|
|
546
616
|
|
|
617
|
+
/**
|
|
618
|
+
* Send a report to an issues URL: a GitHub issues URL is filed with `gh` only
|
|
619
|
+
* with consent; any other URL comes back as routed_only. Serves the
|
|
620
|
+
* zero-handler fallback (spec:AST-031/FR8) and a destination named with `to`
|
|
621
|
+
* (architecture:cli-surface INV36).
|
|
622
|
+
*
|
|
623
|
+
* @param {string} issuesUrl
|
|
624
|
+
* @param {{component: string, categoryLabel: string, intention: string, detail?: string, source: string, timestamp: string}} report
|
|
625
|
+
* @param {boolean} confirmPublic
|
|
626
|
+
* @returns {Promise<import('./gap-report.type.mjs').GapReportDelivery>}
|
|
627
|
+
*/
|
|
628
|
+
async function deliverToIssuesUrl(issuesUrl, report, confirmPublic) {
|
|
629
|
+
const github = githubRoute(issuesUrl);
|
|
630
|
+
if (github != null && !confirmPublic) {
|
|
631
|
+
return {
|
|
632
|
+
handlerType: 'fallback',
|
|
633
|
+
handler: 'github',
|
|
634
|
+
audience: 'public',
|
|
635
|
+
status: 'consent_required',
|
|
636
|
+
url: null,
|
|
637
|
+
message: PUBLIC_CONFIRMATION_MESSAGE,
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
if (github) {
|
|
641
|
+
return {
|
|
642
|
+
handlerType: 'fallback',
|
|
643
|
+
handler: 'github',
|
|
644
|
+
audience: 'public',
|
|
645
|
+
...(await runGithubFallback(report, github)),
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
return {
|
|
649
|
+
handlerType: 'fallback',
|
|
650
|
+
handler: 'issuesUrl',
|
|
651
|
+
audience: null,
|
|
652
|
+
status: 'routed_only',
|
|
653
|
+
url: issuesUrl,
|
|
654
|
+
message:
|
|
655
|
+
'No automatic handler is available; open the routed URL to file this report.',
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/**
|
|
660
|
+
* Where a report can go: the default (the handlers, or with none the owning
|
|
661
|
+
* package's issues URL), then each loaded integration that names its own
|
|
662
|
+
* issues URL (architecture:cli-surface INV36).
|
|
663
|
+
*
|
|
664
|
+
* @param {Project} project
|
|
665
|
+
* @returns {GapReportDestination[]}
|
|
666
|
+
*/
|
|
667
|
+
function listDestinations(project) {
|
|
668
|
+
/** @type {GapReportDestination[]} */
|
|
669
|
+
const destinations = [{to: null, default: true, issuesUrl: null}];
|
|
670
|
+
for (const integration of project.loadedIntegrations) {
|
|
671
|
+
if (integration.__loadError || !integration.issuesUrl) continue;
|
|
672
|
+
if (destinations.some(destination => destination.to === integration.name))
|
|
673
|
+
continue;
|
|
674
|
+
destinations.push({
|
|
675
|
+
to: integration.name,
|
|
676
|
+
default: false,
|
|
677
|
+
issuesUrl: integration.issuesUrl,
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
return destinations;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/**
|
|
684
|
+
* The destinations of the project at `cwd`, or only the default when no
|
|
685
|
+
* project loads there.
|
|
686
|
+
* @param {string|undefined} cwd
|
|
687
|
+
* @returns {Promise<GapReportDestination[]>}
|
|
688
|
+
*/
|
|
689
|
+
async function destinationsAt(cwd) {
|
|
690
|
+
try {
|
|
691
|
+
const {resolve} = await import('node:path');
|
|
692
|
+
return listDestinations(await Project.load(resolve(cwd ?? process.cwd())));
|
|
693
|
+
} catch {
|
|
694
|
+
return [{to: null, default: true, issuesUrl: null}];
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
547
698
|
/**
|
|
548
699
|
* Compute the aggregate status from the deliveries.
|
|
549
700
|
* @param {import('./gap-report.type.mjs').GapReportDelivery[]} deliveries
|
|
@@ -602,6 +753,7 @@ export async function gapReport(component, options = {}) {
|
|
|
602
753
|
options.detail ? '--additional-context' : null,
|
|
603
754
|
options.package ? '--package' : null,
|
|
604
755
|
options.confirmPublic ? '--confirm-public' : null,
|
|
756
|
+
options.to != null ? '--to' : null,
|
|
605
757
|
].filter(Boolean);
|
|
606
758
|
if (ignored.length > 0) {
|
|
607
759
|
throw new AstryxError(
|
|
@@ -610,9 +762,13 @@ export async function gapReport(component, options = {}) {
|
|
|
610
762
|
ERROR_CODES.ERR_INVALID_ARGUMENT,
|
|
611
763
|
);
|
|
612
764
|
}
|
|
765
|
+
const destinations = await destinationsAt(options.cwd);
|
|
613
766
|
return {
|
|
614
767
|
type: 'gap-report.categories',
|
|
615
768
|
data: GAP_REPORT_CATEGORIES.map(category => ({...category})),
|
|
769
|
+
...(destinations.length > 1
|
|
770
|
+
? {meta: {destinations, ask: ASK_DESTINATION_MESSAGE}}
|
|
771
|
+
: {}),
|
|
616
772
|
};
|
|
617
773
|
}
|
|
618
774
|
|
|
@@ -641,7 +797,33 @@ export async function gapReport(component, options = {}) {
|
|
|
641
797
|
options.package,
|
|
642
798
|
);
|
|
643
799
|
|
|
644
|
-
const
|
|
800
|
+
const destinations = listDestinations(project);
|
|
801
|
+
/** @type {GapReportDestination | undefined} */
|
|
802
|
+
let chosen;
|
|
803
|
+
// `to: null` is absent, like `package: null`; any other value is matched
|
|
804
|
+
// against the destinations as given, so an empty or unknown one lists them.
|
|
805
|
+
if (options.to != null) {
|
|
806
|
+
const to = options.to;
|
|
807
|
+
chosen = destinations.find(
|
|
808
|
+
destination => !destination.default && destination.to === to,
|
|
809
|
+
);
|
|
810
|
+
if (!chosen) {
|
|
811
|
+
const choices = destinations.filter(destination => !destination.default);
|
|
812
|
+
const named = JSON.stringify(String(to).slice(0, 214));
|
|
813
|
+
throw new AstryxError(
|
|
814
|
+
choices.length > 0
|
|
815
|
+
? `No gap-report destination ${named}. Choose one of: ${choices.map(destination => destination.to).join(', ')}; or leave out --to for the default.`
|
|
816
|
+
: `No gap-report destination ${named}: no loaded integration names an issues URL. Leave out --to for the default.`,
|
|
817
|
+
choices.map(destination => ({
|
|
818
|
+
name: /** @type {string} */ (destination.to),
|
|
819
|
+
reason: /** @type {string} */ (destination.issuesUrl),
|
|
820
|
+
})),
|
|
821
|
+
ERROR_CODES.ERR_UNKNOWN_PACKAGE,
|
|
822
|
+
);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
const entries = chosen ? [] : collectGapReportHandlers(project);
|
|
645
827
|
|
|
646
828
|
const timestamp = new Date().toISOString();
|
|
647
829
|
const source = captureEnv().invocationSource;
|
|
@@ -668,8 +850,24 @@ export async function gapReport(component, options = {}) {
|
|
|
668
850
|
|
|
669
851
|
/** @type {import('./gap-report.type.mjs').GapReportDelivery[]} */
|
|
670
852
|
const deliveries = [];
|
|
853
|
+
const routeReport = {
|
|
854
|
+
component: resolvedComponent,
|
|
855
|
+
categoryLabel: categoryEntry.label,
|
|
856
|
+
intention,
|
|
857
|
+
detail,
|
|
858
|
+
source,
|
|
859
|
+
timestamp,
|
|
860
|
+
};
|
|
671
861
|
|
|
672
|
-
if (
|
|
862
|
+
if (chosen) {
|
|
863
|
+
deliveries.push(
|
|
864
|
+
await deliverToIssuesUrl(
|
|
865
|
+
/** @type {string} */ (chosen.issuesUrl),
|
|
866
|
+
routeReport,
|
|
867
|
+
options.confirmPublic === true,
|
|
868
|
+
),
|
|
869
|
+
);
|
|
870
|
+
} else if (entries.length > 0) {
|
|
673
871
|
deliveries.push(
|
|
674
872
|
...(await deliverGapReportHandlers(entries, report, {
|
|
675
873
|
confirmPublic: options.confirmPublic === true,
|
|
@@ -683,47 +881,13 @@ export async function gapReport(component, options = {}) {
|
|
|
683
881
|
ERROR_CODES.ERR_NOT_FOUND,
|
|
684
882
|
);
|
|
685
883
|
}
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
status: 'consent_required',
|
|
694
|
-
url: null,
|
|
695
|
-
message: PUBLIC_CONFIRMATION_MESSAGE,
|
|
696
|
-
});
|
|
697
|
-
} else if (github) {
|
|
698
|
-
const outcome = await runGithubFallback(
|
|
699
|
-
target,
|
|
700
|
-
{
|
|
701
|
-
component: resolvedComponent,
|
|
702
|
-
categoryLabel: categoryEntry.label,
|
|
703
|
-
intention,
|
|
704
|
-
detail,
|
|
705
|
-
source,
|
|
706
|
-
timestamp,
|
|
707
|
-
},
|
|
708
|
-
github,
|
|
709
|
-
);
|
|
710
|
-
deliveries.push({
|
|
711
|
-
handlerType: 'fallback',
|
|
712
|
-
handler: 'github',
|
|
713
|
-
audience: 'public',
|
|
714
|
-
...outcome,
|
|
715
|
-
});
|
|
716
|
-
} else {
|
|
717
|
-
deliveries.push({
|
|
718
|
-
handlerType: 'fallback',
|
|
719
|
-
handler: 'issuesUrl',
|
|
720
|
-
audience: null,
|
|
721
|
-
status: 'routed_only',
|
|
722
|
-
url: target.issuesUrl,
|
|
723
|
-
message:
|
|
724
|
-
'No automatic handler is available; open the routed URL to file this report.',
|
|
725
|
-
});
|
|
726
|
-
}
|
|
884
|
+
deliveries.push(
|
|
885
|
+
await deliverToIssuesUrl(
|
|
886
|
+
target.issuesUrl,
|
|
887
|
+
routeReport,
|
|
888
|
+
options.confirmPublic === true,
|
|
889
|
+
),
|
|
890
|
+
);
|
|
727
891
|
}
|
|
728
892
|
|
|
729
893
|
const filedCount = deliveries.filter(d => d.status === 'filed').length;
|
|
@@ -737,10 +901,13 @@ export async function gapReport(component, options = {}) {
|
|
|
737
901
|
data: {
|
|
738
902
|
status,
|
|
739
903
|
package: target.package,
|
|
740
|
-
issuesUrl: target.issuesUrl,
|
|
904
|
+
issuesUrl: chosen ? chosen.issuesUrl : target.issuesUrl,
|
|
741
905
|
deliveries,
|
|
742
906
|
filedCount,
|
|
743
907
|
routedOnlyCount,
|
|
908
|
+
...(!chosen && destinations.length > 1
|
|
909
|
+
? {destinations, ask: ASK_DESTINATION_MESSAGE}
|
|
910
|
+
: {}),
|
|
744
911
|
},
|
|
745
912
|
};
|
|
746
913
|
}
|
|
@@ -7,6 +7,7 @@ import * as path from 'node:path';
|
|
|
7
7
|
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
|
|
8
8
|
import {Project} from '../../foundation/config/project.mjs';
|
|
9
9
|
import {
|
|
10
|
+
ASK_DESTINATION_MESSAGE,
|
|
10
11
|
GAP_REPORT_CATEGORIES,
|
|
11
12
|
PUBLIC_CONFIRMATION_MESSAGE,
|
|
12
13
|
collectGapReportHandlers,
|
|
@@ -1022,6 +1023,238 @@ console.log('https://github.com/acme/widgets/issues/42');
|
|
|
1022
1023
|
});
|
|
1023
1024
|
});
|
|
1024
1025
|
|
|
1026
|
+
describe('gapReport destinations and --to', () => {
|
|
1027
|
+
/** A shared internal handler that records each call in a marker file. */
|
|
1028
|
+
function addSharedHandler() {
|
|
1029
|
+
const marker = path.join(projectDir, 'shared-called');
|
|
1030
|
+
addIntegration({
|
|
1031
|
+
name: '@test/shared',
|
|
1032
|
+
audience: 'internal',
|
|
1033
|
+
handleBody: `(await import('node:fs')).writeFileSync(${JSON.stringify(marker)}, 'x'); return {status: 'filed', message: 'shared'};`,
|
|
1034
|
+
});
|
|
1035
|
+
return marker;
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
function addWidgets(issuesUrl = 'https://github.com/acme/widgets/issues') {
|
|
1039
|
+
addIntegration({name: '@test/widgets', handler: false, issuesUrl});
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
it('keeps the default route and lists the destinations with the ask line', async () => {
|
|
1043
|
+
const marker = addSharedHandler();
|
|
1044
|
+
addWidgets();
|
|
1045
|
+
configure(['@test/shared', '@test/widgets']);
|
|
1046
|
+
const argsFile = stubGh();
|
|
1047
|
+
|
|
1048
|
+
const result = await gapReport('General', {
|
|
1049
|
+
...reportOptions,
|
|
1050
|
+
confirmPublic: true,
|
|
1051
|
+
cwd: projectDir,
|
|
1052
|
+
});
|
|
1053
|
+
|
|
1054
|
+
expect(result.data.deliveries).toEqual([
|
|
1055
|
+
expect.objectContaining({handler: '@test/shared', status: 'filed'}),
|
|
1056
|
+
]);
|
|
1057
|
+
expect(fs.existsSync(marker)).toBe(true);
|
|
1058
|
+
expect(fs.existsSync(argsFile)).toBe(false);
|
|
1059
|
+
expect(result.data.destinations).toEqual([
|
|
1060
|
+
{to: null, default: true, issuesUrl: null},
|
|
1061
|
+
{
|
|
1062
|
+
to: '@test/widgets',
|
|
1063
|
+
default: false,
|
|
1064
|
+
issuesUrl: 'https://github.com/acme/widgets/issues',
|
|
1065
|
+
},
|
|
1066
|
+
]);
|
|
1067
|
+
expect(result.data.ask).toBe(ASK_DESTINATION_MESSAGE);
|
|
1068
|
+
expect(ASK_DESTINATION_MESSAGE).toMatch(/ask the person/i);
|
|
1069
|
+
});
|
|
1070
|
+
|
|
1071
|
+
it('lists no destinations when no integration names an issuesUrl', async () => {
|
|
1072
|
+
addSharedHandler();
|
|
1073
|
+
configure(['@test/shared']);
|
|
1074
|
+
|
|
1075
|
+
const result = await gapReport('General', {
|
|
1076
|
+
...reportOptions,
|
|
1077
|
+
cwd: projectDir,
|
|
1078
|
+
});
|
|
1079
|
+
|
|
1080
|
+
expect(result.data).not.toHaveProperty('destinations');
|
|
1081
|
+
expect(result.data).not.toHaveProperty('ask');
|
|
1082
|
+
});
|
|
1083
|
+
|
|
1084
|
+
it('files with the chosen integration GitHub issuesUrl only with consent, and runs no handler', async () => {
|
|
1085
|
+
const marker = addSharedHandler();
|
|
1086
|
+
addWidgets();
|
|
1087
|
+
configure(['@test/shared', '@test/widgets']);
|
|
1088
|
+
const argsFile = stubGh();
|
|
1089
|
+
|
|
1090
|
+
const pending = await gapReport('General', {
|
|
1091
|
+
...reportOptions,
|
|
1092
|
+
to: '@test/widgets',
|
|
1093
|
+
cwd: projectDir,
|
|
1094
|
+
});
|
|
1095
|
+
expect(pending.data.deliveries).toEqual([
|
|
1096
|
+
{
|
|
1097
|
+
handlerType: 'fallback',
|
|
1098
|
+
handler: 'github',
|
|
1099
|
+
audience: 'public',
|
|
1100
|
+
status: 'consent_required',
|
|
1101
|
+
url: null,
|
|
1102
|
+
message: PUBLIC_CONFIRMATION_MESSAGE,
|
|
1103
|
+
},
|
|
1104
|
+
]);
|
|
1105
|
+
expect(pending.data.issuesUrl).toBe(
|
|
1106
|
+
'https://github.com/acme/widgets/issues',
|
|
1107
|
+
);
|
|
1108
|
+
expect(pending.data).not.toHaveProperty('destinations');
|
|
1109
|
+
expect(fs.existsSync(argsFile)).toBe(false);
|
|
1110
|
+
|
|
1111
|
+
const filed = await gapReport('General', {
|
|
1112
|
+
...reportOptions,
|
|
1113
|
+
to: '@test/widgets',
|
|
1114
|
+
confirmPublic: true,
|
|
1115
|
+
cwd: projectDir,
|
|
1116
|
+
});
|
|
1117
|
+
expect(filed.data.deliveries).toHaveLength(1);
|
|
1118
|
+
expect(filed.data.deliveries[0]).toMatchObject({
|
|
1119
|
+
handlerType: 'fallback',
|
|
1120
|
+
handler: 'github',
|
|
1121
|
+
status: 'filed',
|
|
1122
|
+
});
|
|
1123
|
+
const args = JSON.parse(fs.readFileSync(argsFile, 'utf8'));
|
|
1124
|
+
expect(args.slice(0, 4)).toEqual([
|
|
1125
|
+
'issue',
|
|
1126
|
+
'create',
|
|
1127
|
+
'--repo',
|
|
1128
|
+
'acme/widgets',
|
|
1129
|
+
]);
|
|
1130
|
+
expect(fs.existsSync(marker)).toBe(false);
|
|
1131
|
+
});
|
|
1132
|
+
|
|
1133
|
+
it('routes a chosen non-GitHub issuesUrl as routed_only', async () => {
|
|
1134
|
+
addSharedHandler();
|
|
1135
|
+
addWidgets('https://tracker.example/widgets');
|
|
1136
|
+
configure(['@test/shared', '@test/widgets']);
|
|
1137
|
+
|
|
1138
|
+
const result = await gapReport('General', {
|
|
1139
|
+
...reportOptions,
|
|
1140
|
+
to: '@test/widgets',
|
|
1141
|
+
cwd: projectDir,
|
|
1142
|
+
});
|
|
1143
|
+
|
|
1144
|
+
expect(result.data.deliveries).toEqual([
|
|
1145
|
+
expect.objectContaining({
|
|
1146
|
+
handlerType: 'fallback',
|
|
1147
|
+
handler: 'issuesUrl',
|
|
1148
|
+
status: 'routed_only',
|
|
1149
|
+
url: 'https://tracker.example/widgets',
|
|
1150
|
+
}),
|
|
1151
|
+
]);
|
|
1152
|
+
expect(result.data.status).toBe('routed_only');
|
|
1153
|
+
});
|
|
1154
|
+
|
|
1155
|
+
it.each([
|
|
1156
|
+
['a package that is not loaded', '@test/nope'],
|
|
1157
|
+
['a loaded integration without an issuesUrl', '@test/shared'],
|
|
1158
|
+
])(
|
|
1159
|
+
'refuses --to naming %s, lists the choices, and sends nothing',
|
|
1160
|
+
async (_label, to) => {
|
|
1161
|
+
const marker = addSharedHandler();
|
|
1162
|
+
addWidgets();
|
|
1163
|
+
configure(['@test/shared', '@test/widgets']);
|
|
1164
|
+
|
|
1165
|
+
await expect(
|
|
1166
|
+
gapReport('General', {...reportOptions, to, cwd: projectDir}),
|
|
1167
|
+
).rejects.toMatchObject({
|
|
1168
|
+
code: 'ERR_UNKNOWN_PACKAGE',
|
|
1169
|
+
suggestions: [
|
|
1170
|
+
{
|
|
1171
|
+
name: '@test/widgets',
|
|
1172
|
+
reason: 'https://github.com/acme/widgets/issues',
|
|
1173
|
+
},
|
|
1174
|
+
],
|
|
1175
|
+
});
|
|
1176
|
+
expect(fs.existsSync(marker)).toBe(false);
|
|
1177
|
+
},
|
|
1178
|
+
);
|
|
1179
|
+
|
|
1180
|
+
it.each([
|
|
1181
|
+
['an empty value', ''],
|
|
1182
|
+
['a blank value', ' '],
|
|
1183
|
+
['an over-long value', `@test/${'a'.repeat(300)}`],
|
|
1184
|
+
])('refuses %s for --to with the destination list', async (_label, to) => {
|
|
1185
|
+
const marker = addSharedHandler();
|
|
1186
|
+
addWidgets();
|
|
1187
|
+
configure(['@test/shared', '@test/widgets']);
|
|
1188
|
+
|
|
1189
|
+
await expect(
|
|
1190
|
+
gapReport('General', {...reportOptions, to, cwd: projectDir}),
|
|
1191
|
+
).rejects.toMatchObject({
|
|
1192
|
+
code: 'ERR_UNKNOWN_PACKAGE',
|
|
1193
|
+
suggestions: [{name: '@test/widgets'}],
|
|
1194
|
+
});
|
|
1195
|
+
expect(fs.existsSync(marker)).toBe(false);
|
|
1196
|
+
});
|
|
1197
|
+
|
|
1198
|
+
it('treats to: null as absent', async () => {
|
|
1199
|
+
const marker = addSharedHandler();
|
|
1200
|
+
addWidgets();
|
|
1201
|
+
configure(['@test/shared', '@test/widgets']);
|
|
1202
|
+
|
|
1203
|
+
const result = await gapReport('General', {
|
|
1204
|
+
...reportOptions,
|
|
1205
|
+
to: /** @type {any} */ (null),
|
|
1206
|
+
cwd: projectDir,
|
|
1207
|
+
});
|
|
1208
|
+
|
|
1209
|
+
expect(result.data.deliveries).toHaveLength(1);
|
|
1210
|
+
expect(fs.existsSync(marker)).toBe(true);
|
|
1211
|
+
expect(result.data.destinations).toHaveLength(2);
|
|
1212
|
+
});
|
|
1213
|
+
|
|
1214
|
+
it('lists the destinations with the categories', async () => {
|
|
1215
|
+
addSharedHandler();
|
|
1216
|
+
addWidgets();
|
|
1217
|
+
configure(['@test/shared', '@test/widgets']);
|
|
1218
|
+
|
|
1219
|
+
const listed = await gapReport(undefined, {
|
|
1220
|
+
listCategories: true,
|
|
1221
|
+
cwd: projectDir,
|
|
1222
|
+
});
|
|
1223
|
+
|
|
1224
|
+
expect(listed.data).toEqual(GAP_REPORT_CATEGORIES);
|
|
1225
|
+
expect(listed.meta).toEqual({
|
|
1226
|
+
destinations: [
|
|
1227
|
+
{to: null, default: true, issuesUrl: null},
|
|
1228
|
+
{
|
|
1229
|
+
to: '@test/widgets',
|
|
1230
|
+
default: false,
|
|
1231
|
+
issuesUrl: 'https://github.com/acme/widgets/issues',
|
|
1232
|
+
},
|
|
1233
|
+
],
|
|
1234
|
+
ask: ASK_DESTINATION_MESSAGE,
|
|
1235
|
+
});
|
|
1236
|
+
});
|
|
1237
|
+
|
|
1238
|
+
it('adds no meta to the categories when there is only the default', async () => {
|
|
1239
|
+
configure([]);
|
|
1240
|
+
const listed = await gapReport(undefined, {
|
|
1241
|
+
listCategories: true,
|
|
1242
|
+
cwd: projectDir,
|
|
1243
|
+
});
|
|
1244
|
+
expect(listed).not.toHaveProperty('meta');
|
|
1245
|
+
});
|
|
1246
|
+
|
|
1247
|
+
it('refuses --to with --list-categories', async () => {
|
|
1248
|
+
await expect(
|
|
1249
|
+
gapReport(undefined, {
|
|
1250
|
+
listCategories: true,
|
|
1251
|
+
to: '@test/widgets',
|
|
1252
|
+
cwd: projectDir,
|
|
1253
|
+
}),
|
|
1254
|
+
).rejects.toMatchObject({code: 'ERR_INVALID_ARGUMENT'});
|
|
1255
|
+
});
|
|
1256
|
+
});
|
|
1257
|
+
|
|
1025
1258
|
describe('gapReport target selection', () => {
|
|
1026
1259
|
it('routes to the unique component owner', async () => {
|
|
1027
1260
|
addIntegration({
|
|
@@ -35,10 +35,42 @@ export type GapReportOptions = {
|
|
|
35
35
|
* Return the category vocabulary without routing or writing.
|
|
36
36
|
*/
|
|
37
37
|
listCategories?: boolean | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* A destination the person chose: a loaded integration
|
|
40
|
+
* whose manifest names an issues URL. The report goes only there.
|
|
41
|
+
*/
|
|
42
|
+
to?: string | undefined;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Where a report can go. The default entry (`to: null`) is the configured
|
|
46
|
+
* handlers, or with none the owning package's issues URL.
|
|
47
|
+
*/
|
|
48
|
+
export type GapReportDestination = {
|
|
49
|
+
/**
|
|
50
|
+
* The value to pass as `to`; null for the default.
|
|
51
|
+
*/
|
|
52
|
+
to: string | null;
|
|
53
|
+
/**
|
|
54
|
+
* Whether this is the default destination.
|
|
55
|
+
*/
|
|
56
|
+
default: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* The integration's issues URL; null for the
|
|
59
|
+
* default.
|
|
60
|
+
*/
|
|
61
|
+
issuesUrl: string | null;
|
|
38
62
|
};
|
|
39
63
|
export type GapReportCategoriesResponse = {
|
|
40
64
|
type: "gap-report.categories";
|
|
41
65
|
data: GapReportCategoryEntry[];
|
|
66
|
+
/**
|
|
67
|
+
* Present when a destination besides the default exists: every destination,
|
|
68
|
+
* and the line telling an agent to ask the person.
|
|
69
|
+
*/
|
|
70
|
+
meta?: {
|
|
71
|
+
destinations: GapReportDestination[];
|
|
72
|
+
ask: string;
|
|
73
|
+
} | undefined;
|
|
42
74
|
};
|
|
43
75
|
export type GapReportAggregateStatus = "filed" | "partial" | "failed" | "routed_only" | "consent_required" | "skipped";
|
|
44
76
|
export type GapReportDeliveryStatus = "filed" | "routed_only" | "skipped" | "failed" | "consent_required";
|
|
@@ -81,6 +113,15 @@ export type GapReportReceipt = {
|
|
|
81
113
|
* Count of handlers that routed only.
|
|
82
114
|
*/
|
|
83
115
|
routedOnlyCount: number;
|
|
116
|
+
/**
|
|
117
|
+
* For a run without `to`,
|
|
118
|
+
* when a destination besides the default exists: every destination.
|
|
119
|
+
*/
|
|
120
|
+
destinations?: GapReportDestination[] | undefined;
|
|
121
|
+
/**
|
|
122
|
+
* With `destinations`: ask the person where to file.
|
|
123
|
+
*/
|
|
124
|
+
ask?: string | undefined;
|
|
84
125
|
};
|
|
85
126
|
export type GapReportReceiptResponse = {
|
|
86
127
|
type: "gap-report.file";
|
|
@@ -23,12 +23,27 @@
|
|
|
23
23
|
* @property {string} [package] Explicit owner package for ambiguous routes.
|
|
24
24
|
* @property {boolean} [confirmPublic] Explicit consent for public handlers or GitHub issue creation.
|
|
25
25
|
* @property {boolean} [listCategories] Return the category vocabulary without routing or writing.
|
|
26
|
+
* @property {string} [to] A destination the person chose: a loaded integration
|
|
27
|
+
* whose manifest names an issues URL. The report goes only there.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Where a report can go. The default entry (`to: null`) is the configured
|
|
32
|
+
* handlers, or with none the owning package's issues URL.
|
|
33
|
+
* @typedef {object} GapReportDestination
|
|
34
|
+
* @property {string|null} to The value to pass as `to`; null for the default.
|
|
35
|
+
* @property {boolean} default Whether this is the default destination.
|
|
36
|
+
* @property {string|null} issuesUrl The integration's issues URL; null for the
|
|
37
|
+
* default.
|
|
26
38
|
*/
|
|
27
39
|
|
|
28
40
|
/**
|
|
29
41
|
* @typedef {object} GapReportCategoriesResponse
|
|
30
42
|
* @property {'gap-report.categories'} type
|
|
31
43
|
* @property {GapReportCategoryEntry[]} data
|
|
44
|
+
* @property {{destinations: GapReportDestination[], ask: string}} [meta]
|
|
45
|
+
* Present when a destination besides the default exists: every destination,
|
|
46
|
+
* and the line telling an agent to ask the person.
|
|
32
47
|
*/
|
|
33
48
|
|
|
34
49
|
/**
|
|
@@ -58,6 +73,9 @@
|
|
|
58
73
|
* @property {GapReportDelivery[]} deliveries Ordered handler outcomes.
|
|
59
74
|
* @property {number} filedCount Count of handlers that filed the report.
|
|
60
75
|
* @property {number} routedOnlyCount Count of handlers that routed only.
|
|
76
|
+
* @property {GapReportDestination[]} [destinations] For a run without `to`,
|
|
77
|
+
* when a destination besides the default exists: every destination.
|
|
78
|
+
* @property {string} [ask] With `destinations`: ask the person where to file.
|
|
61
79
|
*/
|
|
62
80
|
|
|
63
81
|
/**
|