@intentius/chant 0.124.45 → 0.124.48
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/dist/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-hold.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-pass.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-skip.json +10 -0
- package/dist/__golden__/wave-loop/op-cost-member-clash.json +6 -0
- package/dist/__golden__/wave-loop/op-cost-member.json +13 -0
- package/dist/__golden__/wave-loop/op-denied-source.json +16 -0
- package/dist/__golden__/wave-loop/op-denied.json +16 -0
- package/dist/__golden__/wave-loop/op-discover-rest-short.json +6 -0
- package/dist/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
- package/dist/__golden__/wave-loop/op-discover-rest.json +26 -0
- package/dist/__golden__/wave-loop/op-discover-wide.json +26 -0
- package/dist/__golden__/wave-loop/op-held-on-again.json +16 -0
- package/dist/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
- package/dist/__golden__/wave-loop/op-held-on.json +16 -0
- package/dist/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-held.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-pass.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-share.json +33 -0
- package/dist/__golden__/wave-loop/op-outcome-held.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-replan.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
- package/dist/__golden__/wave-loop/op-overridden.json +16 -0
- package/dist/__golden__/wave-loop/op-per-run.json +20 -0
- package/dist/__golden__/wave-loop/op-point.json +13 -0
- package/dist/__golden__/wave-loop/op-pr-review.json +10 -0
- package/dist/__golden__/wave-loop/op-sealed.json +10 -0
- package/dist/__golden__/wave-loop/op-spend-change-only.json +10 -0
- package/dist/__golden__/wave-loop/op-spend.json +10 -0
- package/dist/__golden__/wave-loop/op-wave-commands.json +55 -0
- package/dist/__golden__/wave-loop/op-wide-refused.json +26 -0
- package/dist/__golden__/wave-loop/op-wide-waiting.json +29 -0
- package/dist/__golden__/wave-loop/op-wide.json +39 -0
- package/dist/action-pins.d.ts +61 -0
- package/dist/action-pins.d.ts.map +1 -0
- package/dist/action-pins.js +77 -0
- package/dist/capabilities/aws.paths +148 -0
- package/dist/capabilities/base-mappings.json +122 -0
- package/dist/capabilities/catalog.d.ts +89 -0
- package/dist/capabilities/catalog.d.ts.map +1 -0
- package/dist/capabilities/catalog.js +204 -0
- package/dist/capabilities/language.d.ts +103 -0
- package/dist/capabilities/language.d.ts.map +1 -0
- package/dist/capabilities/language.js +335 -0
- package/dist/capabilities/matcher.d.ts +65 -0
- package/dist/capabilities/matcher.d.ts.map +1 -0
- package/dist/capabilities/matcher.js +299 -0
- package/dist/capabilities/view.d.ts +207 -0
- package/dist/capabilities/view.d.ts.map +1 -0
- package/dist/capabilities/view.js +484 -0
- package/dist/cli/commands/carve.d.ts +3 -0
- package/dist/cli/commands/carve.d.ts.map +1 -1
- package/dist/cli/commands/carve.js +36 -7
- package/dist/cli/commands/import-report.d.ts +26 -0
- package/dist/cli/commands/import-report.d.ts.map +1 -0
- package/dist/cli/commands/import-report.js +65 -0
- package/dist/cli/commands/import.d.ts +11 -1
- package/dist/cli/commands/import.d.ts.map +1 -1
- package/dist/cli/commands/import.js +22 -3
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +1 -0
- package/dist/cli/commands/migrate.d.ts +13 -1
- package/dist/cli/commands/migrate.d.ts.map +1 -1
- package/dist/cli/commands/migrate.js +134 -10
- package/dist/cli/handlers/approve.d.ts.map +1 -1
- package/dist/cli/handlers/approve.js +21 -2
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +6 -1
- package/dist/cli/handlers/declared-graph.d.ts +44 -0
- package/dist/cli/handlers/declared-graph.d.ts.map +1 -0
- package/dist/cli/handlers/declared-graph.js +87 -0
- package/dist/cli/handlers/graph.d.ts +25 -0
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +93 -87
- package/dist/cli/handlers/ledger.d.ts +3 -0
- package/dist/cli/handlers/ledger.d.ts.map +1 -0
- package/dist/cli/handlers/ledger.js +55 -0
- package/dist/cli/handlers/migrate.d.ts.map +1 -1
- package/dist/cli/handlers/migrate.js +18 -11
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/misc.js +12 -1
- package/dist/cli/handlers/pr-env.d.ts.map +1 -1
- package/dist/cli/handlers/pr-env.js +4 -3
- package/dist/cli/handlers/pr.d.ts +15 -1
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +143 -39
- package/dist/cli/handlers/query.d.ts +7 -2
- package/dist/cli/handlers/query.d.ts.map +1 -1
- package/dist/cli/handlers/query.js +16 -4
- package/dist/cli/handlers/release.d.ts.map +1 -1
- package/dist/cli/handlers/release.js +6 -3
- package/dist/cli/handlers/search-count.d.ts +89 -0
- package/dist/cli/handlers/search-count.d.ts.map +1 -0
- package/dist/cli/handlers/search-count.js +132 -0
- package/dist/cli/handlers/search.d.ts +356 -6
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/handlers/search.js +1039 -155
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +88 -17
- package/dist/cli/mcp/server.d.ts.map +1 -1
- package/dist/cli/mcp/server.js +3 -0
- package/dist/cli/mcp/tools/capabilities.d.ts +7 -0
- package/dist/cli/mcp/tools/capabilities.d.ts.map +1 -0
- package/dist/cli/mcp/tools/capabilities.js +27 -0
- package/dist/cli/mcp/workspace-tools.d.ts +3 -1
- package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
- package/dist/cli/mcp/workspace-tools.js +47 -2
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +100 -19
- package/dist/cli/registry.d.ts +36 -4
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/components/builders.d.ts +5 -1
- package/dist/components/builders.d.ts.map +1 -1
- package/dist/components/builders.js +5 -0
- package/dist/components/capability-plugin-loader.d.ts.map +1 -1
- package/dist/components/capability-plugin-loader.js +16 -1
- package/dist/components/capability-plugin.d.ts +14 -0
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/pr-env-ports.d.ts +29 -0
- package/dist/components/pr-env-ports.d.ts.map +1 -0
- package/dist/components/pr-env-ports.js +77 -0
- package/dist/components/pr-env-run.d.ts +5 -21
- package/dist/components/pr-env-run.d.ts.map +1 -1
- package/dist/components/pr-env-run.js +6 -70
- package/dist/components/pr-environment.d.ts +2 -1
- package/dist/components/pr-environment.d.ts.map +1 -1
- package/dist/components/pr-environment.js +1 -1
- package/dist/components/pr-hooks.d.ts +21 -1
- package/dist/components/pr-hooks.d.ts.map +1 -1
- package/dist/components/pr-hooks.js +72 -4
- package/dist/components/pr-pipeline.d.ts +45 -10
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +47 -14
- package/dist/components/pr-policy.d.ts +36 -0
- package/dist/components/pr-policy.d.ts.map +1 -1
- package/dist/components/pr-policy.js +36 -0
- package/dist/components/starter-plugin.d.ts +1 -0
- package/dist/components/starter-plugin.d.ts.map +1 -1
- package/dist/components/starter-plugin.js +5 -1
- package/dist/components/verbs/index.d.ts +2 -0
- package/dist/components/verbs/index.d.ts.map +1 -1
- package/dist/components/verbs/index.js +2 -0
- package/dist/components/verbs/publish-artifact.d.ts +65 -0
- package/dist/components/verbs/publish-artifact.d.ts.map +1 -0
- package/dist/components/verbs/publish-artifact.js +74 -0
- package/dist/components/verbs/publish-image.d.ts +129 -0
- package/dist/components/verbs/publish-image.d.ts.map +1 -0
- package/dist/components/verbs/publish-image.js +145 -0
- package/dist/config-environments.d.ts +112 -0
- package/dist/config-environments.d.ts.map +1 -0
- package/dist/config-environments.js +114 -0
- package/dist/config.d.ts +32 -84
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -96
- package/dist/gate-decision.d.ts +11 -2
- package/dist/gate-decision.d.ts.map +1 -1
- package/dist/gate-decision.js +15 -3
- package/dist/graph-detail.d.ts.map +1 -1
- package/dist/graph-detail.js +15 -3
- package/dist/graph-effective.d.ts +33 -2
- package/dist/graph-effective.d.ts.map +1 -1
- package/dist/graph-effective.js +215 -68
- package/dist/graph-ir.d.ts +48 -0
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ir.js +130 -0
- package/dist/graph-sub-template.d.ts +11 -0
- package/dist/graph-sub-template.d.ts.map +1 -0
- package/dist/graph-sub-template.js +19 -0
- package/dist/graph-walk.d.ts +66 -0
- package/dist/graph-walk.d.ts.map +1 -0
- package/dist/graph-walk.js +70 -0
- package/dist/import/parser.d.ts +19 -0
- package/dist/import/parser.d.ts.map +1 -1
- package/dist/lexicon.d.ts +80 -6
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +11 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/git.d.ts +2 -5
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/ledger-read.d.ts +65 -0
- package/dist/lifecycle/ledger-read.d.ts.map +1 -0
- package/dist/lifecycle/ledger-read.js +160 -0
- package/dist/lifecycle/observe.d.ts +28 -0
- package/dist/lifecycle/observe.d.ts.map +1 -1
- package/dist/lifecycle/observe.js +23 -1
- package/dist/lifecycle/release-workstation.d.ts +7 -0
- package/dist/lifecycle/release-workstation.d.ts.map +1 -1
- package/dist/lifecycle/release-workstation.js +25 -0
- package/dist/lifecycle/run-ledger.d.ts +4 -3
- package/dist/lifecycle/run-ledger.d.ts.map +1 -1
- package/dist/lifecycle/run-ledger.js +1 -0
- package/dist/lint/discover.js +3 -1
- package/dist/lint/post-synth.d.ts +127 -1
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/lint/post-synth.js +84 -2
- package/dist/lint/rule.d.ts +6 -0
- package/dist/lint/rule.d.ts.map +1 -1
- package/dist/lint/rules/op/index.d.ts +1 -0
- package/dist/lint/rules/op/index.d.ts.map +1 -1
- package/dist/lint/rules/op/index.js +2 -0
- package/dist/lint/rules/op/ops019-workspace-op-target.d.ts +32 -0
- package/dist/lint/rules/op/ops019-workspace-op-target.d.ts.map +1 -0
- package/dist/lint/rules/op/ops019-workspace-op-target.js +63 -0
- package/dist/live-endpoint.d.ts +1 -1
- package/dist/live-endpoint.d.ts.map +1 -1
- package/dist/live-endpoint.js +1 -1
- package/dist/observation.d.ts +48 -1
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +21 -5
- package/dist/op/activities/activity-contracts.d.ts +9 -6
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.js +5 -2
- package/dist/op/activities/index.d.ts +2 -2
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/index.js +1 -1
- package/dist/op/activities/review-agent.d.ts +90 -4
- package/dist/op/activities/review-agent.d.ts.map +1 -1
- package/dist/op/activities/review-agent.js +217 -19
- package/dist/op/activities/work-evidence.d.ts +8 -1
- package/dist/op/activities/work-evidence.d.ts.map +1 -1
- package/dist/op/activities/work-evidence.js +1 -0
- package/dist/op/builders.d.ts +9 -5
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/builders.js +9 -5
- package/dist/op/composites/apply-op.d.ts +29 -2
- package/dist/op/composites/apply-op.d.ts.map +1 -1
- package/dist/op/composites/apply-op.js +20 -1
- package/dist/op/gate-approval.d.ts +11 -5
- package/dist/op/gate-approval.d.ts.map +1 -1
- package/dist/op/gate-approval.js +11 -6
- package/dist/op/gate-quorum.d.ts +100 -3
- package/dist/op/gate-quorum.d.ts.map +1 -1
- package/dist/op/gate-quorum.js +108 -6
- package/dist/op/gate-review.d.ts +9 -0
- package/dist/op/gate-review.d.ts.map +1 -1
- package/dist/op/gate-review.js +13 -0
- package/dist/op/gate.d.ts +44 -3
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/gate.js +25 -4
- package/dist/op/index.d.ts +3 -3
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/index.js +1 -1
- package/dist/op/local-executor.d.ts +38 -3
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +48 -6
- package/dist/op/op-waves-run.d.ts +26 -1
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +259 -13
- package/dist/op/op-waves.d.ts +72 -5
- package/dist/op/op-waves.d.ts.map +1 -1
- package/dist/op/op-waves.js +110 -15
- package/dist/op/runtime.d.ts +11 -0
- package/dist/op/runtime.d.ts.map +1 -1
- package/dist/op/schedule-overdue.d.ts +16 -0
- package/dist/op/schedule-overdue.d.ts.map +1 -1
- package/dist/op/schedule-overdue.js +36 -0
- package/dist/op/stage-hooks.d.ts +9 -2
- package/dist/op/stage-hooks.d.ts.map +1 -1
- package/dist/op/stage-hooks.js +7 -5
- package/dist/op/workspace-run-env.d.ts +22 -0
- package/dist/op/workspace-run-env.d.ts.map +1 -0
- package/dist/op/workspace-run-env.js +21 -0
- package/dist/pr-forge.d.ts +24 -0
- package/dist/pr-forge.d.ts.map +1 -1
- package/dist/pr-forge.js +47 -0
- package/dist/pr-post.d.ts +42 -0
- package/dist/pr-post.d.ts.map +1 -1
- package/dist/pr-post.js +67 -1
- package/dist/read-filter.d.ts +65 -0
- package/dist/read-filter.d.ts.map +1 -0
- package/dist/read-filter.js +179 -0
- package/dist/run-event.d.ts +1 -1
- package/dist/run-event.d.ts.map +1 -1
- package/dist/terraform/carve.d.ts +24 -3
- package/dist/terraform/carve.d.ts.map +1 -1
- package/dist/terraform/carve.js +32 -14
- package/dist/terraform/cuts.d.ts +97 -0
- package/dist/terraform/cuts.d.ts.map +1 -0
- package/dist/terraform/cuts.js +138 -0
- package/dist/terraform/folds.d.ts +26 -0
- package/dist/terraform/folds.d.ts.map +1 -0
- package/dist/terraform/folds.js +38 -0
- package/dist/terraform/graph.d.ts.map +1 -1
- package/dist/terraform/graph.js +10 -0
- package/dist/terraform/reach.d.ts +140 -0
- package/dist/terraform/reach.d.ts.map +1 -0
- package/dist/terraform/reach.js +170 -0
- package/dist/terraform/score.d.ts +14 -0
- package/dist/terraform/score.d.ts.map +1 -1
- package/dist/terraform/score.js +14 -31
- package/dist/terraform/state.d.ts.map +1 -1
- package/dist/terraform/state.js +4 -2
- package/dist/terraform/types.d.ts +8 -0
- package/dist/terraform/types.d.ts.map +1 -1
- package/dist/wave-blocked.d.ts +10 -1
- package/dist/wave-blocked.d.ts.map +1 -1
- package/dist/wave-blocked.js +31 -3
- package/dist/wave-runtime.mjs +266 -256
- package/dist/workspace/capabilities-contract.d.ts +66 -0
- package/dist/workspace/capabilities-contract.d.ts.map +1 -0
- package/dist/workspace/capabilities-contract.js +107 -0
- package/dist/workspace/capabilities.schema.json +229 -0
- package/dist/workspace/check.schema.json +11 -2
- package/dist/workspace/checks/ci-branch.d.ts +44 -0
- package/dist/workspace/checks/ci-branch.d.ts.map +1 -0
- package/dist/workspace/checks/ci-branch.js +133 -0
- package/dist/workspace/checks/links.d.ts +3 -0
- package/dist/workspace/checks/links.d.ts.map +1 -1
- package/dist/workspace/checks/links.js +12 -1
- package/dist/workspace/checks/org.d.ts +48 -0
- package/dist/workspace/checks/org.d.ts.map +1 -0
- package/dist/workspace/checks/org.js +156 -0
- package/dist/workspace/checks.d.ts +11 -1
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +59 -7
- package/dist/workspace/ci-branches.d.ts +16 -0
- package/dist/workspace/ci-branches.d.ts.map +1 -1
- package/dist/workspace/ci-branches.js +27 -0
- package/dist/workspace/ci-green-cli.js +7 -7
- package/dist/workspace/ci-green-workflow.d.ts +1 -1
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +13 -8
- package/dist/workspace/ci-green.d.ts +14 -0
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +44 -11
- package/dist/workspace/ci-run.d.ts +9 -1
- package/dist/workspace/ci-run.d.ts.map +1 -1
- package/dist/workspace/ci-run.js +67 -6
- package/dist/workspace/ci-serve.d.ts +9 -0
- package/dist/workspace/ci-serve.d.ts.map +1 -1
- package/dist/workspace/ci-serve.js +114 -76
- package/dist/workspace/compose-graph.d.ts +23 -0
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/compose-graph.js +3 -1
- package/dist/workspace/composites.d.ts +4 -1
- package/dist/workspace/composites.d.ts.map +1 -1
- package/dist/workspace/composites.js +5 -2
- package/dist/workspace/composites.schema.json +22 -0
- package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
- package/dist/workspace/conformance/index.d.ts +1 -1
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/conformance/index.js +39 -2
- package/dist/workspace/cross-root-lint.d.ts +56 -0
- package/dist/workspace/cross-root-lint.d.ts.map +1 -0
- package/dist/workspace/cross-root-lint.js +111 -0
- package/dist/workspace/dbt-models-reader.d.ts +44 -0
- package/dist/workspace/dbt-models-reader.d.ts.map +1 -0
- package/dist/workspace/dbt-models-reader.js +356 -0
- package/dist/workspace/dbt-project-common.d.ts +40 -0
- package/dist/workspace/dbt-project-common.d.ts.map +1 -0
- package/dist/workspace/dbt-project-common.js +106 -0
- package/dist/workspace/dbt-project-reader.d.ts +4 -3
- package/dist/workspace/dbt-project-reader.d.ts.map +1 -1
- package/dist/workspace/dbt-project-reader.js +14 -108
- package/dist/workspace/decision-rank.d.ts +26 -0
- package/dist/workspace/decision-rank.d.ts.map +1 -0
- package/dist/workspace/decision-rank.js +16 -0
- package/dist/workspace/declaration.d.ts +43 -2
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +45 -11
- package/dist/workspace/declaration.schema.json +133 -24
- package/dist/workspace/environments.d.ts +26 -2
- package/dist/workspace/environments.d.ts.map +1 -1
- package/dist/workspace/environments.js +26 -2
- package/dist/workspace/flyway-dir.d.ts +39 -0
- package/dist/workspace/flyway-dir.d.ts.map +1 -0
- package/dist/workspace/flyway-dir.js +104 -0
- package/dist/workspace/flyway-layout.d.ts +96 -0
- package/dist/workspace/flyway-layout.d.ts.map +1 -0
- package/dist/workspace/flyway-layout.js +308 -0
- package/dist/workspace/graph-cache.d.ts +8 -0
- package/dist/workspace/graph-cache.d.ts.map +1 -1
- package/dist/workspace/graph-cache.js +27 -3
- package/dist/workspace/graph-cli.d.ts +39 -2
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/graph-cli.js +92 -32
- package/dist/workspace/graph.schema.json +182 -0
- package/dist/workspace/intent.d.ts +2 -3
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/intent.js +5 -9
- package/dist/workspace/kind-link-readers.d.ts +59 -2
- package/dist/workspace/kind-link-readers.d.ts.map +1 -1
- package/dist/workspace/kind-link-readers.js +17 -1
- package/dist/workspace/kind-readers.d.ts +3 -0
- package/dist/workspace/kind-readers.d.ts.map +1 -1
- package/dist/workspace/kind-readers.js +7 -1
- package/dist/workspace/kinds.d.ts +66 -2
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/kinds.js +98 -4
- package/dist/workspace/ledger.schema.json +158 -0
- package/dist/workspace/lexicon-outputs.d.ts +20 -1
- package/dist/workspace/lexicon-outputs.d.ts.map +1 -1
- package/dist/workspace/lexicon-outputs.js +102 -10
- package/dist/workspace/lineage-check.d.ts +3 -0
- package/dist/workspace/lineage-check.d.ts.map +1 -1
- package/dist/workspace/lineage-check.js +23 -4
- package/dist/workspace/links.d.ts +8 -1
- package/dist/workspace/links.d.ts.map +1 -1
- package/dist/workspace/links.js +25 -1
- package/dist/workspace/ls.d.ts +8 -0
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/ls.js +7 -1
- package/dist/workspace/ls.schema.json +7 -0
- package/dist/workspace/member-commands.d.ts +10 -1
- package/dist/workspace/member-commands.d.ts.map +1 -1
- package/dist/workspace/member-commands.js +71 -6
- package/dist/workspace/migrate-links.d.ts +45 -0
- package/dist/workspace/migrate-links.d.ts.map +1 -0
- package/dist/workspace/migrate-links.js +100 -0
- package/dist/workspace/migration-dirs.d.ts +74 -0
- package/dist/workspace/migration-dirs.d.ts.map +1 -0
- package/dist/workspace/migration-dirs.js +254 -0
- package/dist/workspace/nested-graph.d.ts +2 -0
- package/dist/workspace/nested-graph.d.ts.map +1 -1
- package/dist/workspace/nested-graph.js +32 -1
- package/dist/workspace/reason-codes.d.ts +18 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +23 -0
- package/dist/workspace/records-cli.d.ts +11 -0
- package/dist/workspace/records-cli.d.ts.map +1 -1
- package/dist/workspace/records-cli.js +57 -5
- package/dist/workspace/records.schema.json +5 -0
- package/dist/workspace/release-candidates.d.ts +2 -0
- package/dist/workspace/release-candidates.d.ts.map +1 -1
- package/dist/workspace/release-candidates.js +5 -2
- package/dist/workspace/release-train.d.ts +53 -0
- package/dist/workspace/release-train.d.ts.map +1 -0
- package/dist/workspace/release-train.js +134 -0
- package/dist/workspace/release-workflow.d.ts.map +1 -1
- package/dist/workspace/release-workflow.js +4 -3
- package/dist/workspace/repo-ref.d.ts +45 -0
- package/dist/workspace/repo-ref.d.ts.map +1 -0
- package/dist/workspace/repo-ref.js +114 -0
- package/dist/workspace/run-event.schema.json +2 -2
- package/dist/workspace/runs-cli.d.ts +9 -0
- package/dist/workspace/runs-cli.d.ts.map +1 -1
- package/dist/workspace/runs-cli.js +48 -3
- package/dist/workspace/runs.schema.json +7 -0
- package/dist/workspace/search-cli.d.ts +204 -0
- package/dist/workspace/search-cli.d.ts.map +1 -0
- package/dist/workspace/search-cli.js +466 -0
- package/dist/workspace/search-contract.d.ts +56 -0
- package/dist/workspace/search-contract.d.ts.map +1 -0
- package/dist/workspace/search-contract.js +70 -0
- package/dist/workspace/search.schema.json +822 -0
- package/dist/workspace/status-decisions.d.ts +37 -0
- package/dist/workspace/status-decisions.d.ts.map +1 -0
- package/dist/workspace/status-decisions.js +147 -0
- package/dist/workspace/status-gates.d.ts +9 -0
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status.d.ts +4 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/status.js +14 -2
- package/dist/workspace/status.schema.json +6 -0
- package/dist/workspace/work-cli.d.ts.map +1 -1
- package/dist/workspace/work-cli.js +5 -3
- package/dist/workspace/work-evidence-ops.d.ts +83 -0
- package/dist/workspace/work-evidence-ops.d.ts.map +1 -0
- package/dist/workspace/work-evidence-ops.js +169 -0
- package/dist/workspace/work-evidence.d.ts +12 -2
- package/dist/workspace/work-evidence.d.ts.map +1 -1
- package/dist/workspace/work-evidence.js +21 -3
- package/dist/workspace/work-evidence.schema.json +49 -2
- package/dist/workspace/workspace-gates.d.ts +110 -0
- package/dist/workspace/workspace-gates.d.ts.map +1 -0
- package/dist/workspace/workspace-gates.js +140 -0
- package/dist/workspace/workspace-kinds.schema.json +58 -3
- package/dist/workspace/workspace-ledger.d.ts +76 -0
- package/dist/workspace/workspace-ledger.d.ts.map +1 -0
- package/dist/workspace/workspace-ledger.js +91 -0
- package/dist/workspace/workspace-run.d.ts +112 -0
- package/dist/workspace/workspace-run.d.ts.map +1 -0
- package/dist/workspace/workspace-run.js +432 -0
- package/package.json +1 -1
- package/src/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-hold.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-pass.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-skip.json +10 -0
- package/src/__golden__/wave-loop/op-cost-member-clash.json +6 -0
- package/src/__golden__/wave-loop/op-cost-member.json +13 -0
- package/src/__golden__/wave-loop/op-denied-source.json +16 -0
- package/src/__golden__/wave-loop/op-denied.json +16 -0
- package/src/__golden__/wave-loop/op-discover-rest-short.json +6 -0
- package/src/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
- package/src/__golden__/wave-loop/op-discover-rest.json +26 -0
- package/src/__golden__/wave-loop/op-discover-wide.json +26 -0
- package/src/__golden__/wave-loop/op-held-on-again.json +16 -0
- package/src/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
- package/src/__golden__/wave-loop/op-held-on.json +16 -0
- package/src/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-held.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-pass.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-share.json +33 -0
- package/src/__golden__/wave-loop/op-outcome-held.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-replan.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
- package/src/__golden__/wave-loop/op-overridden.json +16 -0
- package/src/__golden__/wave-loop/op-per-run.json +20 -0
- package/src/__golden__/wave-loop/op-point.json +13 -0
- package/src/__golden__/wave-loop/op-pr-review.json +10 -0
- package/src/__golden__/wave-loop/op-sealed.json +10 -0
- package/src/__golden__/wave-loop/op-spend-change-only.json +10 -0
- package/src/__golden__/wave-loop/op-spend.json +10 -0
- package/src/__golden__/wave-loop/op-wave-commands.json +55 -0
- package/src/__golden__/wave-loop/op-wide-refused.json +26 -0
- package/src/__golden__/wave-loop/op-wide-waiting.json +29 -0
- package/src/__golden__/wave-loop/op-wide.json +39 -0
- package/src/__snapshots__/okf.test.ts.snap +10 -0
- package/src/action-pins.test.ts +78 -0
- package/src/action-pins.ts +92 -0
- package/src/capabilities/aws.paths +148 -0
- package/src/capabilities/base-mappings.json +122 -0
- package/src/capabilities/catalog.ts +230 -0
- package/src/capabilities/language.test.ts +191 -0
- package/src/capabilities/language.ts +373 -0
- package/src/capabilities/matcher.ts +315 -0
- package/src/capabilities/view-compose.test.ts +76 -0
- package/src/capabilities/view.ts +631 -0
- package/src/cli/commands/carve-score-once.test.ts +99 -0
- package/src/cli/commands/carve.ts +37 -6
- package/src/cli/commands/check-lexicon.test.ts +2 -2
- package/src/cli/commands/import-report.ts +71 -0
- package/src/cli/commands/import.ts +33 -3
- package/src/cli/commands/lint.ts +1 -0
- package/src/cli/commands/migrate-dialect.test.ts +145 -0
- package/src/cli/commands/migrate.ts +132 -11
- package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +4 -4
- package/src/cli/handlers/approve.ts +23 -2
- package/src/cli/handlers/build.ts +7 -1
- package/src/cli/handlers/declared-graph.ts +99 -0
- package/src/cli/handlers/graph.test.ts +94 -3
- package/src/cli/handlers/graph.ts +123 -96
- package/src/cli/handlers/ledger.ts +54 -0
- package/src/cli/handlers/migrate.ts +21 -12
- package/src/cli/handlers/misc.ts +10 -1
- package/src/cli/handlers/pr-env.ts +3 -4
- package/src/cli/handlers/pr.ts +138 -36
- package/src/cli/handlers/query.ts +16 -4
- package/src/cli/handlers/release.ts +6 -3
- package/src/cli/handlers/search-build-roots.test.ts +144 -0
- package/src/cli/handlers/search-count.test.ts +191 -0
- package/src/cli/handlers/search-count.ts +165 -0
- package/src/cli/handlers/search-json.test.ts +333 -0
- package/src/cli/handlers/search-live.test.ts +387 -0
- package/src/cli/handlers/search-paths.test.ts +235 -0
- package/src/cli/handlers/search.ts +1291 -166
- package/src/cli/main.test.ts +43 -3
- package/src/cli/main.ts +88 -17
- package/src/cli/mcp/server.test.ts +3 -3
- package/src/cli/mcp/server.ts +3 -0
- package/src/cli/mcp/tools/capabilities.ts +32 -0
- package/src/cli/mcp/workspace-tools.e2e.test.ts +21 -1
- package/src/cli/mcp/workspace-tools.ts +47 -2
- package/src/cli/parse-args.ts +79 -15
- package/src/cli/registry.ts +36 -4
- package/src/components/builders.ts +8 -0
- package/src/components/capability-plugin-loader.ts +13 -1
- package/src/components/capability-plugin.ts +16 -0
- package/src/components/pr-env-ports.ts +89 -0
- package/src/components/pr-env-run-bundle.test.ts +54 -0
- package/src/components/pr-env-run.ts +5 -76
- package/src/components/pr-environment.ts +2 -1
- package/src/components/pr-hooks.test.ts +73 -5
- package/src/components/pr-hooks.ts +95 -5
- package/src/components/pr-pipeline.ts +64 -16
- package/src/components/pr-policy.test.ts +64 -1
- package/src/components/pr-policy.ts +53 -0
- package/src/components/registry.test.ts +1 -1
- package/src/components/starter-plugin.ts +6 -0
- package/src/components/verbs/index.ts +2 -0
- package/src/components/verbs/publish-artifact.test.ts +60 -0
- package/src/components/verbs/publish-artifact.ts +122 -0
- package/src/components/verbs/publish-image.test.ts +101 -0
- package/src/components/verbs/publish-image.ts +265 -0
- package/src/config-environments.ts +160 -0
- package/src/config.ts +44 -124
- package/src/gate-decision-bundle.test.ts +1 -0
- package/src/gate-decision-identity.test.ts +9 -0
- package/src/gate-decision.ts +26 -3
- package/src/graph-detail.ts +15 -3
- package/src/graph-effective.ts +226 -75
- package/src/graph-ir.test.ts +163 -0
- package/src/graph-ir.ts +174 -0
- package/src/graph-sub-template.ts +22 -0
- package/src/graph-walk.test.ts +44 -0
- package/src/graph-walk.ts +102 -0
- package/src/import/parser.ts +20 -0
- package/src/lexicon.ts +84 -6
- package/src/lifecycle/gate-ledger.ts +8 -0
- package/src/lifecycle/git.ts +2 -2
- package/src/lifecycle/ledger-read.test.ts +107 -0
- package/src/lifecycle/ledger-read.ts +195 -0
- package/src/lifecycle/observe.test.ts +27 -1
- package/src/lifecycle/observe.ts +43 -1
- package/src/lifecycle/release-workstation.ts +24 -0
- package/src/lifecycle/run-ledger.ts +5 -2
- package/src/lint/cross-root.test.ts +122 -0
- package/src/lint/discover.ts +3 -1
- package/src/lint/post-synth.ts +212 -2
- package/src/lint/rule.ts +6 -0
- package/src/lint/rules/op/index.ts +2 -0
- package/src/lint/rules/op/ops019-workspace-op-target.ts +89 -0
- package/src/live-endpoint.ts +1 -1
- package/src/observation.test.ts +25 -0
- package/src/observation.ts +69 -5
- package/src/op/activities/activity-contracts.ts +5 -2
- package/src/op/activities/index.ts +2 -2
- package/src/op/activities/review-agent.test.ts +221 -4
- package/src/op/activities/review-agent.ts +265 -22
- package/src/op/activities/work-evidence.ts +9 -1
- package/src/op/builders.ts +9 -5
- package/src/op/composites/apply-op.test.ts +108 -0
- package/src/op/composites/apply-op.ts +37 -2
- package/src/op/gate-approval.test.ts +6 -1
- package/src/op/gate-approval.ts +12 -6
- package/src/op/gate-quorum-at-base.test.ts +211 -0
- package/src/op/gate-quorum.ts +156 -8
- package/src/op/gate-review.ts +14 -0
- package/src/op/gate.ts +67 -8
- package/src/op/index.ts +3 -2
- package/src/op/local-executor.ts +69 -9
- package/src/op/op-waves-depends-on.test.ts +81 -0
- package/src/op/op-waves-hook-targets.test.ts +4 -2
- package/src/op/op-waves-quorum-product.test.ts +158 -0
- package/src/op/op-waves-run.ts +288 -14
- package/src/op/op-waves.ts +143 -14
- package/src/op/runtime.ts +8 -0
- package/src/op/schedule-overdue.ts +33 -0
- package/src/op/stage-hooks.ts +13 -5
- package/src/op/workspace-run-env.ts +29 -0
- package/src/pr-forge-bundle.test.ts +2 -2
- package/src/pr-forge.test.ts +47 -0
- package/src/pr-forge.ts +68 -0
- package/src/pr-post-open.e2e.test.ts +36 -0
- package/src/pr-post.test.ts +102 -3
- package/src/pr-post.ts +89 -1
- package/src/read-filter.test.ts +54 -0
- package/src/read-filter.ts +193 -0
- package/src/run-event.ts +1 -1
- package/src/stage-hooks-bundle.test.ts +1 -0
- package/src/terraform/carve.ts +52 -15
- package/src/terraform/cuts.test.ts +173 -0
- package/src/terraform/cuts.ts +188 -0
- package/src/terraform/folds.ts +44 -0
- package/src/terraform/graph.ts +9 -0
- package/src/terraform/radius.test.ts +90 -0
- package/src/terraform/reach.test.ts +146 -0
- package/src/terraform/reach.ts +247 -0
- package/src/terraform/score.ts +27 -29
- package/src/terraform/state.ts +3 -1
- package/src/terraform/types.ts +8 -0
- package/src/wave-blocked.ts +28 -3
- package/src/wave-loop-golden.test.ts +4 -3
- package/src/workspace/behold-kinds.test.ts +1 -1
- package/src/workspace/capabilities-contract.test.ts +88 -0
- package/src/workspace/capabilities-contract.ts +132 -0
- package/src/workspace/capabilities.schema.json +229 -0
- package/src/workspace/check-contract.test.ts +7 -6
- package/src/workspace/check.schema.json +11 -2
- package/src/workspace/checks/ci-branch.test.ts +128 -0
- package/src/workspace/checks/ci-branch.ts +141 -0
- package/src/workspace/checks/links.ts +12 -1
- package/src/workspace/checks/org.ts +169 -0
- package/src/workspace/checks.ts +64 -7
- package/src/workspace/ci-branches.ts +31 -0
- package/src/workspace/ci-green-branches.test.ts +153 -0
- package/src/workspace/ci-green-cli.ts +7 -7
- package/src/workspace/ci-green-workflow.test.ts +4 -3
- package/src/workspace/ci-green-workflow.ts +13 -9
- package/src/workspace/ci-green.ts +49 -12
- package/src/workspace/ci-run.test.ts +72 -1
- package/src/workspace/ci-run.ts +68 -8
- package/src/workspace/ci-serve.test.ts +95 -0
- package/src/workspace/ci-serve.ts +106 -65
- package/src/workspace/component-environments.test.ts +25 -2
- package/src/workspace/compose-graph.ts +19 -3
- package/src/workspace/composites.schema.json +22 -0
- package/src/workspace/composites.test.ts +39 -8
- package/src/workspace/composites.ts +6 -2
- package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
- package/src/workspace/conformance/conformance.e2e.test.ts +14 -1
- package/src/workspace/conformance/index.ts +31 -2
- package/src/workspace/cross-root-lint.test.ts +90 -0
- package/src/workspace/cross-root-lint.ts +126 -0
- package/src/workspace/dbt-kind.test.ts +3 -2
- package/src/workspace/dbt-models-reader.ts +362 -0
- package/src/workspace/dbt-models.test.ts +248 -0
- package/src/workspace/dbt-project-common.ts +113 -0
- package/src/workspace/dbt-project-reader.ts +29 -112
- package/src/workspace/decision-rank.ts +40 -0
- package/src/workspace/declaration.schema.json +133 -24
- package/src/workspace/declaration.ts +84 -15
- package/src/workspace/environments.ts +40 -4
- package/src/workspace/flyway-dir.ts +113 -0
- package/src/workspace/flyway-layout.ts +337 -0
- package/src/workspace/graph-cache.ts +27 -3
- package/src/workspace/graph-cli.ts +119 -32
- package/src/workspace/graph-contract.test.ts +4 -2
- package/src/workspace/graph.schema.json +182 -0
- package/src/workspace/identity.test.ts +14 -2
- package/src/workspace/intent.ts +6 -14
- package/src/workspace/kind-link-readers.ts +68 -3
- package/src/workspace/kind-readers.e2e.test.ts +28 -0
- package/src/workspace/kind-readers.test.ts +1 -1
- package/src/workspace/kind-readers.ts +7 -1
- package/src/workspace/kinds.test.ts +12 -7
- package/src/workspace/kinds.ts +132 -7
- package/src/workspace/ledger.schema.json +158 -0
- package/src/workspace/lexicon-outputs.ts +132 -13
- package/src/workspace/lineage-check.ts +30 -7
- package/src/workspace/links.ts +24 -1
- package/src/workspace/ls-contract.test.ts +1 -1
- package/src/workspace/ls.schema.json +7 -0
- package/src/workspace/ls.ts +10 -1
- package/src/workspace/member-commands.ts +82 -3
- package/src/workspace/member-file-schema.test.ts +124 -0
- package/src/workspace/migrate-links.test.ts +99 -0
- package/src/workspace/migrate-links.ts +108 -0
- package/src/workspace/migration-dirs.test.ts +272 -0
- package/src/workspace/migration-dirs.ts +267 -0
- package/src/workspace/nested-graph.ts +32 -1
- package/src/workspace/org-scope.test.ts +238 -0
- package/src/workspace/reason-codes.test.ts +13 -1
- package/src/workspace/reason-codes.ts +23 -0
- package/src/workspace/records-cli.ts +58 -5
- package/src/workspace/records.schema.json +5 -0
- package/src/workspace/release-candidates.ts +7 -2
- package/src/workspace/release-train.ts +157 -0
- package/src/workspace/release-workflow.ts +4 -3
- package/src/workspace/repo-ref.ts +113 -0
- package/src/workspace/run-event.schema.json +2 -2
- package/src/workspace/runs-cli.ts +48 -4
- package/src/workspace/runs.schema.json +7 -0
- package/src/workspace/search-cli.e2e.test.ts +305 -0
- package/src/workspace/search-cli.ts +591 -0
- package/src/workspace/search-contract.ts +95 -0
- package/src/workspace/search.schema.json +822 -0
- package/src/workspace/status-contract.test.ts +46 -1
- package/src/workspace/status-decisions.test.ts +100 -0
- package/src/workspace/status-decisions.ts +151 -0
- package/src/workspace/status-gates.ts +9 -0
- package/src/workspace/status.schema.json +6 -0
- package/src/workspace/status.ts +17 -3
- package/src/workspace/where-filters.test.ts +39 -0
- package/src/workspace/work-cli.ts +5 -3
- package/src/workspace/work-evidence-ops.test.ts +176 -0
- package/src/workspace/work-evidence-ops.ts +189 -0
- package/src/workspace/work-evidence.schema.json +49 -2
- package/src/workspace/work-evidence.ts +22 -3
- package/src/workspace/workspace-gates.ts +200 -0
- package/src/workspace/workspace-kinds.schema.json +58 -3
- package/src/workspace/workspace-ledger.ts +130 -0
- package/src/workspace/workspace-run.test.ts +322 -0
- package/src/workspace/workspace-run.ts +461 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Flyway project's layout, read from a workspace tree (#4400): its
|
|
3
|
+
* `flyway.toml` or `flyway.conf`, the locations it names, read recursively,
|
|
4
|
+
* and the placeholders it substitutes.
|
|
5
|
+
*
|
|
6
|
+
* This is the layout reading of sql-yodeler's `src/check/flyway.ts` (#250),
|
|
7
|
+
* moved here so the workspace kind and `yodel check` share one reader. It
|
|
8
|
+
* works on a {@link WorkspaceTree} and tree-relative paths instead of the
|
|
9
|
+
* file system, and it never runs Flyway or connects to a database.
|
|
10
|
+
*
|
|
11
|
+
* The configuration is the first `flyway.toml`, else `flyway.conf`, found in
|
|
12
|
+
* the directory checked or a directory above it, up to the tree's root. Its
|
|
13
|
+
* locations are read relative to the file's own directory:
|
|
14
|
+
*
|
|
15
|
+
* filesystem:<path> that directory
|
|
16
|
+
* classpath:<path> src/main/resources/<path> (and, for code
|
|
17
|
+
* <path> migrations, src/main/java/<path> and src/main/kotlin/<path>)
|
|
18
|
+
*
|
|
19
|
+
* With no configuration, or one that names no location, the directory
|
|
20
|
+
* checked is the one location. A location outside the tree is reported by
|
|
21
|
+
* {@link FlywayConfig.outside}, not read. A Java or Kotlin migration in a
|
|
22
|
+
* location is not SQL and is reported by {@link codeMigrations}.
|
|
23
|
+
*
|
|
24
|
+
* Placeholders are `${name}` (the prefix and suffix are configurable), from
|
|
25
|
+
* `flyway.placeholders.<name>` (conf) or `[flyway.placeholders]` (toml), plus
|
|
26
|
+
* Flyway's own: `flyway:defaultSchema`, `flyway:user`, `flyway:database`,
|
|
27
|
+
* `flyway:timestamp`, `flyway:filename`, `flyway:workingDirectory`,
|
|
28
|
+
* `flyway:table` and `flyway:environment`. {@link substitute} replaces them
|
|
29
|
+
* for a replay; the reader that lists migrations leaves the text as it is.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { posix } from "node:path";
|
|
33
|
+
import { joinPath, type WorkspaceTree } from "./tree";
|
|
34
|
+
|
|
35
|
+
export interface FlywayConfig {
|
|
36
|
+
/** The configuration file, tree-relative; undefined with none. */
|
|
37
|
+
file?: string;
|
|
38
|
+
/** Where file names are relative to: the configuration's directory, else the directory checked. Tree-relative. */
|
|
39
|
+
root: string;
|
|
40
|
+
/** The SQL locations, tree-relative directories. */
|
|
41
|
+
locations: string[];
|
|
42
|
+
/** Directories code migrations (Java, Kotlin) of a classpath location would be in. */
|
|
43
|
+
codeLocations: string[];
|
|
44
|
+
/** Locations the configuration names that lie outside the tree, as written. */
|
|
45
|
+
outside: string[];
|
|
46
|
+
placeholders: Record<string, string>;
|
|
47
|
+
placeholderPrefix: string;
|
|
48
|
+
placeholderSuffix: string;
|
|
49
|
+
placeholderReplacement: boolean;
|
|
50
|
+
sqlMigrationPrefix: string;
|
|
51
|
+
repeatableSqlMigrationPrefix: string;
|
|
52
|
+
baselineMigrationPrefix: string;
|
|
53
|
+
undoSqlMigrationPrefix: string;
|
|
54
|
+
sqlMigrationSeparator: string;
|
|
55
|
+
sqlMigrationSuffixes: string[];
|
|
56
|
+
defaultSchema?: string;
|
|
57
|
+
user?: string;
|
|
58
|
+
database?: string;
|
|
59
|
+
/** The JDBC URL, when the configuration has one. */
|
|
60
|
+
url?: string;
|
|
61
|
+
/** The dialect the URL names: `postgres` or `clickhouse`; undefined for another or none. */
|
|
62
|
+
dialect?: string;
|
|
63
|
+
table: string;
|
|
64
|
+
environment?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** The first `flyway.toml`, else `flyway.conf`, in `dir` or a directory above it, up to the tree's root. */
|
|
68
|
+
export function findFlywayConfig(tree: WorkspaceTree, dir: string): string | undefined {
|
|
69
|
+
let at = dir;
|
|
70
|
+
for (;;) {
|
|
71
|
+
for (const name of ["flyway.toml", "flyway.conf"]) {
|
|
72
|
+
const f = joinPath(at, name);
|
|
73
|
+
if (tree.stat(f) === "file") return f;
|
|
74
|
+
}
|
|
75
|
+
if (at === "" || at === ".") return undefined;
|
|
76
|
+
at = posix.dirname(at) === "." ? "" : posix.dirname(at);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
type Values = Record<string, string | string[] | boolean>;
|
|
81
|
+
|
|
82
|
+
/** Java-properties `flyway.*` keys, without the `flyway.` prefix. */
|
|
83
|
+
export function parseFlywayConf(text: string): Values {
|
|
84
|
+
const out: Values = {};
|
|
85
|
+
const lines = text.split(/\r?\n/);
|
|
86
|
+
for (let i = 0; i < lines.length; i++) {
|
|
87
|
+
let line = lines[i] ?? "";
|
|
88
|
+
while (/\\$/.test(line) && i + 1 < lines.length) line = line.slice(0, -1) + (lines[++i] ?? "").trimStart();
|
|
89
|
+
const t = line.trim();
|
|
90
|
+
if (t === "" || t.startsWith("#") || t.startsWith("!")) continue;
|
|
91
|
+
const m = /^([^=:\s]+)\s*[=:]\s*(.*)$/.exec(t);
|
|
92
|
+
if (!m) continue;
|
|
93
|
+
const key = m[1] ?? "";
|
|
94
|
+
if (!key.startsWith("flyway.")) continue;
|
|
95
|
+
out[key.slice("flyway.".length)] = (m[2] ?? "").trim();
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** A TOML document, as far as Flyway's configuration uses it: tables, strings, arrays of strings, booleans and numbers. */
|
|
101
|
+
export function parseToml(text: string): Record<string, Values> {
|
|
102
|
+
const tables: Record<string, Values> = { "": {} };
|
|
103
|
+
let current = "";
|
|
104
|
+
const lines = text.split(/\r?\n/);
|
|
105
|
+
for (let i = 0; i < lines.length; i++) {
|
|
106
|
+
const t = stripComment(lines[i] ?? "").trim();
|
|
107
|
+
if (t === "") continue;
|
|
108
|
+
const table = /^\[\s*([^\]]+?)\s*\]$/.exec(t);
|
|
109
|
+
if (table) {
|
|
110
|
+
current = (table[1] ?? "").split(".").map((k) => unquote(k.trim())).join(".");
|
|
111
|
+
tables[current] ??= {};
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const kv = /^("[^"]*"|'[^']*'|[A-Za-z0-9_.:-]+)\s*=\s*(.*)$/.exec(t);
|
|
115
|
+
if (!kv) continue;
|
|
116
|
+
let raw = kv[2] ?? "";
|
|
117
|
+
// A multi-line array runs to its closing bracket.
|
|
118
|
+
while (raw.trimStart().startsWith("[") && !balanced(raw) && i + 1 < lines.length) raw += ` ${stripComment(lines[++i] ?? "").trim()}`;
|
|
119
|
+
const path = unquote(kv[1] ?? "").split(".");
|
|
120
|
+
const key = path.pop() ?? "";
|
|
121
|
+
const where = [current, ...path].filter(Boolean).join(".");
|
|
122
|
+
tables[where] ??= {};
|
|
123
|
+
tables[where][key] = tomlValue(raw.trim());
|
|
124
|
+
}
|
|
125
|
+
return tables;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function stripComment(line: string): string {
|
|
129
|
+
let quote: string | undefined;
|
|
130
|
+
for (let i = 0; i < line.length; i++) {
|
|
131
|
+
const c = line[i];
|
|
132
|
+
if (quote) {
|
|
133
|
+
if (c === "\\" && quote === '"') i++;
|
|
134
|
+
else if (c === quote) quote = undefined;
|
|
135
|
+
} else if (c === '"' || c === "'") quote = c;
|
|
136
|
+
else if (c === "#") return line.slice(0, i);
|
|
137
|
+
}
|
|
138
|
+
return line;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const balanced = (s: string) => (s.match(/\[/g) ?? []).length <= (s.match(/\]/g) ?? []).length;
|
|
142
|
+
|
|
143
|
+
function unquote(s: string): string {
|
|
144
|
+
if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) return s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
145
|
+
return s;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function tomlValue(raw: string): string | string[] | boolean {
|
|
149
|
+
if (raw === "true" || raw === "false") return raw === "true";
|
|
150
|
+
if (raw.startsWith("[")) {
|
|
151
|
+
const inner = raw.replace(/^\[/, "").replace(/\]\s*$/, "");
|
|
152
|
+
return (inner.match(/"(?:[^"\\]|\\.)*"|'[^']*'|[^,\s]+/g) ?? []).map((v) => unquote(v.trim())).filter((v) => v !== "");
|
|
153
|
+
}
|
|
154
|
+
return unquote(raw);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const list = (v: string | string[] | boolean | undefined): string[] | undefined =>
|
|
158
|
+
v === undefined || typeof v === "boolean" ? undefined : Array.isArray(v) ? v : v.split(",").map((s) => s.trim()).filter(Boolean);
|
|
159
|
+
const str = (v: string | string[] | boolean | undefined): string | undefined => (typeof v === "string" ? v : Array.isArray(v) ? v.join(",") : undefined);
|
|
160
|
+
|
|
161
|
+
/** The database name a JDBC URL names: the path after the host. */
|
|
162
|
+
function databaseOf(url: string | undefined): string | undefined {
|
|
163
|
+
const m = url === undefined ? null : /^jdbc:[a-z0-9]+:\/\/[^/]+\/([^?;]+)/i.exec(url);
|
|
164
|
+
return m?.[1] ?? undefined;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** The dialect a JDBC URL names. */
|
|
168
|
+
function dialectOf(url: string | undefined): string | undefined {
|
|
169
|
+
const m = url === undefined ? null : /^jdbc:([a-z0-9]+):/i.exec(url);
|
|
170
|
+
const driver = m?.[1]?.toLowerCase();
|
|
171
|
+
return driver === "postgresql" ? "postgres" : driver === "clickhouse" ? "clickhouse" : undefined;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** The configuration `file` holds, or the defaults with `dir` as the one location when there is none. */
|
|
175
|
+
export function readFlywayConfig(tree: WorkspaceTree, file: string | undefined, dir: string): FlywayConfig {
|
|
176
|
+
let values: Values = {};
|
|
177
|
+
let placeholders: Record<string, string> = {};
|
|
178
|
+
if (file !== undefined) {
|
|
179
|
+
const text = tree.read(file);
|
|
180
|
+
if (file.endsWith(".toml")) {
|
|
181
|
+
const t = parseToml(text);
|
|
182
|
+
const flyway = t.flyway ?? {};
|
|
183
|
+
const name = str(flyway.environment) ?? "default";
|
|
184
|
+
const env = t[`environments.${name}`] ?? {};
|
|
185
|
+
values = { ...flyway, ...(t[`environments.${name}.flyway`] ?? {}), ...(env.url !== undefined ? { url: env.url } : {}), ...(env.user !== undefined ? { user: env.user } : {}), ...(env.schemas !== undefined ? { schemas: env.schemas } : {}) };
|
|
186
|
+
if (str(flyway.environment) !== undefined) values.environment = name;
|
|
187
|
+
placeholders = Object.fromEntries(Object.entries({ ...(t["flyway.placeholders"] ?? {}), ...(t[`environments.${name}.flyway.placeholders`] ?? {}) }).map(([k, v]) => [k, str(v) ?? String(v)]));
|
|
188
|
+
} else {
|
|
189
|
+
values = parseFlywayConf(text);
|
|
190
|
+
placeholders = Object.fromEntries(Object.entries(values).flatMap(([k, v]) => (k.startsWith("placeholders.") ? [[k.slice("placeholders.".length), str(v) ?? ""]] : [])));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const root = file === undefined ? dir : posix.dirname(file) === "." ? "" : posix.dirname(file);
|
|
194
|
+
const named = list(values.locations) ?? [];
|
|
195
|
+
const locations: string[] = [];
|
|
196
|
+
const codeLocations: string[] = [];
|
|
197
|
+
const outside: string[] = [];
|
|
198
|
+
const inside = (...parts: string[]): string | undefined => {
|
|
199
|
+
const p = posix.normalize(joinPath(...parts)) || ".";
|
|
200
|
+
if (p === ".." || p.startsWith("../") || posix.isAbsolute(p)) return undefined;
|
|
201
|
+
return p === "." ? "" : p;
|
|
202
|
+
};
|
|
203
|
+
for (const l of named) {
|
|
204
|
+
const m = /^(filesystem|classpath):(.*)$/.exec(l);
|
|
205
|
+
const kind = m?.[1] ?? "classpath";
|
|
206
|
+
const raw = m?.[2] ?? l;
|
|
207
|
+
if (kind === "filesystem") {
|
|
208
|
+
const at = posix.isAbsolute(raw) ? undefined : inside(root, raw);
|
|
209
|
+
if (at === undefined) outside.push(l);
|
|
210
|
+
else locations.push(at);
|
|
211
|
+
} else {
|
|
212
|
+
const path = raw.replace(/^\/+/, "");
|
|
213
|
+
const res = inside(root, "src/main/resources", path);
|
|
214
|
+
if (res === undefined) outside.push(l);
|
|
215
|
+
else {
|
|
216
|
+
locations.push(res);
|
|
217
|
+
for (const lang of ["java", "kotlin"]) {
|
|
218
|
+
const c = inside(root, "src/main", lang, path);
|
|
219
|
+
if (c !== undefined) codeLocations.push(c);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (named.length === 0) locations.push(dir);
|
|
225
|
+
const schemas = list(values.schemas);
|
|
226
|
+
const replacement = values.placeholderReplacement;
|
|
227
|
+
const defaultSchema = str(values.defaultSchema) ?? schemas?.[0];
|
|
228
|
+
const user = str(values.user);
|
|
229
|
+
const url = str(values.url);
|
|
230
|
+
const database = databaseOf(url);
|
|
231
|
+
const dialect = dialectOf(url);
|
|
232
|
+
const environment = str(values.environment);
|
|
233
|
+
return {
|
|
234
|
+
...(file !== undefined ? { file } : {}),
|
|
235
|
+
root,
|
|
236
|
+
locations,
|
|
237
|
+
codeLocations,
|
|
238
|
+
outside,
|
|
239
|
+
placeholders,
|
|
240
|
+
placeholderPrefix: str(values.placeholderPrefix) ?? "${",
|
|
241
|
+
placeholderSuffix: str(values.placeholderSuffix) ?? "}",
|
|
242
|
+
placeholderReplacement: !(replacement === false || replacement === "false"),
|
|
243
|
+
sqlMigrationPrefix: str(values.sqlMigrationPrefix) ?? "V",
|
|
244
|
+
repeatableSqlMigrationPrefix: str(values.repeatableSqlMigrationPrefix) ?? "R",
|
|
245
|
+
baselineMigrationPrefix: str(values.baselineMigrationPrefix) ?? "B",
|
|
246
|
+
undoSqlMigrationPrefix: str(values.undoSqlMigrationPrefix) ?? "U",
|
|
247
|
+
sqlMigrationSeparator: str(values.sqlMigrationSeparator) ?? "__",
|
|
248
|
+
sqlMigrationSuffixes: list(values.sqlMigrationSuffixes) ?? [".sql"],
|
|
249
|
+
...(defaultSchema !== undefined ? { defaultSchema } : {}),
|
|
250
|
+
...(user !== undefined ? { user } : {}),
|
|
251
|
+
...(database !== undefined ? { database } : {}),
|
|
252
|
+
...(url !== undefined ? { url } : {}),
|
|
253
|
+
...(dialect !== undefined ? { dialect } : {}),
|
|
254
|
+
table: str(values.table) ?? "flyway_schema_history",
|
|
255
|
+
...(environment !== undefined ? { environment } : {}),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** Every file under `dir`, recursively, tree-relative, sorted; none when it does not exist. */
|
|
260
|
+
export function walk(tree: WorkspaceTree, dir: string): string[] {
|
|
261
|
+
const entries = tree.list(dir);
|
|
262
|
+
if (!entries) return [];
|
|
263
|
+
const out: string[] = [];
|
|
264
|
+
for (const e of [...entries].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))) {
|
|
265
|
+
const p = joinPath(dir, e.name);
|
|
266
|
+
if (e.type === "dir") out.push(...walk(tree, p));
|
|
267
|
+
else out.push(p);
|
|
268
|
+
}
|
|
269
|
+
return out;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const base = (f: string): string => posix.basename(f);
|
|
273
|
+
|
|
274
|
+
/** A Flyway SQL callback (`beforeMigrate.sql`, `afterEachMigrate__notify.sql`, ...): run around a migrate, not a migration. */
|
|
275
|
+
export const isCallback = (file: string): boolean => /^(before|after)[A-Z][A-Za-z]*(__.*)?\.[A-Za-z]+$/.test(base(file));
|
|
276
|
+
|
|
277
|
+
/** The code migrations (Java, Kotlin) in `config`'s locations, relative to the tree. */
|
|
278
|
+
export function codeMigrations(tree: WorkspaceTree, config: FlywayConfig): string[] {
|
|
279
|
+
const code = /\.(java|kt|class)$/;
|
|
280
|
+
const prefixes = [config.sqlMigrationPrefix, config.repeatableSqlMigrationPrefix, config.baselineMigrationPrefix].filter(Boolean);
|
|
281
|
+
const migration = (f: string) => code.test(f) && prefixes.some((p) => base(f).startsWith(p)) && base(f).includes(config.sqlMigrationSeparator);
|
|
282
|
+
return [...new Set([...config.locations, ...config.codeLocations])].flatMap((d) => walk(tree, d)).filter(migration);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/** The values Flyway gives its own placeholders, for `file`. */
|
|
286
|
+
function builtins(config: FlywayConfig, file: string, fallback: { defaultSchema?: string | undefined }): Record<string, string | undefined> {
|
|
287
|
+
return {
|
|
288
|
+
"flyway:defaultSchema": config.defaultSchema ?? fallback.defaultSchema,
|
|
289
|
+
"flyway:user": config.user,
|
|
290
|
+
"flyway:database": config.database,
|
|
291
|
+
"flyway:timestamp": new Date().toISOString().replace("T", " ").replace(/\..*$/, ""),
|
|
292
|
+
"flyway:filename": base(file),
|
|
293
|
+
"flyway:workingDirectory": process.cwd(),
|
|
294
|
+
"flyway:table": config.table,
|
|
295
|
+
"flyway:environment": config.environment,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const escape = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
300
|
+
|
|
301
|
+
/** A placeholder with no value; `file` is as the caller passed it, `line` is from 1. */
|
|
302
|
+
export class FlywayPlaceholderError extends Error {
|
|
303
|
+
constructor(
|
|
304
|
+
readonly file: string,
|
|
305
|
+
readonly line: number,
|
|
306
|
+
readonly placeholder: string,
|
|
307
|
+
readonly name: string,
|
|
308
|
+
readonly where: string,
|
|
309
|
+
) {
|
|
310
|
+
super(`${file}:${String(line)}: no value for the placeholder ${placeholder}; set it in ${where} (flyway.placeholders.${name} in flyway.conf, [flyway.placeholders] in flyway.toml)`);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* `text` with its placeholders replaced, line by line so line numbers hold.
|
|
316
|
+
* A placeholder with no value throws a {@link FlywayPlaceholderError} naming
|
|
317
|
+
* `file` and the line, as Flyway's own run would fail.
|
|
318
|
+
*/
|
|
319
|
+
export function substitute(text: string, file: string, config: FlywayConfig, fallback: { defaultSchema?: string | undefined } = {}): string {
|
|
320
|
+
if (!config.placeholderReplacement) return text;
|
|
321
|
+
const values: Record<string, string | undefined> = { ...builtins(config, file, fallback), ...config.placeholders };
|
|
322
|
+
const lower = new Map(Object.entries(values).map(([k, v]) => [k.toLowerCase(), v]));
|
|
323
|
+
const pattern = new RegExp(`${escape(config.placeholderPrefix)}([A-Za-z0-9_.:-]+)${escape(config.placeholderSuffix)}`, "g");
|
|
324
|
+
return text
|
|
325
|
+
.split("\n")
|
|
326
|
+
.map((line, i) =>
|
|
327
|
+
line.replace(pattern, (whole, name: string) => {
|
|
328
|
+
const v = values[name] ?? lower.get(name.toLowerCase());
|
|
329
|
+
if (v === undefined) {
|
|
330
|
+
const where = config.file === undefined ? "a flyway.toml or flyway.conf beside the migrations" : config.file;
|
|
331
|
+
throw new FlywayPlaceholderError(file, i + 1, whole, name, where);
|
|
332
|
+
}
|
|
333
|
+
return v;
|
|
334
|
+
}),
|
|
335
|
+
)
|
|
336
|
+
.join("\n");
|
|
337
|
+
}
|
|
@@ -368,9 +368,7 @@ export function splitCached(plan: MemberPlan, args: ParsedArgs, cache: GraphCach
|
|
|
368
368
|
// A member read through a generated reader project (#2874) is also keyed on
|
|
369
369
|
// the kind's graph block and the version of the package that reads it.
|
|
370
370
|
const reader = unit.reader ? readerStamp(unit.reader) : "";
|
|
371
|
-
const abs
|
|
372
|
-
const revision = at ? { commit: at, dir: unit.dir } : undefined;
|
|
373
|
-
const stamp = memberStamp(abs, unit.exclude, revision);
|
|
371
|
+
const { abs, revision, stamp } = unitStamp(plan, unit, at);
|
|
374
372
|
if (!stamp) continue;
|
|
375
373
|
stamps.set(unit.id, stamp.value);
|
|
376
374
|
const key = cacheKey({ member: unit.member, dir: unit.dir, stamp: stamp.value, toolchain: `${tool}\0${reader}`, argv, env });
|
|
@@ -385,6 +383,32 @@ export function splitCached(plan: MemberPlan, args: ParsedArgs, cache: GraphCach
|
|
|
385
383
|
return { hits, stamps, pending, started };
|
|
386
384
|
}
|
|
387
385
|
|
|
386
|
+
/** One unit's stamp, and what it was taken over: the member's directory on disk, and the commit for `--at`. */
|
|
387
|
+
function unitStamp(plan: MemberPlan, unit: RunUnit, at: string | null): { abs: string; revision?: { commit: string; dir: string }; stamp: Stamp | undefined } {
|
|
388
|
+
const abs = unit.dir === "." ? plan.workspace.root : join(plan.workspace.root, ...unit.dir.split("/"));
|
|
389
|
+
const revision = at ? { commit: at, dir: unit.dir } : undefined;
|
|
390
|
+
return { abs, ...(revision ? { revision } : {}), stamp: memberStamp(abs, unit.exclude, revision) };
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Every member unit's stamp, by unit id, by the rule {@link splitCached} keys
|
|
395
|
+
* the cache on (ws-059), with no cache read. A read that is never cached, such
|
|
396
|
+
* as `chant workspace search` (#4374), still stamps its members this way, so a
|
|
397
|
+
* reader compares stamps across documents with one meaning. A unit whose stamp
|
|
398
|
+
* can't be taken is left out.
|
|
399
|
+
*/
|
|
400
|
+
export function planStamps(plan: MemberPlan, at: string | null): Map<string, string> {
|
|
401
|
+
const stamps = new Map<string, string>();
|
|
402
|
+
for (const group of plan.groups) {
|
|
403
|
+
for (const unit of group.units) {
|
|
404
|
+
if (unit.group) continue;
|
|
405
|
+
const { stamp } = unitStamp(plan, unit, at);
|
|
406
|
+
if (stamp) stamps.set(unit.id, stamp.value);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return stamps;
|
|
410
|
+
}
|
|
411
|
+
|
|
388
412
|
/** The plan without the units in `ids`; a toolchain left with no units is dropped. */
|
|
389
413
|
export function withoutUnits(plan: MemberPlan, ids: ReadonlySet<string>): MemberPlan {
|
|
390
414
|
if (ids.size === 0) return plan;
|
|
@@ -31,11 +31,14 @@ import { dirname, join, resolve } from "node:path";
|
|
|
31
31
|
import { formatError } from "../cli/format";
|
|
32
32
|
import type { CommandContext, ParsedArgs } from "../cli/registry";
|
|
33
33
|
import { graphBox, plantability, type Plantable } from "./box-factory";
|
|
34
|
-
import { composeWorkspaceGraph, readMemberIr, type ComposedMember, type ComposeInput, type WorkspaceGraph } from "./compose-graph";
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
34
|
+
import { composedId, composeWorkspaceGraph, readMemberIr, type ComposedMember, type ComposeInput, type WorkspaceGraph } from "./compose-graph";
|
|
35
|
+
import { isViewDocument, prefixView } from "../capabilities/view";
|
|
36
|
+
import { refusedCapabilityView } from "./nested-graph";
|
|
37
|
+
import { openGraphCache, planStamps, splitCached, storeReads, withoutUnits } from "./graph-cache";
|
|
38
|
+
import { readDeclaration, readerVersion, WORKSPACE_ERROR_CODES, WorkspaceReadError, type Declaration, type ErrorLocation, type RepoRef } from "./declaration";
|
|
39
|
+
import { describePlan, emitDocument, executePlan, memberStatus, planJson, planMembers, type MemberArgv, type MemberPlan, type Toolchain, type UnitResult } from "./member-commands";
|
|
40
|
+
import { loadKindRegistry, REPO_KIND, type KindRegistry } from "./kinds";
|
|
41
|
+
import { repoIdentity } from "./repo-ref";
|
|
39
42
|
import { readKindLinks } from "./kind-link-readers";
|
|
40
43
|
import { prepareKindReaders, type PreparedReaders } from "./kind-readers";
|
|
41
44
|
import { recordLinkRows } from "./record-assets";
|
|
@@ -168,6 +171,7 @@ function compose(
|
|
|
168
171
|
only: string[] | undefined,
|
|
169
172
|
declarationMembers: { name: string; dir: string; kind: string }[],
|
|
170
173
|
live = false,
|
|
174
|
+
capabilityView = false,
|
|
171
175
|
): { inputs: ComposeInput[]; failed: boolean } {
|
|
172
176
|
// A member that ran was read live when --live was given, and says when (#2875).
|
|
173
177
|
const read = (member: ComposedMember, r: UnitResult): ComposedMember => {
|
|
@@ -203,6 +207,12 @@ function compose(
|
|
|
203
207
|
}
|
|
204
208
|
const member = read(memberStatus(m.name, m.dir, m.kind, "composed", null, r.chant), r);
|
|
205
209
|
member.irVersion = ir.irVersion;
|
|
210
|
+
// The member's own capability view (#4378), with composed ids; null when its chant printed none.
|
|
211
|
+
if (capabilityView) {
|
|
212
|
+
const view = (ir.ir as { capabilityView?: unknown }).capabilityView;
|
|
213
|
+
member.capabilityView = isViewDocument(view) ? prefixView(view, composedId(m.name, "")) : null;
|
|
214
|
+
}
|
|
215
|
+
delete (ir.ir as { capabilityView?: unknown }).capabilityView;
|
|
206
216
|
inputs.push({ member, ir: ir.ir });
|
|
207
217
|
}
|
|
208
218
|
return { inputs, failed };
|
|
@@ -212,58 +222,125 @@ function compose(
|
|
|
212
222
|
export function planGraph(query: GraphQuery): MemberPlan {
|
|
213
223
|
const located = locateWorkspace(query.cwd, query.at);
|
|
214
224
|
const declaration = readDeclaration(located.tree, "", { rootChant: true });
|
|
215
|
-
const kinds = loadKindRegistry(declaration.pins, located.rootOnDisk)
|
|
216
|
-
return planMembers("graph", located.rootOnDisk, { only: query.members, reader: query.reader, tree: located.tree, kinds });
|
|
225
|
+
const { registry: kinds, problems } = loadKindRegistry(declaration.pins, located.rootOnDisk);
|
|
226
|
+
return planMembers("graph", located.rootOnDisk, { only: query.members, reader: query.reader, tree: located.tree, kinds, kindProblems: problems.map((p) => p.message) });
|
|
217
227
|
}
|
|
218
228
|
|
|
219
|
-
/**
|
|
220
|
-
export
|
|
221
|
-
|
|
229
|
+
/** The members of a workspace read, each read under its own toolchain: what graph and search compose (#4374). */
|
|
230
|
+
export interface MemberReads {
|
|
231
|
+
located: LocatedWorkspace;
|
|
232
|
+
declaration: Declaration;
|
|
233
|
+
kinds: KindRegistry;
|
|
234
|
+
/** The plan the members ran from. */
|
|
235
|
+
plan: MemberPlan;
|
|
236
|
+
/** Each member's answer, the cache's included, in no particular order. */
|
|
237
|
+
results: UnitResult[];
|
|
238
|
+
/** The members the cache answered. */
|
|
239
|
+
served: ReadonlySet<string>;
|
|
240
|
+
/** Each member's stamp, by unit id (ws-059). */
|
|
241
|
+
stamps: ReadonlyMap<string, string>;
|
|
242
|
+
/** With {@link GraphQuery.components}: each member's component graph run. */
|
|
243
|
+
components?: UnitResult[];
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export interface MemberReadOptions {
|
|
247
|
+
/** The command line each member runs; `chant graph --format ir` and the verb's flags by default. */
|
|
248
|
+
argvFor?: MemberArgv;
|
|
249
|
+
/**
|
|
250
|
+
* Answer members from the per-member cache and store what they print
|
|
251
|
+
* (ws-059). Only a read whose output is a graph IR may be cached. When
|
|
252
|
+
* off, every member is still stamped by the same rule.
|
|
253
|
+
*/
|
|
254
|
+
cache: boolean;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Plan the members a workspace read covers, run each under its own toolchain
|
|
259
|
+
* (ws-021) at the revision asked for, and return what they printed. One
|
|
260
|
+
* fan-out, shared by `chant workspace graph` and `chant workspace search`
|
|
261
|
+
* (#4374): `--at` exports the tree once, a member of a package's kind runs in
|
|
262
|
+
* its reader project, and every member is stamped by the rule of ws-059. The
|
|
263
|
+
* exported tree and the reader projects are removed before this returns.
|
|
264
|
+
* Throws a {@link WorkspaceReadError} when the declaration can't be read.
|
|
265
|
+
*/
|
|
266
|
+
export async function readMembers(query: GraphQuery, options: MemberReadOptions): Promise<MemberReads> {
|
|
222
267
|
let exported: string | undefined;
|
|
223
268
|
let readers: PreparedReaders | undefined;
|
|
224
|
-
if (query.args?.live && query.at !== undefined) {
|
|
225
|
-
return { doc: { ...head, error: { code: "live-at-revision", message: LIVE_AT_REVISION, location: null } }, failed: true };
|
|
226
|
-
}
|
|
227
269
|
try {
|
|
228
270
|
const located = locateWorkspace(query.cwd, query.at);
|
|
229
271
|
const declaration = readDeclaration(located.tree, "", { rootChant: true });
|
|
230
272
|
// Kinds are read before planning: a package kind with a graph block runs (#2874).
|
|
231
|
-
const kinds = loadKindRegistry(declaration.pins, located.rootOnDisk)
|
|
232
|
-
|
|
273
|
+
const { registry: kinds, problems } = loadKindRegistry(declaration.pins, located.rootOnDisk);
|
|
274
|
+
const kindProblems = problems.map((p) => p.message);
|
|
275
|
+
let plan = planMembers("graph", located.rootOnDisk, { only: query.members, reader: query.reader, tree: located.tree, kinds, kindProblems });
|
|
233
276
|
const args = (query.args ?? {}) as ParsedArgs;
|
|
234
277
|
// Members whose last source read still stands are answered from the cache (#2876).
|
|
235
278
|
// A composites read runs every member's component graph as well, so it reads everything.
|
|
236
|
-
const cache = query.noCache || query.components ? undefined : openGraphCache(located.rootOnDisk);
|
|
279
|
+
const cache = !options.cache || query.noCache || query.components ? undefined : openGraphCache(located.rootOnDisk);
|
|
237
280
|
const split = cache ? splitCached(plan, args, cache, located.at) : undefined;
|
|
281
|
+
const stamps = split?.stamps ?? (options.cache ? new Map<string, string>() : planStamps(plan, located.at));
|
|
238
282
|
const served = new Set(split?.hits.map((h) => h.id));
|
|
239
283
|
if (located.at !== null && withoutUnits(plan, served).groups.length > 0) {
|
|
240
284
|
exported = exportRevision(located, withoutUnits(plan, served).groups.flatMap((g) => g.units.map((u) => u.dir)));
|
|
241
|
-
plan = planMembers("graph", exported, { only: query.members, reader: query.reader, tree: workingTree(exported), kinds });
|
|
285
|
+
plan = planMembers("graph", exported, { only: query.members, reader: query.reader, tree: workingTree(exported), kinds, kindProblems });
|
|
242
286
|
}
|
|
243
287
|
// Only the members that run get a reader project; a served member needs none.
|
|
244
288
|
const toRun = withoutUnits(plan, served);
|
|
245
289
|
readers = prepareKindReaders(toRun, exported ?? located.rootOnDisk);
|
|
246
|
-
const [
|
|
247
|
-
executePlan(toRun, args),
|
|
290
|
+
const [first, components] = await Promise.all([
|
|
291
|
+
executePlan(toRun, args, options.argvFor),
|
|
248
292
|
query.components ? executePlan(plan, args, () => componentGraphArgv(args)) : Promise.resolve(undefined),
|
|
249
293
|
]);
|
|
294
|
+
const ran = args.capabilityView && !options.argvFor ? await withoutViewWhereRefused(toRun, args, first) : first;
|
|
250
295
|
if (cache && split) storeReads(split, ran, cache);
|
|
251
296
|
const results = [...(split?.hits ?? []), ...ran];
|
|
252
297
|
if (query.inTree) await query.inTree(exported ?? located.rootOnDisk, declaration.members.filter((m) => !query.members?.length || query.members.includes(m.name)));
|
|
253
298
|
for (const r of components ?? []) if (r.stderr.trim() && query.onStderr) query.onStderr(r.stderr.endsWith("\n") ? r.stderr : `${r.stderr}\n`);
|
|
254
299
|
for (const r of results) if (r.stderr.trim() && query.onStderr) query.onStderr(r.stderr.endsWith("\n") ? r.stderr : `${r.stderr}\n`);
|
|
255
|
-
|
|
300
|
+
return { located, declaration, kinds, plan, results, served, stamps, ...(components ? { components } : {}) };
|
|
301
|
+
} finally {
|
|
302
|
+
readers?.cleanup();
|
|
303
|
+
if (exported) rmSync(dirname(exported), { recursive: true, force: true });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* A member's chant from before #4378 refuses `--capability-view` as a flag
|
|
309
|
+
* it doesn't know. Read those members again without it, so the graph still
|
|
310
|
+
* composes them; they carry `capabilityView: null`, which a capability search
|
|
311
|
+
* reports as `member-chant-too-old`.
|
|
312
|
+
*/
|
|
313
|
+
async function withoutViewWhereRefused(plan: MemberPlan, args: ParsedArgs, results: UnitResult[]): Promise<UnitResult[]> {
|
|
314
|
+
const refused = new Set(results.filter((r) => r.exitCode !== 0 && refusedCapabilityView(r.stderr)).map((r) => r.id));
|
|
315
|
+
if (refused.size === 0) return results;
|
|
316
|
+
const others = new Set(results.filter((r) => !refused.has(r.id)).map((r) => r.id));
|
|
317
|
+
const again = await executePlan(withoutUnits(plan, others), { ...args, capabilityView: false });
|
|
318
|
+
const byId = new Map(again.map((r) => [r.id, r]));
|
|
319
|
+
return results.map((r) => byId.get(r.id) ?? r);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/** Read and compose the graph, and build the document. Never throws a {@link WorkspaceReadError}. */
|
|
323
|
+
export async function workspaceGraph(query: GraphQuery): Promise<GraphResult> {
|
|
324
|
+
const head: Head = { $schema: GRAPH_OUTPUT_SCHEMA_ID, contract: GRAPH_CONTRACT_VERSION, chant: readerVersion() };
|
|
325
|
+
if (query.args?.live && query.at !== undefined) {
|
|
326
|
+
return { doc: { ...head, error: { code: "live-at-revision", message: LIVE_AT_REVISION, location: null } }, failed: true };
|
|
327
|
+
}
|
|
328
|
+
try {
|
|
329
|
+
const { located, declaration, kinds, plan, results, served, stamps, components } = await readMembers(query, { cache: true });
|
|
330
|
+
const args = (query.args ?? {}) as ParsedArgs;
|
|
331
|
+
const { inputs, failed } = compose(plan, results, query.members, declaration.members, !!args.live, !!args.capabilityView);
|
|
256
332
|
for (const { member } of inputs) {
|
|
257
333
|
if (member.status !== "composed") continue;
|
|
258
334
|
member.cached = served.has(member.name);
|
|
259
|
-
member.stamp =
|
|
335
|
+
member.stamp = stamps.get(member.name) ?? null;
|
|
260
336
|
}
|
|
261
337
|
// Links (#2539) resolve against the declaration that was read, the revision's for --at, and the kinds installed now.
|
|
262
338
|
// A kind's link reader (#3932) reads the member's files in the tree read, as check does.
|
|
263
|
-
const graph = composeWorkspaceGraph({ name: declaration.name, root: located.root }, inputs, { declaration, kinds, read: readKindLinks(declaration, located.tree, kinds) });
|
|
339
|
+
const graph = composeWorkspaceGraph({ name: declaration.name, root: located.root, repo: repoIdentity(located.rootOnDisk) }, inputs, { declaration, kinds, read: readKindLinks(declaration, located.tree, kinds) });
|
|
264
340
|
// The box's factory and listing (#3146), from the declaration read, so --at gives them at that revision.
|
|
265
341
|
for (const member of graph.members) member.box = graphBox(declaration.members.find((m) => m.name === member.name)?.box ?? null, located.tree, declaration.members);
|
|
266
342
|
// Nested workspaces (#2551, ws-071): read-only, through their own chant workspace graph.
|
|
343
|
+
// Repo members (#3168): another repository's workspace at its pinned revision, read the same way.
|
|
267
344
|
const nestedFailed = await expandNested(graph, declaration.members, query, located.rootOnDisk, located.at);
|
|
268
345
|
let recordsFailed = false;
|
|
269
346
|
if (query.kind !== undefined) {
|
|
@@ -285,41 +362,51 @@ export async function workspaceGraph(query: GraphQuery): Promise<GraphResult> {
|
|
|
285
362
|
} catch (err) {
|
|
286
363
|
if (!(err instanceof WorkspaceReadError)) throw err;
|
|
287
364
|
return { doc: { ...head, error: { code: err.code, message: err.message, location: err.location ?? null } }, failed: true };
|
|
288
|
-
} finally {
|
|
289
|
-
readers?.cleanup();
|
|
290
|
-
if (exported) rmSync(dirname(exported), { recursive: true, force: true });
|
|
291
365
|
}
|
|
292
366
|
}
|
|
293
367
|
|
|
294
368
|
/**
|
|
295
369
|
* Expand every member of kind `workspace` the query covers, read-only (#2551,
|
|
296
|
-
* ws-071)
|
|
370
|
+
* ws-071), and every member of kind `repo` the same way, at its pinned
|
|
371
|
+
* revision, fetched into the user's cache (#3168). Returns whether one could
|
|
372
|
+
* not be read.
|
|
297
373
|
*/
|
|
298
374
|
async function expandNested(
|
|
299
375
|
graph: WorkspaceGraph,
|
|
300
|
-
members: readonly { name: string; dir: string; kind: string }[],
|
|
376
|
+
members: readonly { name: string; dir: string; kind: string; repo: RepoRef | null }[],
|
|
301
377
|
query: GraphQuery,
|
|
302
378
|
rootOnDisk: string,
|
|
303
379
|
at: string | null,
|
|
304
380
|
): Promise<boolean> {
|
|
305
|
-
const
|
|
381
|
+
const covered = (m: { name: string }) => !query.members?.length || query.members.includes(m.name);
|
|
382
|
+
const nested = members.filter((m) => (m.kind === "workspace" || (m.kind === REPO_KIND && m.repo !== null)) && covered(m));
|
|
306
383
|
if (nested.length === 0) return false;
|
|
307
384
|
const { foldNested, readNested } = await import("./nested-graph");
|
|
385
|
+
const { fetchRepoAt } = await import("./repo-ref");
|
|
308
386
|
const reads = await Promise.all(
|
|
309
387
|
nested.map(async (m) => {
|
|
388
|
+
if (m.repo) {
|
|
389
|
+
// The other repository at its pinned revision, whatever revision the outer read is at.
|
|
390
|
+
const fetched = fetchRepoAt(m.repo, rootOnDisk);
|
|
391
|
+
if (!fetched.ok) return { m, read: null, missing: fetched.message };
|
|
392
|
+
if (!existsSync(fetched.dir)) return { m, read: null, missing: `${m.repo.url} at ${m.repo.rev} has no directory ${m.repo.workspace}` };
|
|
393
|
+
return { m, read: await readNested(fetched.dir, query.args ?? {}, m.repo.rev, GRAPH_OUTPUT_SCHEMA_ID, GRAPH_CONTRACT_VERSION, query.reader), missing: null };
|
|
394
|
+
}
|
|
310
395
|
const abs = join(rootOnDisk, ...m.dir.split("/"));
|
|
311
|
-
if (!existsSync(abs)) return { m, read: null };
|
|
312
|
-
return { m, read: await readNested(abs, query.args ?? {}, at, GRAPH_OUTPUT_SCHEMA_ID, GRAPH_CONTRACT_VERSION, query.reader) };
|
|
396
|
+
if (!existsSync(abs)) return { m, read: null, missing: null };
|
|
397
|
+
return { m, read: await readNested(abs, query.args ?? {}, at, GRAPH_OUTPUT_SCHEMA_ID, GRAPH_CONTRACT_VERSION, query.reader), missing: null };
|
|
313
398
|
}),
|
|
314
399
|
);
|
|
315
400
|
let failed = false;
|
|
316
|
-
for (const { m, read } of reads) {
|
|
401
|
+
for (const { m, read, missing } of reads) {
|
|
317
402
|
const member = graph.members.find((x) => x.name === m.name);
|
|
318
403
|
if (!member) continue;
|
|
404
|
+
if (m.repo) member.repo = { ...m.repo, read: read?.ok ? (read.doc.workspace.repo ?? null) : null };
|
|
319
405
|
if (!read) {
|
|
320
406
|
failed = true;
|
|
321
407
|
member.status = "failed";
|
|
322
|
-
|
|
408
|
+
// A repo that can't be fetched is a read that failed; the contract's codes stay as they are.
|
|
409
|
+
member.reason = missing !== null ? { code: "command-failed", message: missing } : { code: "dir-missing", message: `the nested workspace's directory ${m.dir} does not exist` };
|
|
323
410
|
continue;
|
|
324
411
|
}
|
|
325
412
|
if (read.stderr.trim() && query.onStderr) query.onStderr(read.stderr.endsWith("\n") ? read.stderr : `${read.stderr}\n`);
|
|
@@ -230,7 +230,9 @@ describe("chant workspace graph on the chant repo (#2557)", () => {
|
|
|
230
230
|
const g = result(doc);
|
|
231
231
|
expectValid(g);
|
|
232
232
|
expect(failed).toBe(false);
|
|
233
|
-
expect(g.workspace).
|
|
233
|
+
expect(g.workspace).toMatchObject({ name: "chant", root: "." });
|
|
234
|
+
// The repo identity (#3168) is this checkout's origin, whatever it is here.
|
|
235
|
+
expect(g.workspace.repo === null || typeof g.workspace.repo === "string").toBe(true);
|
|
234
236
|
expect(g.at).toBeNull();
|
|
235
237
|
expect(g.members.every((m) => m.status === "skipped" && m.reason?.code === "kind-not-run")).toBe(true);
|
|
236
238
|
});
|
|
@@ -294,7 +296,7 @@ describe("chant workspace graph on built workspaces", () => {
|
|
|
294
296
|
for (const at of [undefined, sha]) {
|
|
295
297
|
const g = result((await workspaceGraph({ cwd: join(top, "infra", "api"), at })).doc);
|
|
296
298
|
expectValid(g);
|
|
297
|
-
expect(g.workspace).toEqual({ name: "acme", root: "infra" });
|
|
299
|
+
expect(g.workspace).toEqual({ name: "acme", root: "infra", repo: null });
|
|
298
300
|
expect(g.nodes.map((n) => n.id)).toEqual(["api/Queue"]);
|
|
299
301
|
}
|
|
300
302
|
});
|