@gfdelarue/testkit 0.4.5 → 0.5.0
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/README.md +666 -463
- package/bin/testkit-windows-owner-arm64.exe +0 -0
- package/bin/testkit-windows-owner-x64.exe +0 -0
- package/dist/app/bugs/ci-report.js +2 -2
- package/dist/app/bugs/ci-summary.js +3 -3
- package/dist/app/bugs/draft.js +3 -3
- package/dist/app/bugs/file.js +1 -1
- package/dist/app/bugs/gate.js +1 -1
- package/dist/app/bugs/guide.js +3 -3
- package/dist/app/bugs/issue.js +4 -4
- package/dist/app/bugs/known-failures.js +1 -1
- package/dist/app/bugs/record.js +2 -2
- package/dist/app/bugs/run-reading.js +1 -1
- package/dist/app/bugs/supplied-reproduce.js +1 -0
- package/dist/app/campaigns/campaign.js +1 -1
- package/dist/app/cleanup/index.js +1 -1
- package/dist/app/db-schema/prepare.js +1 -1
- package/dist/app/destroy/index.js +1 -1
- package/dist/app/discover/index.js +2 -2
- package/dist/app/doctor/index.js +1 -1
- package/dist/app/environments/config-driven.js +1 -1
- package/dist/app/environments/environment-file.js +1 -0
- package/dist/app/environments/file-setup.js +1 -0
- package/dist/app/environments/routing.js +1 -1
- package/dist/app/environments/static-values.js +1 -0
- package/dist/app/environments/supplied-input.js +1 -0
- package/dist/app/environments/supplied.js +1 -1
- package/dist/app/environments/task-databases.js +2 -0
- package/dist/app/inspect/artifacts.js +1 -1
- package/dist/app/inspect/index.js +1 -1
- package/dist/app/lint/index.js +1 -1
- package/dist/app/lint/native.js +1 -1
- package/dist/app/lint/options.js +1 -1
- package/dist/app/lint/rules/data.js +1 -1
- package/dist/app/lint/rules/engine-imports.js +1 -1
- package/dist/app/lint/rules/syntax.js +1 -1
- package/dist/app/lint/rules/unit.js +1 -1
- package/dist/app/reports/prepare.js +1 -1
- package/dist/app/run/caller-redaction.js +1 -0
- package/dist/app/run/engine-execution-failures.js +1 -1
- package/dist/app/run/engine-execution-reporting.js +1 -1
- package/dist/app/run/engine-execution.js +1 -1
- package/dist/app/run/engine-orchestration.js +1 -1
- package/dist/app/run/environment.js +1 -1
- package/dist/app/run/failure-details.js +1 -1
- package/dist/app/run/live-run.js +1 -1
- package/dist/app/run/orchestrator.js +1 -1
- package/dist/app/run/planning.js +1 -1
- package/dist/app/run/request.js +1 -1
- package/dist/app/run/results.js +1 -1
- package/dist/app/run/run-events.js +1 -1
- package/dist/app/run/run-finalization.js +1 -1
- package/dist/app/run/scheduler/estimates.js +1 -1
- package/dist/app/run/scheduler/identity.js +1 -1
- package/dist/app/run/scheduler/index.js +1 -1
- package/dist/app/run/setup/runtime-node-setup-protocol.js +1 -1
- package/dist/app/run/setup/runtime-node-setup-worker.js +1 -1
- package/dist/app/run/setup/runtime-node-setup.js +2 -2
- package/dist/app/run/task-batches.js +1 -1
- package/dist/app/run/worker-loop.js +1 -1
- package/dist/app/status/runs.js +1 -1
- package/dist/app/typecheck/index.js +4 -4
- package/dist/cli/command-catalog.js +1 -1
- package/dist/cli/command-flags.js +1 -1
- package/dist/cli/commands/artifacts.js +2 -2
- package/dist/cli/commands/bug/file.js +2 -2
- package/dist/cli/commands/bug/record.js +2 -2
- package/dist/cli/commands/discover.js +1 -1
- package/dist/cli/commands/run.js +2 -2
- package/dist/cli/commands/typecheck.js +1 -1
- package/dist/cli/commands/workspace.js +1 -1
- package/dist/cli/framework/errors.js +1 -1
- package/dist/cli/framework/execute.js +7 -6
- package/dist/cli/framework/parser.js +1 -1
- package/dist/cli/operations/run/operation.js +2 -2
- package/dist/cli/renderers/bug/text.js +1 -1
- package/dist/cli/renderers/discover/report.js +1 -1
- package/dist/cli/renderers/run/events.js +2 -2
- package/dist/cli/renderers/run/formatting.js +1 -1
- package/dist/cli/renderers/run/status.js +1 -1
- package/dist/cli/renderers/run/text-reporter.js +24 -22
- package/dist/cli/terminal/colors.js +1 -1
- package/dist/cli/terminal/layout.js +2 -2
- package/dist/config/authoring/http-methods.js +1 -1
- package/dist/config/loader/config-loader.js +1 -1
- package/dist/config/loader/decode-execution.js +1 -1
- package/dist/config/loader/dependencies.js +1 -1
- package/dist/config/loader/discover-tests.js +1 -1
- package/dist/config/loader/discovery-summary.js +1 -1
- package/dist/config/loader/discovery.js +2 -2
- package/dist/config/loader/env.js +1 -1
- package/dist/config/loader/file-metadata.js +1 -1
- package/dist/config/loader/groups.js +1 -1
- package/dist/config/loader/index.js +1 -1
- package/dist/config/loader/load.js +1 -1
- package/dist/config/loader/managed-configs.js +1 -1
- package/dist/config/loader/owned-discovery.js +1 -0
- package/dist/config/loader/path-policy.js +1 -1
- package/dist/config/loader/runtime-isolation.js +1 -1
- package/dist/config/loader/runtime.js +1 -1
- package/dist/config/loader/skip-config.js +1 -1
- package/dist/config/loader/task-policy.js +1 -0
- package/dist/config/loader/test-selection.js +1 -1
- package/dist/config/loader/validation.js +1 -1
- package/dist/database/admin.js +2 -2
- package/dist/database/bindings.js +1 -0
- package/dist/database/cleanup.js +1 -1
- package/dist/database/docker-metadata.js +3 -3
- package/dist/database/docker.js +3 -3
- package/dist/database/index.js +1 -1
- package/dist/database/local-postgres.js +1 -1
- package/dist/database/naming.js +1 -1
- package/dist/database/postgres/connection-check.js +1 -0
- package/dist/database/postgres/protocol.js +2 -0
- package/dist/database/schema-operations.js +1 -1
- package/dist/database/schema-source.js +3 -3
- package/dist/database/source-schema-env.js +1 -0
- package/dist/database/state-files.js +1 -1
- package/dist/database/state.js +1 -1
- package/dist/database/steps.js +3 -3
- package/dist/domain/file-timeout.js +1 -1
- package/dist/domain/identifiers.js +1 -1
- package/dist/domain/retired-test-types.js +1 -0
- package/dist/domain/runtime-isolation-contract.js +1 -1
- package/dist/domain/suite-selection.js +1 -1
- package/dist/domain/test-types.js +1 -1
- package/dist/engines/adapters/evidence-files.js +1 -1
- package/dist/engines/adapters/execution.js +1 -1
- package/dist/engines/adapters/json-bounds.js +2 -0
- package/dist/engines/adapters/native-report.js +1 -1
- package/dist/engines/api/execution.js +1 -1
- package/dist/engines/api/index.js +1 -1
- package/dist/engines/api/runtime-artifact.js +1 -1
- package/dist/engines/catalog.js +1 -1
- package/dist/engines/contracts/environment-values.js +1 -0
- package/dist/engines/definitions.js +1 -1
- package/dist/engines/environment/handles.js +1 -0
- package/dist/engines/environment/index.js +1 -0
- package/dist/engines/factory.js +1 -1
- package/dist/engines/installations/node-vitest.js +1 -1
- package/dist/engines/installations/package-resolution.js +1 -1
- package/dist/engines/installations/playwright.js +1 -1
- package/dist/engines/managed-module-resolution.js +2 -2
- package/dist/engines/manager.js +1 -1
- package/dist/engines/node-vitest/adapter/adapter.js +1 -1
- package/dist/engines/node-vitest/adapter/driver.js +2 -0
- package/dist/engines/node-vitest/adapter/evidence.js +2 -2
- package/dist/engines/node-vitest/adapter/failure-details.js +4 -2
- package/dist/engines/node-vitest/adapter/reporter.js +1 -1
- package/dist/engines/node-vitest/adapter/workspace.js +26 -188
- package/dist/engines/node-vitest/inventory/index.js +2 -0
- package/dist/engines/node-vitest/inventory/list-files.js +3 -0
- package/dist/engines/node-vitest/runtime/contract/index.js +1 -1
- package/dist/engines/node-vitest/runtime/data/http.js +1 -1
- package/dist/engines/node-vitest/runtime/data/index.js +1 -1
- package/dist/engines/node-vitest/runtime/data/report.js +5 -6
- package/dist/engines/node-vitest/runtime/data/scenario.js +2 -2
- package/dist/engines/node-vitest/runtime/runtime-input.js +1 -1
- package/dist/engines/node-vitest/selection.js +1 -0
- package/dist/engines/playwright/adapter/adapter.js +1 -1
- package/dist/engines/playwright/adapter/config.js +3 -3
- package/dist/engines/playwright/adapter/evidence-validation.js +1 -1
- package/dist/engines/playwright/adapter/evidence.js +1 -1
- package/dist/engines/playwright/adapter/reporter.js +1 -1
- package/dist/engines/playwright/runtime/config-file.js +1 -1
- package/dist/engines/playwright/runtime/config.js +1 -1
- package/dist/engines/playwright/runtime/runtime-input.js +29 -10
- package/dist/engines/runtime-input-file.js +1 -1
- package/dist/environment/lifecycle-controller.js +1 -1
- package/dist/environment/lifecycle.js +1 -1
- package/dist/environment/ready-environment.js +1 -1
- package/dist/environment/run-stopping.js +1 -1
- package/dist/environment/runtime-contexts.js +1 -1
- package/dist/environment/runtime-manager.js +1 -1
- package/dist/environment/runtime-planning.js +1 -1
- package/dist/environment/runtime-preparation.js +1 -1
- package/dist/environment/services.js +3 -3
- package/dist/environment/template.js +1 -1
- package/dist/evidence/artifact-config.js +1 -1
- package/dist/evidence/artifacts.js +2 -2
- package/dist/evidence/bundles.js +1 -1
- package/dist/evidence/environment-record.js +1 -1
- package/dist/evidence/index.js +1 -1
- package/dist/evidence/read-run.js +1 -1
- package/dist/evidence/reading.js +1 -1
- package/dist/evidence/redaction.js +4 -0
- package/dist/evidence/reporting.js +1 -1
- package/dist/evidence/run-model.js +1 -0
- package/dist/evidence/storage.js +2 -2
- package/dist/evidence/timing.js +1 -1
- package/dist/kernel/error-serialization.js +1 -1
- package/dist/kernel/redaction-targets.js +1 -0
- package/dist/kernel/redaction.js +4 -1
- package/dist/kernel/unknown-values.js +1 -1
- package/dist/process/environment.js +1 -1
- package/dist/process/execa-bundle.json +3 -3
- package/dist/process/files/json-file.js +1 -1
- package/dist/process/host/platform.js +1 -1
- package/dist/process/host-process.js +1 -1
- package/dist/process/index.js +1 -1
- package/dist/process/locks.js +4 -4
- package/dist/process/port-listener.js +2 -0
- package/dist/process/process-group.js +1 -1
- package/dist/process/process.js +32 -32
- package/dist/process/readiness.js +1 -1
- package/dist/process/ready-deadline.js +1 -0
- package/dist/process/runs/ownership.js +1 -1
- package/dist/process/runs/stop.js +1 -1
- package/dist/process/service-processes.js +1 -1
- package/dist/process/windows-cli-owner.js +3 -3
- package/dist/process/windows-native.js +1 -1
- package/dist/repo/fingerprint-policy.js +1 -1
- package/dist/repo/managed-git.js +1 -1
- package/dist/repo/physical-tree.js +1 -1
- package/dist/repo/state.js +4 -4
- package/dist/steps/build-config.js +1 -1
- package/dist/steps/configured-step-testkit-modules.js +1 -1
- package/dist/steps/configured-steps.js +1 -1
- package/dist/steps/environment.js +1 -1
- package/dist/steps/index.js +1 -1
- package/dist/toolchains/index.js +3 -3
- package/dist/toolchains/semver.js +1 -1
- package/dist/toolchains/vitest/index.js +1 -1
- package/dist/tracker/redaction.js +1 -2
- package/dist/{config/runtime/build-assets.d.ts → types/config-build-assets.d.ts} +5 -3
- package/dist/{database/steps.d.ts → types/config-database-steps.d.ts} +7 -7
- package/dist/{config/runtime/next-runtime-tsconfig.d.ts → types/config-next-runtime-tsconfig.d.ts} +5 -3
- package/dist/types/config.d.ts +501 -0
- package/dist/types/drizzle.d.ts +13 -0
- package/dist/{config/runtime/env/index.d.ts → types/env.d.ts} +22 -20
- package/dist/types/environment.d.ts +40 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/node-vitest-contract.d.ts +75 -0
- package/dist/types/node-vitest-data.d.ts +407 -0
- package/dist/types/playwright.d.ts +130 -0
- package/dist/types/tooling-vitest.d.ts +13 -0
- package/dist/types/workspace.d.ts +617 -0
- package/docs/bug-records.md +37 -37
- package/docs/engines.md +213 -0
- package/docs/test-types.md +35 -33
- package/package.json +22 -29
- package/testkit-config-schema.md +378 -184
- package/dist/app/bugs/areas.d.ts +0 -38
- package/dist/app/bugs/assessment.d.ts +0 -9
- package/dist/app/bugs/categories.d.ts +0 -41
- package/dist/app/bugs/ci-report.d.ts +0 -21
- package/dist/app/bugs/ci-summary.d.ts +0 -13
- package/dist/app/bugs/draft.d.ts +0 -70
- package/dist/app/bugs/facts.d.ts +0 -49
- package/dist/app/bugs/file.d.ts +0 -45
- package/dist/app/bugs/gate.d.ts +0 -22
- package/dist/app/bugs/guide.d.ts +0 -20
- package/dist/app/bugs/issue.d.ts +0 -18
- package/dist/app/bugs/known-failures.d.ts +0 -49
- package/dist/app/bugs/record.d.ts +0 -14
- package/dist/app/bugs/run-reading.d.ts +0 -51
- package/dist/app/bugs/store.d.ts +0 -34
- package/dist/app/campaigns/brief.d.ts +0 -7
- package/dist/app/campaigns/campaign.d.ts +0 -14
- package/dist/app/campaigns/index.d.ts +0 -38
- package/dist/app/campaigns/store.d.ts +0 -5
- package/dist/app/campaigns/summary.d.ts +0 -13
- package/dist/app/cleanup/index.d.ts +0 -52
- package/dist/app/db-schema/prepare.d.ts +0 -11
- package/dist/app/db-schema/refresh.d.ts +0 -17
- package/dist/app/db-schema/verify.d.ts +0 -11
- package/dist/app/destroy/index.d.ts +0 -16
- package/dist/app/discover/index.d.ts +0 -8
- package/dist/app/doctor/index.d.ts +0 -17
- package/dist/app/environments/config-driven.d.ts +0 -5
- package/dist/app/environments/routing.d.ts +0 -6
- package/dist/app/environments/supplied.d.ts +0 -3
- package/dist/app/file-selection.d.ts +0 -1
- package/dist/app/inspect/artifacts.d.ts +0 -30
- package/dist/app/inspect/index.d.ts +0 -112
- package/dist/app/lint/index.d.ts +0 -28
- package/dist/app/lint/native.d.ts +0 -10
- package/dist/app/lint/options.d.ts +0 -66
- package/dist/app/lint/policy.d.ts +0 -21
- package/dist/app/lint/rules/data.d.ts +0 -3
- package/dist/app/lint/rules/engine-imports.d.ts +0 -3
- package/dist/app/lint/rules/syntax.d.ts +0 -4
- package/dist/app/lint/rules/unit.d.ts +0 -3
- package/dist/app/lint/shared.d.ts +0 -34
- package/dist/app/package-inspection.d.ts +0 -20
- package/dist/app/reports/files.d.ts +0 -13
- package/dist/app/reports/prepare.d.ts +0 -20
- package/dist/app/reports/publish.d.ts +0 -21
- package/dist/app/run/endpoint-readiness.d.ts +0 -43
- package/dist/app/run/endpoint-readiness.js +0 -1
- package/dist/app/run/engine-evidence-persistence.d.ts +0 -39
- package/dist/app/run/engine-execution-cleanup.d.ts +0 -8
- package/dist/app/run/engine-execution-cleanup.js +0 -1
- package/dist/app/run/engine-execution-failures.d.ts +0 -41
- package/dist/app/run/engine-execution-observer.d.ts +0 -21
- package/dist/app/run/engine-execution-reporting.d.ts +0 -17
- package/dist/app/run/engine-execution.d.ts +0 -65
- package/dist/app/run/engine-failure-stack.d.ts +0 -1
- package/dist/app/run/engine-orchestration.d.ts +0 -30
- package/dist/app/run/environment.d.ts +0 -33
- package/dist/app/run/failure-details.d.ts +0 -37
- package/dist/app/run/live-run.d.ts +0 -29
- package/dist/app/run/operation-progress.d.ts +0 -13
- package/dist/app/run/orchestrator.d.ts +0 -75
- package/dist/app/run/planning-types.d.ts +0 -68
- package/dist/app/run/planning.d.ts +0 -14
- package/dist/app/run/request.d.ts +0 -30
- package/dist/app/run/results.d.ts +0 -161
- package/dist/app/run/run-events.d.ts +0 -144
- package/dist/app/run/run-finalization.d.ts +0 -56
- package/dist/app/run/run-guards.d.ts +0 -3
- package/dist/app/run/runtime-failures.d.ts +0 -18
- package/dist/app/run/runtime-fixtures.d.ts +0 -2
- package/dist/app/run/runtime-task-types.d.ts +0 -20
- package/dist/app/run/scheduler/estimates.d.ts +0 -32
- package/dist/app/run/scheduler/identity.d.ts +0 -9
- package/dist/app/run/scheduler/index.d.ts +0 -124
- package/dist/app/run/scheduler/locks.d.ts +0 -6
- package/dist/app/run/scheduler/observations.d.ts +0 -20
- package/dist/app/run/selection.d.ts +0 -9
- package/dist/app/run/setup/runtime-node-setup-errors.d.ts +0 -13
- package/dist/app/run/setup/runtime-node-setup-protocol.d.ts +0 -85
- package/dist/app/run/setup/runtime-node-setup-worker.d.ts +0 -1
- package/dist/app/run/setup/runtime-node-setup.d.ts +0 -48
- package/dist/app/run/task-batches.d.ts +0 -23
- package/dist/app/run/task-leases.d.ts +0 -15
- package/dist/app/run/worker-loop.d.ts +0 -66
- package/dist/app/setup/playwright.d.ts +0 -22
- package/dist/app/status/index.d.ts +0 -9
- package/dist/app/status/model.d.ts +0 -29
- package/dist/app/status/runs.d.ts +0 -99
- package/dist/app/stop/index.d.ts +0 -14
- package/dist/app/tracker/index.d.ts +0 -13
- package/dist/app/tracker/remote.d.ts +0 -13
- package/dist/app/tracker/token.d.ts +0 -7
- package/dist/app/typecheck/index.d.ts +0 -63
- package/dist/cli/command-catalog.d.ts +0 -156
- package/dist/cli/command-flags.d.ts +0 -19
- package/dist/cli/command-registry.d.ts +0 -3
- package/dist/cli/commands/artifacts.d.ts +0 -48
- package/dist/cli/commands/bug/file.d.ts +0 -16
- package/dist/cli/commands/bug/guide.d.ts +0 -5
- package/dist/cli/commands/bug/record.d.ts +0 -9
- package/dist/cli/commands/campaign/finish.d.ts +0 -10
- package/dist/cli/commands/campaign/start.d.ts +0 -7
- package/dist/cli/commands/campaign/status.d.ts +0 -13
- package/dist/cli/commands/ci/report.d.ts +0 -15
- package/dist/cli/commands/cleanup.d.ts +0 -13
- package/dist/cli/commands/db/schema/refresh.d.ts +0 -2
- package/dist/cli/commands/db/schema/verify.d.ts +0 -2
- package/dist/cli/commands/destroy.d.ts +0 -9
- package/dist/cli/commands/discover.d.ts +0 -2
- package/dist/cli/commands/doctor.d.ts +0 -2
- package/dist/cli/commands/guard/unsafe-entrypoint.d.ts +0 -2
- package/dist/cli/commands/lint.d.ts +0 -2
- package/dist/cli/commands/report/prepare.d.ts +0 -12
- package/dist/cli/commands/report/publish.d.ts +0 -13
- package/dist/cli/commands/run/status.d.ts +0 -5
- package/dist/cli/commands/run/stop.d.ts +0 -7
- package/dist/cli/commands/run.d.ts +0 -9
- package/dist/cli/commands/setup/playwright.d.ts +0 -2
- package/dist/cli/commands/status.d.ts +0 -5
- package/dist/cli/commands/stop.d.ts +0 -12
- package/dist/cli/commands/typecheck.d.ts +0 -2
- package/dist/cli/commands/workspace.d.ts +0 -2
- package/dist/cli/entrypoint.d.ts +0 -1
- package/dist/cli/framework/command.d.ts +0 -21
- package/dist/cli/framework/definitions.d.ts +0 -100
- package/dist/cli/framework/errors.d.ts +0 -6
- package/dist/cli/framework/execute.d.ts +0 -14
- package/dist/cli/framework/help.d.ts +0 -11
- package/dist/cli/framework/index.d.ts +0 -3
- package/dist/cli/framework/parser.d.ts +0 -6
- package/dist/cli/index.d.ts +0 -4
- package/dist/cli/json-errors.d.ts +0 -3
- package/dist/cli/operations/db/schema/refresh/operation.d.ts +0 -7
- package/dist/cli/operations/db/schema/verify/operation.d.ts +0 -7
- package/dist/cli/operations/run/operation.d.ts +0 -26
- package/dist/cli/process-signal.d.ts +0 -1
- package/dist/cli/renderers/bug/text.d.ts +0 -8
- package/dist/cli/renderers/campaign/text.d.ts +0 -2
- package/dist/cli/renderers/ci/text.d.ts +0 -2
- package/dist/cli/renderers/cleanup/format.d.ts +0 -14
- package/dist/cli/renderers/db-schema/text.d.ts +0 -4
- package/dist/cli/renderers/destroy/text.d.ts +0 -4
- package/dist/cli/renderers/discover/report.d.ts +0 -7
- package/dist/cli/renderers/discover/text.d.ts +0 -3
- package/dist/cli/renderers/doctor/text.d.ts +0 -2
- package/dist/cli/renderers/lint/text.d.ts +0 -2
- package/dist/cli/renderers/run/events.d.ts +0 -8
- package/dist/cli/renderers/run/failure.d.ts +0 -8
- package/dist/cli/renderers/run/formatting.d.ts +0 -79
- package/dist/cli/renderers/run/status.d.ts +0 -6
- package/dist/cli/renderers/run/text-reporter.d.ts +0 -19
- package/dist/cli/renderers/status/text.d.ts +0 -2
- package/dist/cli/renderers/stop/text.d.ts +0 -7
- package/dist/cli/renderers/typecheck/text.d.ts +0 -2
- package/dist/cli/terminal/colors.d.ts +0 -10
- package/dist/cli/terminal/layout.d.ts +0 -11
- package/dist/cli/version-drift.d.ts +0 -25
- package/dist/config/authoring/build-config-contract.d.ts +0 -27
- package/dist/config/authoring/configured-step-contract.d.ts +0 -18
- package/dist/config/authoring/http-execution-contract.d.ts +0 -70
- package/dist/config/authoring/http-methods.d.ts +0 -18
- package/dist/config/authoring/index.d.ts +0 -372
- package/dist/config/authoring/preset-env.d.ts +0 -19
- package/dist/config/authoring/runtime.d.ts +0 -64
- package/dist/config/loader/bugs.d.ts +0 -15
- package/dist/config/loader/config-loader.d.ts +0 -9
- package/dist/config/loader/database-materialization.d.ts +0 -19
- package/dist/config/loader/database-roles.d.ts +0 -2
- package/dist/config/loader/database.d.ts +0 -55
- package/dist/config/loader/decode-discovery.d.ts +0 -5
- package/dist/config/loader/decode-execution.d.ts +0 -7
- package/dist/config/loader/dependencies.d.ts +0 -7
- package/dist/config/loader/discover-tests.d.ts +0 -111
- package/dist/config/loader/discovery-summary.d.ts +0 -29
- package/dist/config/loader/discovery.d.ts +0 -53
- package/dist/config/loader/env.d.ts +0 -4
- package/dist/config/loader/execution-model.d.ts +0 -15
- package/dist/config/loader/file-metadata.d.ts +0 -19
- package/dist/config/loader/groups.d.ts +0 -33
- package/dist/config/loader/index.d.ts +0 -10
- package/dist/config/loader/load.d.ts +0 -89
- package/dist/config/loader/managed-configs.d.ts +0 -23
- package/dist/config/loader/path-policy.d.ts +0 -9
- package/dist/config/loader/paths.d.ts +0 -5
- package/dist/config/loader/runtime-isolation.d.ts +0 -44
- package/dist/config/loader/runtime.d.ts +0 -16
- package/dist/config/loader/skip-config.d.ts +0 -44
- package/dist/config/loader/test-selection.d.ts +0 -15
- package/dist/config/loader/validation.d.ts +0 -15
- package/dist/config/loader/values.d.ts +0 -3
- package/dist/config/loader/values.js +0 -1
- package/dist/database/activity-gate.d.ts +0 -22
- package/dist/database/admin.d.ts +0 -31
- package/dist/database/cleanup.d.ts +0 -36
- package/dist/database/configured-steps.d.ts +0 -27
- package/dist/database/constants.d.ts +0 -11
- package/dist/database/docker-metadata.d.ts +0 -3
- package/dist/database/docker.d.ts +0 -65
- package/dist/database/drizzle/index.d.ts +0 -13
- package/dist/database/fingerprint.d.ts +0 -12
- package/dist/database/index.d.ts +0 -39
- package/dist/database/lifecycle-cleanup.d.ts +0 -8
- package/dist/database/local-postgres.d.ts +0 -71
- package/dist/database/naming.d.ts +0 -17
- package/dist/database/postgres/index.d.ts +0 -71
- package/dist/database/progress.d.ts +0 -6
- package/dist/database/roles.d.ts +0 -19
- package/dist/database/runtime-config.d.ts +0 -16
- package/dist/database/runtime-reservations.d.ts +0 -19
- package/dist/database/schema-operations.d.ts +0 -18
- package/dist/database/schema-source.d.ts +0 -96
- package/dist/database/source-refresh-lock.d.ts +0 -8
- package/dist/database/source-url.d.ts +0 -21
- package/dist/database/state-files.d.ts +0 -13
- package/dist/database/state.d.ts +0 -26
- package/dist/database/template-steps.d.ts +0 -39
- package/dist/domain/file-timeout.d.ts +0 -25
- package/dist/domain/identifiers.d.ts +0 -9
- package/dist/domain/operation-display.d.ts +0 -10
- package/dist/domain/operation-reason.d.ts +0 -5
- package/dist/domain/postgres-route.d.ts +0 -4
- package/dist/domain/runtime-identity.d.ts +0 -1
- package/dist/domain/runtime-isolation-contract.d.ts +0 -5
- package/dist/domain/service-name.d.ts +0 -2
- package/dist/domain/suite-selection.d.ts +0 -20
- package/dist/domain/test-outcomes.d.ts +0 -2
- package/dist/domain/test-types.d.ts +0 -16
- package/dist/engines/adapters/evidence-files.d.ts +0 -32
- package/dist/engines/adapters/evidence-identity.d.ts +0 -12
- package/dist/engines/adapters/execution.d.ts +0 -41
- package/dist/engines/adapters/native-report.d.ts +0 -25
- package/dist/engines/adapters/node-startup-cache.d.ts +0 -8
- package/dist/engines/adapters/workspace.d.ts +0 -4
- package/dist/engines/api/capabilities.d.ts +0 -21
- package/dist/engines/api/capabilities.js +0 -1
- package/dist/engines/api/evidence.d.ts +0 -38
- package/dist/engines/api/execution-observer.d.ts +0 -8
- package/dist/engines/api/execution-scope.d.ts +0 -17
- package/dist/engines/api/execution.d.ts +0 -101
- package/dist/engines/api/index.d.ts +0 -5
- package/dist/engines/api/k6-runtime-input.d.ts +0 -26
- package/dist/engines/api/k6-runtime-input.js +0 -1
- package/dist/engines/api/runtime-artifact.d.ts +0 -19
- package/dist/engines/bundle-cache.d.ts +0 -32
- package/dist/engines/catalog.d.ts +0 -27
- package/dist/engines/contracts/fixture-manifest.d.ts +0 -34
- package/dist/engines/contracts/json-bounds.d.ts +0 -36
- package/dist/engines/contracts/json-bounds.js +0 -2
- package/dist/engines/contracts/k6-repository-configuration.d.ts +0 -12
- package/dist/engines/contracts/k6-repository-configuration.js +0 -1
- package/dist/engines/contracts/test-context.d.ts +0 -15
- package/dist/engines/contracts/test-context.js +0 -1
- package/dist/engines/definitions.d.ts +0 -23
- package/dist/engines/factory.d.ts +0 -6
- package/dist/engines/generated-performance.d.ts +0 -1
- package/dist/engines/installation-catalog.d.ts +0 -27
- package/dist/engines/installation-catalog.js +0 -1
- package/dist/engines/installations/k6.d.ts +0 -98
- package/dist/engines/installations/k6.js +0 -1
- package/dist/engines/installations/node-vitest.d.ts +0 -33
- package/dist/engines/installations/package-requirements.d.ts +0 -28
- package/dist/engines/installations/package-resolution.d.ts +0 -51
- package/dist/engines/installations/playwright-resolution-child.d.ts +0 -1
- package/dist/engines/installations/playwright.d.ts +0 -75
- package/dist/engines/installations/types.d.ts +0 -10
- package/dist/engines/k6/adapter/bundle.d.ts +0 -25
- package/dist/engines/k6/adapter/bundle.js +0 -112
- package/dist/engines/k6/adapter/evidence.d.ts +0 -15
- package/dist/engines/k6/adapter/evidence.js +0 -4
- package/dist/engines/k6/adapter/executor.d.ts +0 -13
- package/dist/engines/k6/adapter/executor.js +0 -1
- package/dist/engines/k6/adapter/index.d.ts +0 -1
- package/dist/engines/k6/adapter/index.js +0 -1
- package/dist/engines/k6/adapter/input.d.ts +0 -21
- package/dist/engines/k6/adapter/input.js +0 -1
- package/dist/engines/k6/adapter/native-summary.d.ts +0 -11
- package/dist/engines/k6/adapter/native-summary.js +0 -1
- package/dist/engines/k6/adapter/repository-configuration.d.ts +0 -2
- package/dist/engines/k6/adapter/repository-configuration.js +0 -1
- package/dist/engines/k6/authoring-type-paths.d.ts +0 -3
- package/dist/engines/k6/authoring-type-paths.js +0 -1
- package/dist/engines/k6/runtime/ambient-types/bundle-manifest.json +0 -146
- package/dist/engines/k6/runtime/ambient-types/k6/LICENSE +0 -21
- package/dist/engines/k6/runtime/ambient-types/k6/browser/index.d.ts +0 -6332
- package/dist/engines/k6/runtime/ambient-types/k6/crypto/index.d.ts +0 -218
- package/dist/engines/k6/runtime/ambient-types/k6/data/index.d.ts +0 -16
- package/dist/engines/k6/runtime/ambient-types/k6/encoding/index.d.ts +0 -46
- package/dist/engines/k6/runtime/ambient-types/k6/execution/index.d.ts +0 -127
- package/dist/engines/k6/runtime/ambient-types/k6/experimental/csv/index.d.ts +0 -96
- package/dist/engines/k6/runtime/ambient-types/k6/experimental/fs/index.d.ts +0 -104
- package/dist/engines/k6/runtime/ambient-types/k6/experimental/redis/index.d.ts +0 -821
- package/dist/engines/k6/runtime/ambient-types/k6/experimental/streams/index.d.ts +0 -198
- package/dist/engines/k6/runtime/ambient-types/k6/global.d.ts +0 -83
- package/dist/engines/k6/runtime/ambient-types/k6/html/index.d.ts +0 -1325
- package/dist/engines/k6/runtime/ambient-types/k6/http/index.d.ts +0 -806
- package/dist/engines/k6/runtime/ambient-types/k6/index.d.ts +0 -126
- package/dist/engines/k6/runtime/ambient-types/k6/metrics/index.d.ts +0 -66
- package/dist/engines/k6/runtime/ambient-types/k6/net/grpc/index.d.ts +0 -247
- package/dist/engines/k6/runtime/ambient-types/k6/options/index.d.ts +0 -459
- package/dist/engines/k6/runtime/ambient-types/k6/package.json +0 -79
- package/dist/engines/k6/runtime/ambient-types/k6/secrets/index.d.ts +0 -36
- package/dist/engines/k6/runtime/ambient-types/k6/timers/index.d.ts +0 -47
- package/dist/engines/k6/runtime/ambient-types/k6/websockets/index.d.ts +0 -324
- package/dist/engines/k6/runtime/ambient-types/k6/ws/index.d.ts +0 -283
- package/dist/engines/k6/runtime/ambient-types/xk6-sql/LICENSE +0 -201
- package/dist/engines/k6/runtime/ambient-types/xk6-sql/index.d.ts +0 -397
- package/dist/engines/k6/runtime/ambient-types/xk6-sql/package.json +0 -15
- package/dist/engines/k6/runtime/artifacts.d.ts +0 -2
- package/dist/engines/k6/runtime/artifacts.js +0 -1
- package/dist/engines/k6/runtime/checks.d.ts +0 -17
- package/dist/engines/k6/runtime/checks.js +0 -1
- package/dist/engines/k6/runtime/dal-fixtures.d.ts +0 -24
- package/dist/engines/k6/runtime/dal-fixtures.js +0 -1
- package/dist/engines/k6/runtime/dal-suite.d.ts +0 -24
- package/dist/engines/k6/runtime/dal-suite.js +0 -1
- package/dist/engines/k6/runtime/dal.d.ts +0 -10
- package/dist/engines/k6/runtime/dal.js +0 -1
- package/dist/engines/k6/runtime/fixtures.d.ts +0 -3
- package/dist/engines/k6/runtime/fixtures.js +0 -1
- package/dist/engines/k6/runtime/http-assertions.d.ts +0 -19
- package/dist/engines/k6/runtime/http-assertions.js +0 -1
- package/dist/engines/k6/runtime/http-checks.d.ts +0 -19
- package/dist/engines/k6/runtime/http-checks.js +0 -1
- package/dist/engines/k6/runtime/http-suite-runtime.d.ts +0 -103
- package/dist/engines/k6/runtime/http-suite-runtime.js +0 -1
- package/dist/engines/k6/runtime/http.d.ts +0 -15
- package/dist/engines/k6/runtime/http.js +0 -1
- package/dist/engines/k6/runtime/index.d.ts +0 -11
- package/dist/engines/k6/runtime/index.js +0 -1
- package/dist/engines/k6/runtime/input.d.ts +0 -3
- package/dist/engines/k6/runtime/input.js +0 -1
- package/dist/engines/k6/runtime/k6-repository-configuration.d.ts +0 -9
- package/dist/engines/k6/runtime/k6-repository-configuration.js +0 -1
- package/dist/engines/k6/runtime/node-setup.d.ts +0 -13
- package/dist/engines/k6/runtime/node-setup.js +0 -1
- package/dist/engines/k6/runtime/runtime-globals.d.ts +0 -10
- package/dist/engines/k6/runtime/runtime.d.ts +0 -54
- package/dist/engines/k6/runtime/runtime.js +0 -1
- package/dist/engines/k6/runtime/shared/assertion-details.d.ts +0 -19
- package/dist/engines/k6/runtime/shared/assertion-details.js +0 -2
- package/dist/engines/k6/runtime/shared/db-normalization.d.ts +0 -19
- package/dist/engines/k6/runtime/shared/db-normalization.js +0 -1
- package/dist/engines/k6/runtime/shared/error-body.d.ts +0 -3
- package/dist/engines/k6/runtime/shared/error-body.js +0 -1
- package/dist/engines/k6/runtime/shared/file-data.d.ts +0 -1
- package/dist/engines/k6/runtime/shared/file-data.js +0 -1
- package/dist/engines/k6/runtime/shared/fixture-engine.d.ts +0 -8
- package/dist/engines/k6/runtime/shared/fixture-engine.js +0 -2
- package/dist/engines/k6/runtime/shared/http-check-plan.d.ts +0 -29
- package/dist/engines/k6/runtime/shared/http-check-plan.js +0 -1
- package/dist/engines/k6/runtime/shared/http-parsing.d.ts +0 -10
- package/dist/engines/k6/runtime/shared/http-parsing.js +0 -3
- package/dist/engines/k6/runtime/shared/ordering.d.ts +0 -2
- package/dist/engines/k6/runtime/shared/ordering.js +0 -1
- package/dist/engines/k6/runtime/shared/properties.d.ts +0 -1
- package/dist/engines/k6/runtime/shared/properties.js +0 -1
- package/dist/engines/k6/runtime/suite.d.ts +0 -4
- package/dist/engines/k6/runtime/suite.js +0 -1
- package/dist/engines/k6/runtime/types.d.ts +0 -244
- package/dist/engines/k6/runtime/types.js +0 -1
- package/dist/engines/k6/runtime/xk6-sql-driver-postgres.d.ts +0 -7
- package/dist/engines/k6/runtime/xk6-sql-driver-postgres.js +0 -1
- package/dist/engines/managed-module-resolution-policy-input.d.ts +0 -8
- package/dist/engines/managed-module-resolution-policy.d.ts +0 -25
- package/dist/engines/managed-module-resolution.d.ts +0 -13
- package/dist/engines/manager.d.ts +0 -25
- package/dist/engines/node-vitest/adapter/adapter.d.ts +0 -16
- package/dist/engines/node-vitest/adapter/consumer-typescript-paths.d.ts +0 -17
- package/dist/engines/node-vitest/adapter/consumer-typescript-paths.js +0 -3
- package/dist/engines/node-vitest/adapter/evidence.d.ts +0 -33
- package/dist/engines/node-vitest/adapter/failure-details.d.ts +0 -3
- package/dist/engines/node-vitest/adapter/index.d.ts +0 -1
- package/dist/engines/node-vitest/adapter/reporter.d.ts +0 -7
- package/dist/engines/node-vitest/adapter/resolution.d.ts +0 -12
- package/dist/engines/node-vitest/adapter/resolution.js +0 -1
- package/dist/engines/node-vitest/adapter/workspace.d.ts +0 -19
- package/dist/engines/node-vitest/runtime/contract/index.d.ts +0 -64
- package/dist/engines/node-vitest/runtime/data/http.d.ts +0 -4
- package/dist/engines/node-vitest/runtime/data/index.d.ts +0 -8
- package/dist/engines/node-vitest/runtime/data/primitives.d.ts +0 -1
- package/dist/engines/node-vitest/runtime/data/report.d.ts +0 -3
- package/dist/engines/node-vitest/runtime/data/runner.d.ts +0 -4
- package/dist/engines/node-vitest/runtime/data/scenario.d.ts +0 -11
- package/dist/engines/node-vitest/runtime/data/types.d.ts +0 -384
- package/dist/engines/node-vitest/runtime/runtime-input.d.ts +0 -64
- package/dist/engines/playwright/adapter/adapter.d.ts +0 -18
- package/dist/engines/playwright/adapter/attachments.d.ts +0 -26
- package/dist/engines/playwright/adapter/config.d.ts +0 -45
- package/dist/engines/playwright/adapter/evidence-validation.d.ts +0 -9
- package/dist/engines/playwright/adapter/evidence.d.ts +0 -32
- package/dist/engines/playwright/adapter/failure-details.d.ts +0 -2
- package/dist/engines/playwright/adapter/index.d.ts +0 -3
- package/dist/engines/playwright/adapter/reporter.d.ts +0 -12
- package/dist/engines/playwright/runtime/config-file.d.ts +0 -2
- package/dist/engines/playwright/runtime/config.d.ts +0 -24
- package/dist/engines/playwright/runtime/index.d.ts +0 -4
- package/dist/engines/playwright/runtime/runtime-input.d.ts +0 -36
- package/dist/engines/playwright/runtime/sandbox.d.ts +0 -84
- package/dist/engines/runtime-input-file.d.ts +0 -27
- package/dist/environment/lifecycle-artifacts.d.ts +0 -7
- package/dist/environment/lifecycle-controller.d.ts +0 -60
- package/dist/environment/lifecycle.d.ts +0 -32
- package/dist/environment/maintenance.d.ts +0 -68
- package/dist/environment/planning-types.d.ts +0 -33
- package/dist/environment/ports.d.ts +0 -10
- package/dist/environment/ready-environment.d.ts +0 -16
- package/dist/environment/run-environment.d.ts +0 -39
- package/dist/environment/run-stopping.d.ts +0 -13
- package/dist/environment/runtime-contexts.d.ts +0 -37
- package/dist/environment/runtime-manager.d.ts +0 -87
- package/dist/environment/runtime-planning.d.ts +0 -16
- package/dist/environment/runtime-preparation.d.ts +0 -30
- package/dist/environment/runtime-service.d.ts +0 -12
- package/dist/environment/services.d.ts +0 -56
- package/dist/environment/state.d.ts +0 -15
- package/dist/environment/status-runtime.d.ts +0 -53
- package/dist/environment/template.d.ts +0 -164
- package/dist/evidence/artifact-config.d.ts +0 -14
- package/dist/evidence/artifact-validation.d.ts +0 -4
- package/dist/evidence/artifacts.d.ts +0 -75
- package/dist/evidence/bundles.d.ts +0 -27
- package/dist/evidence/ci-provenance.d.ts +0 -9
- package/dist/evidence/contracts.d.ts +0 -154
- package/dist/evidence/environment-record.d.ts +0 -22
- package/dist/evidence/file-evidence.d.ts +0 -23
- package/dist/evidence/finalization.d.ts +0 -9
- package/dist/evidence/index.d.ts +0 -8
- package/dist/evidence/logs.d.ts +0 -31
- package/dist/evidence/operation-timings.d.ts +0 -60
- package/dist/evidence/read-bundle.d.ts +0 -4
- package/dist/evidence/read-fields.d.ts +0 -21
- package/dist/evidence/read-provenance.d.ts +0 -2
- package/dist/evidence/read-redaction.d.ts +0 -2
- package/dist/evidence/read-retention.d.ts +0 -2
- package/dist/evidence/read-run.d.ts +0 -2
- package/dist/evidence/reading.d.ts +0 -28
- package/dist/evidence/reporting-types.d.ts +0 -349
- package/dist/evidence/reporting.d.ts +0 -3
- package/dist/evidence/secure-file-copy.d.ts +0 -24
- package/dist/evidence/setup-progress.d.ts +0 -63
- package/dist/evidence/step-output.d.ts +0 -16
- package/dist/evidence/storage-inventory.d.ts +0 -27
- package/dist/evidence/storage.d.ts +0 -25
- package/dist/evidence/timing.d.ts +0 -23
- package/dist/file.d.ts +0 -11
- package/dist/index.d.ts +0 -4
- package/dist/kernel/error-serialization.d.ts +0 -40
- package/dist/kernel/redaction.d.ts +0 -2
- package/dist/kernel/unknown-values.d.ts +0 -11
- package/dist/kernel/work-metrics.d.ts +0 -6
- package/dist/process/capture-output.d.ts +0 -7
- package/dist/process/command-shell.d.ts +0 -1
- package/dist/process/environment-overlay.d.ts +0 -17
- package/dist/process/environment.d.ts +0 -33
- package/dist/process/files/contained-path.d.ts +0 -8
- package/dist/process/files/directory-status.d.ts +0 -14
- package/dist/process/files/dotenv.d.ts +0 -2
- package/dist/process/files/file-snapshot.d.ts +0 -34
- package/dist/process/files/json-file.d.ts +0 -11
- package/dist/process/files/paths.d.ts +0 -3
- package/dist/process/files/product-dir.d.ts +0 -1
- package/dist/process/files/temp-dir.d.ts +0 -11
- package/dist/process/host/metadata.d.ts +0 -6
- package/dist/process/host/platform.d.ts +0 -57
- package/dist/process/host-command.d.ts +0 -4
- package/dist/process/host-inspection-command.d.ts +0 -13
- package/dist/process/host-process.d.ts +0 -19
- package/dist/process/index.d.ts +0 -9
- package/dist/process/lifecycle-fence.d.ts +0 -10
- package/dist/process/locks.d.ts +0 -28
- package/dist/process/process-contracts.d.ts +0 -78
- package/dist/process/process-group.d.ts +0 -12
- package/dist/process/process-identity.d.ts +0 -27
- package/dist/process/process-limits.d.ts +0 -6
- package/dist/process/process.d.ts +0 -12
- package/dist/process/readiness.d.ts +0 -43
- package/dist/process/recovery.d.ts +0 -3
- package/dist/process/runs/inspection.d.ts +0 -5
- package/dist/process/runs/manifest.d.ts +0 -86
- package/dist/process/runs/ownership.d.ts +0 -11
- package/dist/process/runs/product-state.d.ts +0 -2
- package/dist/process/runs/schema.d.ts +0 -3
- package/dist/process/runs/stop.d.ts +0 -19
- package/dist/process/runtime-socket.d.ts +0 -4
- package/dist/process/service-processes.d.ts +0 -13
- package/dist/process/shutdown.d.ts +0 -10
- package/dist/process/stoppable-settlement.d.ts +0 -26
- package/dist/process/url-redaction.d.ts +0 -1
- package/dist/process/windows-cli-owner.d.ts +0 -2
- package/dist/process/windows-native.d.ts +0 -12
- package/dist/process/windows-process-identity.d.ts +0 -4
- package/dist/repo/ci-environment.d.ts +0 -7
- package/dist/repo/fingerprint-policy.d.ts +0 -13
- package/dist/repo/git-path.d.ts +0 -2
- package/dist/repo/history.d.ts +0 -17
- package/dist/repo/managed-git.d.ts +0 -10
- package/dist/repo/metadata.d.ts +0 -3
- package/dist/repo/physical-tree.d.ts +0 -37
- package/dist/repo/publish-directory.d.ts +0 -20
- package/dist/repo/remote.d.ts +0 -6
- package/dist/repo/state.d.ts +0 -26
- package/dist/repo/tree-listing.d.ts +0 -10
- package/dist/steps/build-config.d.ts +0 -34
- package/dist/steps/configured-step-testkit-modules.d.ts +0 -19
- package/dist/steps/configured-steps.d.ts +0 -51
- package/dist/steps/environment.d.ts +0 -82
- package/dist/steps/index.d.ts +0 -2
- package/dist/steps/module-runner.d.ts +0 -1
- package/dist/steps/run.d.ts +0 -36
- package/dist/toolchains/archive.d.ts +0 -53
- package/dist/toolchains/esbuild.d.ts +0 -9
- package/dist/toolchains/host-node-support.d.ts +0 -3
- package/dist/toolchains/index.d.ts +0 -114
- package/dist/toolchains/managed-node-releases.d.ts +0 -28
- package/dist/toolchains/node-cache.d.ts +0 -20
- package/dist/toolchains/node-integrity.d.ts +0 -18
- package/dist/toolchains/node-provisioning.d.ts +0 -29
- package/dist/toolchains/semver.d.ts +0 -13
- package/dist/toolchains/shared-operation.d.ts +0 -11
- package/dist/toolchains/timeouts.d.ts +0 -1
- package/dist/toolchains/vitest/index.d.ts +0 -13
- package/dist/tracker/gitea.d.ts +0 -14
- package/dist/tracker/github.d.ts +0 -14
- package/dist/tracker/http.d.ts +0 -33
- package/dist/tracker/index.d.ts +0 -4
- package/dist/tracker/redaction.d.ts +0 -4
- package/dist/tracker/requests.d.ts +0 -17
- package/dist/tracker/responses.d.ts +0 -24
- package/dist/tracker/types.d.ts +0 -51
- package/docs/engine-architecture.md +0 -682
- /package/dist/engines/{k6/runtime/runtime-globals.js → api/profiles.js} +0 -0
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
import k from"node:path";import{buildDebugRunSummaryLines as
|
|
2
|
-
`);return;case"run.phase_started"
|
|
3
|
-
`);return;case"run.operation_finished":{if(!
|
|
4
|
-
`);return}case"run.local_service_starting":if(
|
|
5
|
-
`);return;case"run.
|
|
6
|
-
`);return;case"run.task_planned_skip":e.write(`${
|
|
7
|
-
`);return;case"run.task_started":if(
|
|
8
|
-
`);return;case"run.task_finished":{u+=1;const i=r.outcome,
|
|
9
|
-
`),
|
|
10
|
-
`)}return}case"run.
|
|
11
|
-
`),e.write(` ${
|
|
12
|
-
`);return;case"run.
|
|
13
|
-
`)
|
|
1
|
+
import k from"node:path";import{buildDebugRunSummaryLines as I,buildRunSummaryData as F,formatDuration as p}from"./formatting.js";import{formatOperationSummary as T,isNeutralOperationStatus as A,isSuccessfulOperationStatus as M,operationStatusLabel as O}from"../../../domain/operation-display.js";import{boldRed as m,colorSectionLine as P,dim as c,statusLabel as a}from"../../terminal/colors.js";import{getTerminalWidth as D}from"../../terminal/layout.js";import{renderFailureBlock as U}from"./failure.js";export function createRunTextListener(t={}){const{outputMode:n="compact",stdout:e=process.stdout}=t;let u=0,s=0;return r=>{switch(r.type){case"run.total_files":s=r.total;return;case"run.debug":e.write(`${r.line}
|
|
2
|
+
`);return;case"run.phase_started":$(n,e,r.label);return;case"run.toolchain_resolved":g(n,e,r.service,r.runtimeLabel,r.summary);return;case"run.setup_finished":S(n,e,r.operation);return;case"run.operation_started":case"run.operation_progress":if(!w(n,r.operation))return;e.write(`${a("RUN")} INFRA ${b(r.operation)}
|
|
3
|
+
`);return;case"run.operation_finished":{if(!w(n,r.operation,{finished:!0}))return;const i=O(r.operation.status);e.write(`${a(i)} INFRA ${b(r.operation)}
|
|
4
|
+
`);return}case"run.local_service_starting":if(n!=="debug")return;e.write(`Starting ${r.runtimeLabel}:${r.service}: ${r.command}
|
|
5
|
+
`);return;case"run.group_skipped":e.write(`${a("SKIP")} ${r.group} ${r.reason}
|
|
6
|
+
`);return;case"run.task_planned_skip":e.write(`${a("SKIP")} ${f(r.group,r.testType,h(r.file))} ${c("0s")} ${l(r.reason||"skipped")}
|
|
7
|
+
`);return;case"run.task_started":if(n!=="debug")return;e.write(`${a("RUN")} ${f(r.targetName,r.testType,r.file)}
|
|
8
|
+
`);return;case"run.task_finished":{u+=1;const i=r.outcome,o=i.status==="not_run"?"NOT RUN":i.status==="skipped"||i.status==="cancelled"||i.status==="interrupted"?"SKIP":i.status==="failed"?"FAIL":"PASS",d=p(i.durationMs||0),y=i.status==="not_run"||i.status==="cancelled"||i.status==="interrupted"?` ${c(l(i.reason||"not run"))}`:"",L=n==="compact"&&s>0?`${c(`[${String(u)}/${String(s)}]`)} `:"";if(e.write(`${L}${a(o)} ${f(r.group,r.testType,h(r.file))} ${c(d)}${y}
|
|
9
|
+
`),o==="FAIL"){const N=U({engineId:r.engineId,file:r.file,profileId:r.profileId,serviceName:r.group,testType:r.testType},i,{width:D(e,100)});for(const R of N)e.write(`${R}
|
|
10
|
+
`)}return}case"run.error":e.write(`${a("FAIL")} run error
|
|
11
|
+
`),e.write(` ${m(l(r.message))}
|
|
12
|
+
`);return;case"run.runtime_error":e.write(`${a("FAIL")} ${r.group} runtime error
|
|
13
|
+
`),e.write(` ${m(l(r.message||"runtime error"))}
|
|
14
|
+
`);return;case"run.summary":x(n,e,r.results,r.durationMs,r.runStatus);return;case"run.group_plans":case"run.warning":return}}}export function createTextStepProgressReporter(t={}){const{debug:n=!1,stdout:e=process.stdout}=t,u=n?"debug":"compact";return{outputMode:u,phaseStarted(s){$(u,e,s)},setupOperationFinished(s){s&&S(u,e,s)},toolchainResolved(s,r){g(u,e,s.serviceName,s.runtimeLabel,r)},writeDebugLine(s=""){e.write(`${s}
|
|
15
|
+
`)}}}function $(t,n,e){t==="debug"&&n.write(`
|
|
14
16
|
\u2500\u2500 ${e} \u2500\u2500
|
|
15
|
-
`)}function
|
|
16
|
-
`)}function
|
|
17
|
-
`);return}if(t==="compact"&&
|
|
18
|
-
`)}}function
|
|
19
|
-
`);for(const d of
|
|
20
|
-
`);return}const r=
|
|
21
|
-
`),
|
|
22
|
-
`);for(const[
|
|
23
|
-
`)}function l(t){return(t??"").replace(/\s+/g," ").trim().slice(0,180)}function
|
|
17
|
+
`)}function g(t,n,e,u,s){t==="debug"&&n.write(`[testkit] ${u}:${e} toolchain ${s}
|
|
18
|
+
`)}function S(t,n,e){if(e.status==="cached")return;const u=p(e.durationMs||0);if(e.status==="failed"){const s=l(e.error||e.summary||e.stage);n.write(`${a("FAIL")} SETUP ${e.serviceName} ${e.stage} ${c(u)} ${m(s)}
|
|
19
|
+
`);return}if(t==="compact"&&K(e)&&(e.durationMs||0)>=5e3){const s=l(e.summary||e.stage);n.write(`${a("RUN")} SETUP ${e.serviceName} ${s} ${c(u)}
|
|
20
|
+
`)}}function x(t,n,e,u,s){if(t==="debug"){const o=I(e,u,s);n.write(`
|
|
21
|
+
`);for(const d of o)n.write(`${P(d)}
|
|
22
|
+
`);return}const r=F(e,u,s),i=[["Result",r.result],["Passed",String(r.passed)],["Failed",String(r.failed)],["Skipped",String(r.skipped)],["Not run",String(r.notRun)],["Files",String(r.files)]];r.serviceErrors>0&&i.push(["Runtime errors",String(r.serviceErrors)]),i.push(["Duration",r.duration]),n.write(`
|
|
23
|
+
`),n.write(`Summary
|
|
24
|
+
`);for(const[o,d]of i)n.write(`${o}: ${d}
|
|
25
|
+
`)}function l(t){return(t??"").replace(/\s+/g," ").trim().slice(0,180)}function h(t){return t.split(k.sep).join("/")}function K(t){return t.kind==="database-template"||t.kind==="runtime-prepare"}function w(t,n,{finished:e=!1}={}){return t==="debug"?!0:E(n)?e?M(n.status)?(n.durationMs||0)>=5e3:!A(n.status):!0:!1}function E(t){return t.kind==="runtime"}function b(t){const n=t.scope??{},e=j(t.name||t.kind||"operation"),u=_(n.serviceName),s=_(n.graphKey),r=[u?`service=${u}`:"",s?`graph=${s}`:""].filter(Boolean).join(" "),i=l(T(t)),o=t.durationMs==null?B(t.startedAt):p(t.durationMs||0);return[e,r?c(r):"",i?l(i):"",o?c(o):""].filter(Boolean).join(" ")}function _(t){return typeof t=="string"?t:""}function j(t){return t.replace(/^testkit\./,"").replaceAll("_","-")}function B(t){const n=Date.parse(t||"");return Number.isFinite(n)?p(Math.max(0,Date.now()-n)):""}function f(t,n,e){return n===void 0?`${t} ${e}`:`${t} ${n} ${e}`}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createColors as
|
|
1
|
+
import t from"node:tty";import{createColors as n}from"picocolors";const{FORCE_COLOR:o,NO_COLOR:u}=process.env,e=n(o===void 0?!u&&t.isatty(1):!["0","false"].includes(o));export function statusLabel(r){return r==="PASS"?e.green("PASS"):r==="FAIL"?e.red("FAIL"):r==="SKIP"?e.yellow("SKIP"):r==="NOT RUN"?e.yellow("NOT RUN"):r==="RUN"?e.cyan("RUN"):r}export function dim(r){return e.dim(r)}export function bold(r){return e.bold(r)}export function boldRed(r){return e.bold(e.red(r))}export function colorService(r){return e.cyan(e.bold(r))}export function colorTypeBadge(r){return r==="PW"?e.blue(e.bold(r)):r}export function colorDiagnosticSeverity(r){return r==="error"?e.red(e.bold("ERR")):r==="warning"?e.yellow(e.bold("WARN")):e.dim("INFO")}export function colorSectionLine(r){return r==="Case store issues:"||r==="Diagnosis:"?e.bold(r):/^Summary: /.test(r)?r.replace("Summary:",e.bold("Summary:")):/^Result: PASSED\b/.test(r)?r.replace("PASSED",e.green("PASSED")):/^Result: FAILED\b/.test(r)?r.replace("FAILED",e.red("FAILED")):r}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import u from"string-width";import s from"wrap-ansi";export function getTerminalWidth(r=process.stdout,t=100){const n=Number(r.columns);return Number.isFinite(n)&&n>0?n:t}export function
|
|
2
|
-
`)}export function renderIndentedBlock(r,{width:t,indent:n=" "}){const e=
|
|
1
|
+
import u from"string-width";import s from"wrap-ansi";export function getTerminalWidth(r=process.stdout,t=100){const n=Number(r.columns);return Number.isFinite(n)&&n>0?n:t}export function wrapText(r,t){return t<=0?[r]:s(r,t,{hard:!0,trim:!1,wordWrap:!0}).split(`
|
|
2
|
+
`)}export function renderIndentedBlock(r,{width:t,indent:n=" "}){const e=u(n),o=Math.max(12,t-e);return wrapText(r,o).map(i=>`${n}${i}`)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function createHttpMethods(T){return{post:(t,e,...p)=>T("POST",t,e,...p),put:(t,e,...p)=>T("PUT",t,e,...p),patch:(t,e,...p)=>T("PATCH",t,e,...p),get:(t,...e)=>T("GET",t,void 0,...e),delete:(t,e,...p)=>T("DELETE",t,e,...p)}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import m from"node:crypto";import{isUnknownRecord as c}from"../../kernel/unknown-values.js";import o from"node:fs";import
|
|
1
|
+
import m from"node:crypto";import{isUnknownRecord as c}from"../../kernel/unknown-values.js";import o from"node:fs";import i from"node:path";import{fileURLToPath as d,pathToFileURL as p}from"node:url";import{buildWithEsbuildRetry as h}from"../../toolchains/esbuild.js";const u=i.resolve(i.dirname(d(import.meta.url)),"..","..",".."),k=i.join(u,"dist","index.js"),j=i.join(u,"dist","config","authoring","index.js"),w=new Set(["/environment","/node-vitest/data","/node-vitest/contract","/playwright"]),y=["testkit.config.ts","testkit.config.mts","testkit.config.mjs","testkit.config.js"];export function findConfigFile(t){for(const n of y){const e=i.join(t,n);if(o.existsSync(e))return e}return null}export async function loadTestkitConfig(t,n={}){const e=findConfigFile(t);if(!e)return{config:{},configFile:null};const r=i.join(t,".testkit","_config");o.mkdirSync(r,{recursive:!0});const s=b(e),a=i.join(r,`config-${s.slice(0,12)}.mjs`);await h({absWorkingDir:t,bundle:!0,entryPoints:[e],format:"esm",legalComments:"none",outfile:a,platform:"node",sourcemap:"inline",target:"es2020",plugins:[C()]});const l=[s,n.importCacheSalt||""].filter(Boolean).join("-"),g=await import(`${p(a).href}?v=${l}`),f=S(g);if(!c(f))throw new Error(`testkit config file must export an object: ${i.basename(e)}`);return{config:f,configFile:e}}function b(t){const n=o.readFileSync(t,"utf8");return m.createHash("sha256").update(t).update("\0").update(n).digest("hex")}function C(){return{name:"testkit-config-alias",setup(t){t.onResolve({filter:/^@gfdelarue\/testkit(?:\/.*)?$/},n=>({namespace:"file",path:E(n.path)}))}}}function E(t){const n=t.slice(18);if(!n)return k;if(n==="/config")return j;throw w.has(n)?new Error(`testkit.config.ts may not import engine authoring module "${t}". Use repository config helpers from @gfdelarue/testkit/config instead.`):new Error(`Unsupported @gfdelarue/testkit import "${t}" while loading testkit config`)}function S(t){if(c(t))return t.default||t.config||{}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DEFAULT_FILE_TIMEOUT_SECONDS as u,normalizeFileTimeoutSeconds as a}from"../../domain/file-timeout.js";export function parseTaskConcurrencyOptions(e,n){return i(e,n,"--task-concurrency","--workers")??null}export function normalizeRuntimeInstances(e,n="runtime.instances"){return c(e,n)}export function normalizeRuntimeMaxConcurrentTasks(e,n="runtime.maxConcurrentTasks"){return e==null?Number.POSITIVE_INFINITY:c(e,n)}export function normalizeDatabaseBinding(e,n="database.binding"){const r=String(e).trim();if(r!=="shared"&&r!=="per-runtime")throw new Error(`Invalid ${n} value "${String(e)}". Expected one of: shared, per-runtime.`);return r}export function resolveExecutionConfig({cli:e={},repo:n={}}={}){const r=i(n.taskConcurrency,n.workers);return{taskConcurrency:i(e.taskConcurrency,e.workers,"--task-concurrency","--workers")??r??1,fileTimeoutSeconds:a(e.fileTimeoutSeconds??n.fileTimeoutSeconds??u)}}export function normalizeExecutionConfig(e={}){const n=new Set(["workers","taskConcurrency","fileTimeoutSeconds"]),r=Object.keys(e).filter(o=>!n.has(o));if(r.length>0)throw new Error(`execution received unexpected key(s): ${r.join(", ")}`);return{taskConcurrency:i(e.taskConcurrency,e.workers)??1,fileTimeoutSeconds:a(e.fileTimeoutSeconds??u)}}function i(e,n,r="execution.taskConcurrency",t="execution.workers"){const o=e==null?void 0:c(e,r),s=n==null?void 0:c(n,t);if(o!==void 0&&s!==void 0&&o!==s)throw new Error(`${r} and ${t} must match when both are provided.`);return o??s}
|
|
1
|
+
import{DEFAULT_FILE_TIMEOUT_SECONDS as u,normalizeFileTimeoutSeconds as a,normalizePositiveInteger as c}from"../../domain/file-timeout.js";export function parseTaskConcurrencyOptions(e,n){return i(e,n,"--task-concurrency","--workers")??null}export function normalizeRuntimeInstances(e,n="runtime.instances"){return c(e,n)}export function normalizeRuntimeMaxConcurrentTasks(e,n="runtime.maxConcurrentTasks"){return e==null?Number.POSITIVE_INFINITY:c(e,n)}export function normalizeDatabaseBinding(e,n="database.binding"){const r=String(e).trim();if(r!=="shared"&&r!=="per-runtime")throw new Error(`Invalid ${n} value "${String(e)}". Expected one of: shared, per-runtime.`);return r}export function resolveExecutionConfig({cli:e={},repo:n={}}={}){const r=i(n.taskConcurrency,n.workers);return{taskConcurrency:i(e.taskConcurrency,e.workers,"--task-concurrency","--workers")??r??1,fileTimeoutSeconds:a(e.fileTimeoutSeconds??n.fileTimeoutSeconds??u)}}export function normalizeExecutionConfig(e={}){const n=new Set(["workers","taskConcurrency","fileTimeoutSeconds"]),r=Object.keys(e).filter(o=>!n.has(o));if(r.length>0)throw new Error(`execution received unexpected key(s): ${r.join(", ")}`);return{taskConcurrency:i(e.taskConcurrency,e.workers)??1,fileTimeoutSeconds:a(e.fileTimeoutSeconds??u)}}function i(e,n,r="execution.taskConcurrency",t="execution.workers"){const o=e==null?void 0:c(e,r),s=n==null?void 0:c(n,t);if(o!==void 0&&s!==void 0&&o!==s)throw new Error(`${r} and ${t} must match when both are provided.`);return o??s}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function resolveRuntimeConfigs(o,
|
|
1
|
+
export function resolveRuntimeClosure(s,o){const n=new Map;for(const t of s)for(const r of resolveRuntimeConfigs(t,o))n.set(r.name,r);return[...n.values()]}export function resolveRuntimeConfigs(s,o){const n=[],t=new Set,r=new Set,a=e=>{if(!r.has(e.name)){if(t.has(e.name))throw new Error(`Dependency cycle detected involving "${e.name}"`);t.add(e.name);for(const d of e.testkit.dependsOn||[]){const u=o.get(d);if(!u)throw new Error(`Service "${e.name}" depends on unknown service "${d}"`);a(u)}t.delete(e.name),r.add(e.name),n.push(e)}};return a(s),n}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import g from"path";import{randomUUID as z}from"node:crypto";import{isUnknownRecord as D}from"../../kernel/unknown-values.js";import{loadConfigContext as P,resolveProductDir as A}from"./load.js";import{discoverProject as B,hasDiscoveryErrors as H,buildDiscoveryErrorFromDiagnostics as L}from"./discovery.js";import{loadTestkitConfig as V}from"./config-loader.js";import{TEST_TYPE_ORDER as _,isRunType as U}from"../../domain/test-types.js";import"../../domain/identifiers.js";import{DEFAULT_RUNTIME_ISOLATION_POLICY as q,resolveRuntimeIsolationPolicy as G}from"./runtime-isolation.js";import{resolveEngineProfile as Y}from"../../engines/catalog.js";import{readTestFileMetadata as K}from"./file-metadata.js";import{normalizeDiscoveryConfig as J}from"./decode-discovery.js";import"./path-policy.js";import{buildDiscoverySummary as Q,emptyDiscoverySummary as W}from"./discovery-summary.js";import{matchesSelectedTypes as X,matchesSuiteSelectors as k,normalizeTypeValues as Z,parseSuiteSelectors as ee}from"../../domain/suite-selection.js";import{errorMessage as E}from"../../kernel/error-serialization.js";import{readObjectRecord as I,readProperty as f}from"./values.js";const ie=9,C=String;export async function discoverTests(e={}){return(await loadDiscoveryContext(e)).discovery}export async function loadDiscoveredConfigContext(e={}){const i=await P({dir:e.dir,configImportCacheSalt:z()}),{discovery:t}=await loadDiscoveryContext({dir:i.productDir,diagnostics:"error"},i);return{context:i,discovery:t}}export async function loadDiscoveryContext(e={},i){const t=i?.productDir??A(process.cwd(),e.dir),o=le(e);if(i&&o.diagnosticsMode==="error"&&H(i.discovery.diagnostics))throw L(i.discovery.diagnostics);const r=i?{config:i.config,configFile:i.configFile,diagnostics:[]}:await te(t,o.diagnosticsMode),s={schemaVersion:ie,source:"testkit-discovery",product:{name:g.basename(t),directory:t},configFile:r.configFile?g.relative(t,r.configFile)||g.basename(r.configFile):null,filters:{service:o.serviceFilter,types:o.typeValues,suiteSelectors:o.suiteSelectors.map(n=>n.raw),fileNames:o.fileNames,runnableOnly:o.runnableOnly,diagnostics:o.diagnosticsMode},services:[],suites:[],files:[],diagnostics:[...r.diagnostics],summary:W()};if(!r.config)return{discovery:R(s),context:null};const a=ue(r.config),l=fe(a.services),p=i?.discovery??B(t,l,{strict:o.diagnosticsMode==="error",discovery:a.discovery}),v={project:p,fileMetadataByPath:new Map(i?.configs.flatMap(n=>[...n.testkit.fileMetadataByPath])??[])};s.diagnostics.push(...p.diagnostics),ae(o.serviceFilter,a.services,p);let y=i??null;try{y=i??await P({dir:t,preparedDiscovery:v,configContext:{config:r.config,configFile:r.configFile},discoveryOptions:{strict:o.diagnosticsMode==="error"}})}catch(n){if(o.diagnosticsMode==="error")throw n;s.diagnostics.push({code:"config_invalid",severity:"error",message:E(n)})}const h=ne({productDir:t,rawDiscovery:p,explicitServices:a.services,configs:y?.configs??[],fileMetadataByPath:v.fileMetadataByPath,filters:o});return{discovery:R({...s,...h}),context:y}}export function formatDisplayName(e){return C(e||"").split(/[-_/]+/g).filter(Boolean).map(i=>i.replace(/^\w/,t=>t.toUpperCase())).join(" ")}export function testTypeContract(e,i,t){const o=Y(e,i);if(o.id!==t)throw new Error(`Discovery profile mismatch for ${e}: metadata resolved ${t}, catalog resolved ${o.id}`);return e==="data"?{authoringApi:"@gfdelarue/testkit/node-vitest/data",executionHost:o.capabilities.executionHost,summary:"Data suites use the node-vitest engine and record Testkit data evidence; they are not raw Vitest or service-namespace tests."}:e==="contract"?{authoringApi:"@gfdelarue/testkit/node-vitest/contract",executionHost:o.capabilities.executionHost,summary:"Contract suites use the node-vitest engine for Node-backed service/runtime contracts without data-flow evidence requirements."}:i==="k6"?{authoringApi:"@gfdelarue/testkit/k6",executionHost:o.capabilities.executionHost}:i==="playwright"?{authoringApi:"@gfdelarue/testkit/playwright",executionHost:o.capabilities.executionHost}:{executionHost:o.capabilities.executionHost}}async function te(e,i){try{const t=await V(e),{config:o,configFile:r}=oe(t);return{config:o,configFile:r,diagnostics:[]}}catch(t){if(i==="error")throw t;return{config:null,configFile:null,diagnostics:[{code:"config_invalid",severity:"error",message:E(t)}]}}}function oe(e){if(!D(e))throw new Error("testkit config loader must return an object");const i=f(e,"config"),t=f(e,"configFile");if(!D(i)){const o=typeof t=="string"?g.basename(t):"testkit config file";throw new Error(`testkit config file must export an object: ${o}`)}if(t!==null&&typeof t!="string")throw new Error("testkit config loader returned an invalid config path");return{config:i,configFile:t}}function ne({configs:e,fileMetadataByPath:i,productDir:t,rawDiscovery:o,explicitServices:r,filters:s}){const a=new Map(e.map(n=>[n.name,n])),l=new Map,p=new Map,v=[],y=new Set([...Object.keys(r),...Object.keys(o.services),...a.keys()]);for(const n of y){if(s.serviceFilter&&n!==s.serviceFilter)continue;const c=a.get(n),u=o.services[n],d=r[n];l.set(n,{name:n,discovered:c!==void 0||!!u,localCwd:c?c.testkit.local?.cwd||".":d?.localCwd||u?.inferredLocalCwd||".",dependsOn:[...c?.testkit.dependsOn??d?.dependsOn??[]],suiteCount:0,fileCount:0,activeFileCount:0,skippedFileCount:0})}for(const n of o.files){const c=n.testType;if(!X(c,s.typeValues)||!k(c,n.suiteName,s.suiteSelectors)||s.serviceFilter&&n.serviceName!==s.serviceFilter||s.fileNameSet.size>0&&!s.fileNameSet.has(n.filePath))continue;const u=i.get(n.filePath)??K(t,n.filePath);i.set(n.filePath,u);const d=a.get(n.serviceName),m=d?.suites[c]?.find(j=>j.name===n.suiteName);if(d&&(!m||m.testType!==c||m.engineId!==u.engineId||m.profileId!==u.profileId))throw new Error(`Normalized suite ${n.serviceName}/${c}:${n.suiteName} conflicts with file ${n.filePath}`);const b=d&&(u.skipReason||d.testkit.skip?.fileReasonByPath.get(n.filePath)||me(d,c,n.suiteName))||null;if(s.runnableOnly&&b)continue;const x=d?[...new Set([...ge(d,c,n.suiteName),...d.testkit.requirements.fileLocksByPath.get(n.filePath)||[],...u.locks])].sort():[],$=l.get(n.serviceName)?.dependsOn||[],w=re({serviceName:n.serviceName,suiteName:n.suiteName,testType:c,filePath:n.filePath,engineId:u.engineId,profileId:u.profileId,skipReason:b,locks:x,runtimeIsolation:d&&m?G(d,m,n.filePath):q,dependsOn:$});v.push(w);const F=[n.serviceName,c,n.suiteName].join("|"),O=p.get(F);O?O.files.push(w):p.set(F,{serviceName:n.serviceName,testType:c,suiteName:n.suiteName,files:[w]})}const h=[...p.values()].map(n=>se(n.serviceName,n.testType,n.suiteName,n.files,l.get(n.serviceName)?.dependsOn||[]));for(const n of h){const c=l.get(n.service)||{name:n.service,discovered:!0,localCwd:o.services[n.service]?.inferredLocalCwd||".",dependsOn:[...r[n.service]?.dependsOn||[]],suiteCount:0,fileCount:0,activeFileCount:0,skippedFileCount:0};c.suiteCount+=1,c.fileCount+=n.fileCount,c.activeFileCount+=n.activeFileCount,c.skippedFileCount+=n.skippedFileCount,l.set(n.service,c)}return{services:[...l.values()].sort((n,c)=>n.name.localeCompare(c.name)),suites:h.sort(he),files:v.sort(Ce)}}function re(e){const i=testTypeContract(e.testType,e.engineId,e.profileId);return{id:ye(e.serviceName,e.testType,e.engineId,e.profileId,e.filePath),path:e.filePath,displayName:fileDisplayName(e.filePath),service:e.serviceName,suiteName:e.suiteName,groupLabel:formatDisplayName(e.suiteName),testType:e.testType,engineId:e.engineId,profileId:e.profileId,skipped:!!e.skipReason,skipReason:e.skipReason,locks:e.locks,runtimeIsolation:e.runtimeIsolation,dependsOn:[...e.dependsOn],contract:i}}function se(e,i,t,o,r){const s=ce(e,i,t,o),a=o.filter(l=>l.skipped).length;return{id:ve(e,i,s.engineId,s.profileId,t),service:e,name:t,displayName:formatDisplayName(t),testType:i,engineId:s.engineId,profileId:s.profileId,groupLabel:formatDisplayName(t),fileCount:o.length,activeFileCount:o.length-a,skippedFileCount:a,dependsOn:[...r],locks:[...new Set(o.flatMap(l=>l.locks))].sort(),filePaths:o.map(l=>l.path),contract:s.contract}}function ce(e,i,t,o){const r=o[0];for(const s of o.slice(1))if(s.engineId!==r.engineId||s.profileId!==r.profileId)throw new Error(`Discovery suite ${e}/${i}:${t} mixes engine profiles ${r.engineId}/${r.profileId} and ${s.engineId}/${s.profileId}`);return{contract:r.contract,engineId:r.engineId,profileId:r.profileId}}function R(e){return{...e,diagnostics:e.diagnostics.sort(we),summary:Q({diagnostics:e.diagnostics,files:e.files,serviceCount:e.services.length,suiteCount:e.suites.length})}}function ae(e,i,t){if(!e)return;const o=new Set([...Object.keys(i),...Object.keys(t.services),...Object.keys(t.suitesByService)]);if(o.has(e))return;const r=[...o].sort((s,a)=>s.localeCompare(a)).join(", ");throw new Error(r.length>0?`Service "${e}" not found. Available: ${r}`:`Service "${e}" not found.`)}function le(e){const i=de(Z(N(e.type))),t=ee(N(e.suite)),o=N(e.file).map(S);return{typeValues:i,suiteSelectors:t,fileNames:o,fileNameSet:new Set(o),serviceFilter:e.service||null,runnableOnly:!!e.runnableOnly,diagnosticsMode:e.diagnostics==="error"?"error":"report"}}function de(e){const i=[];for(const t of e){if(!U(t))throw new Error(`Discovery produced unsupported test type "${t}".`);i.push(t)}return i}function ue(e){const i=I(f(e,"services")),t={};for(const[o,r]of Object.entries(i)){const s=I(r),a=I(f(s,"local"));t[o]={dependsOn:pe(f(s,"dependsOn")),discovery:M(f(s,"discovery")),localCwd:S(f(a,"cwd")||"."),localDisabled:f(s,"local")===!1}}return{discovery:M(f(e,"discovery")),services:t}}function fe(e){const i={};for(const[t,o]of Object.entries(e))o&&(i[t]={discovery:o.discovery,local:o.localDisabled?!1:{baseUrl:"",cwd:o.localCwd,env:{},start:""}});return i}function M(e){try{return J(e,{allowRoots:!0})}catch{return{}}}function pe(e){return Array.isArray(e)?e.filter(t=>typeof t=="string"):[]}function me(e,i,t){for(const o of e.testkit.skip?.suites||[])if(k(i,t,[o.selector]))return o.reason;return null}function ge(e,i,t){const o=new Set;for(const r of e.testkit.requirements.suites)if(k(i,t,[r.selector]))for(const s of r.locks)o.add(s);return[...o].sort()}function N(e){return Array.isArray(e)?e.filter(t=>t!=null).map(t=>C(t)):e==null||e===""?[]:[C(e)]}function S(e){return C(e).split(g.sep).join("/").replace(/^\.\/+/,"")}export function fileDisplayName(e){const i=new RegExp(`\\.(${_.join("|")})\\.testkit\\.ts$`),t=g.posix.basename(e).replace(i,"");return formatDisplayName(t)}function ve(e,i,t,o,r){return[e,i,t,o,r].join("|")}function ye(e,i,t,o,r){return[e,i,t,o,S(r)].join("|")}function he(e,i){return e.service.localeCompare(i.service)||e.testType.localeCompare(i.testType)||e.name.localeCompare(i.name)}function Ce(e,i){return e.service.localeCompare(i.service)||e.testType.localeCompare(i.testType)||e.suiteName.localeCompare(i.suiteName)||e.path.localeCompare(i.path)}function we(e,i){return T(e.severity)-T(i.severity)||e.code.localeCompare(i.code)||(e.path||"").localeCompare(i.path||"")}function T(e){return e==="error"?1:2}
|
|
1
|
+
import m from"path";import{randomUUID as j}from"node:crypto";import{isUnknownRecord as D,readDynamicProperty as S}from"../../kernel/unknown-values.js";import{loadConfigContext as P,resolveProductDir as z}from"./load.js";import{hasDiscoveryErrors as B,buildDiscoveryErrorFromDiagnostics as V}from"./discovery.js";import{discoverOwnedTests as _}from"./owned-discovery.js";import{loadTestkitConfig as x}from"./config-loader.js";import{TEST_TYPE_ORDER as A,isRunType as L}from"../../domain/test-types.js";import"../../domain/identifiers.js";import{DEFAULT_RUNTIME_ISOLATION_POLICY as U,resolveRuntimeIsolationPolicy as q}from"./runtime-isolation.js";import{resolveExecutionProfile as Y}from"../../engines/catalog.js";import{readTestFileMetadata as G}from"./file-metadata.js";import{buildDiscoverySummary as K,emptyDiscoverySummary as H}from"./discovery-summary.js";import{matchesSelectedTypes as J,matchesSuiteSelectors as w,normalizeTypeValues as Q,parseSuiteSelectors as W,suiteKey as E}from"../../domain/suite-selection.js";import{errorMessage as b}from"../../kernel/error-serialization.js";const X=10,h=String;export async function discoverTests(e={}){return(await loadDiscoveryContext(e)).discovery}export async function loadDiscoveredConfigContext(e={}){const i=await P({...e,configImportCacheSalt:j()}),{discovery:o}=await loadDiscoveryContext({dir:i.productDir,diagnostics:"error"},i);return{context:i,discovery:o}}export async function loadDiscoveryContext(e={},i){const o=i?.productDir??z(process.cwd(),e.dir),n=se(e);if(i&&n.diagnosticsMode==="error"&&B(i.discovery.diagnostics))throw V(i.discovery.diagnostics);const r=i?{config:i.config,configFile:i.configFile,diagnostics:[]}:await Z(o,n.diagnosticsMode),a={schemaVersion:X,source:"testkit-discovery",product:{name:m.basename(o),directory:o},configFile:r.configFile?m.relative(o,r.configFile)||m.basename(r.configFile):null,filters:{group:n.groupFilter,types:n.typeValues,suiteSelectors:n.suiteSelectors.map(t=>t.raw),fileNames:n.fileNames,runnableOnly:n.runnableOnly,diagnostics:n.diagnosticsMode},groups:[],suites:[],files:[],diagnostics:[...r.diagnostics],summary:H()};if(!r.config)return{discovery:T(a),context:null,notice:null};const c=i?{groups:i.groups,notice:i.ownershipNotice,plainFiles:[],problems:[],project:i.discovery}:await _(o,r.config,{selection:e.vitest,strict:n.diagnosticsMode==="error"}),p=c.project,d={owned:c,fileMetadataByPath:new Map(i?.groups.flatMap(t=>[...t.testkit.fileMetadataByPath])??[])};a.diagnostics.push(...p.diagnostics),re(n.groupFilter,c.groups);let f=i??null;try{f=i??await P({dir:o,preparedDiscovery:d,configContext:{config:r.config,configFile:r.configFile},discoveryOptions:{strict:n.diagnosticsMode==="error"}})}catch(t){if(n.diagnosticsMode==="error")throw t;a.diagnostics.push({code:"config_invalid",severity:"error",message:b(t)})}const y=ie({productDir:o,rawDiscovery:p,declarations:c.groups,groups:f?.groups??[],fileMetadataByPath:d.fileMetadataByPath,filters:n});return{discovery:T({...a,...y}),context:f,notice:c.notice}}export function formatDisplayName(e){return h(e||"").split(/[-_/]+/g).filter(Boolean).map(i=>i.replace(/^\w/,o=>o.toUpperCase())).join(" ")}export function testTypeContract(e,i,o){return Y({engineId:i,profileId:o,testType:e}),e==="data"?{authoringApi:"@gfdelarue/testkit/node-vitest/data",summary:"Data suites use the node-vitest engine and record Testkit data evidence; they are not raw Vitest or service-namespace tests."}:e==="contract"?{authoringApi:"@gfdelarue/testkit/node-vitest/contract",summary:"Contract suites use the node-vitest engine for Node-backed service/runtime contracts without data-flow evidence requirements."}:i==="playwright"?{authoringApi:"@gfdelarue/testkit/playwright"}:{}}async function Z(e,i){try{const o=await x(e),{config:n,configFile:r}=ee(o);return{config:n,configFile:r,diagnostics:[]}}catch(o){if(i==="error")throw o;return{config:null,configFile:null,diagnostics:[{code:"config_invalid",severity:"error",message:b(o)}]}}}function ee(e){if(!D(e))throw new Error("testkit config loader must return an object");const i=S(e,"config"),o=S(e,"configFile");if(!D(i)){const n=typeof o=="string"?m.basename(o):"testkit config file";throw new Error(`testkit config file must export an object: ${n}`)}if(o!==null&&typeof o!="string")throw new Error("testkit config loader returned an invalid config path");return{config:i,configFile:o}}function ie({declarations:e,fileMetadataByPath:i,filters:o,groups:n,productDir:r,rawDiscovery:a}){const c=new Map(n.map(t=>[t.name,t])),p=new Map,d=new Map,f=[];for(const t of e)o.groupFilter&&t.name!==o.groupFilter||p.set(t.name,{name:t.name,roots:[...t.roots],uses:[...t.uses],source:t.source,suiteCount:0,fileCount:0,activeFileCount:0,skippedFileCount:0});for(const t of a.files){const s=t.testType;if(!J(s,o.typeValues)||!w(s,t.suiteName,o.suiteSelectors)||o.groupFilter&&t.serviceName!==o.groupFilter||o.fileNameSet.size>0&&!o.fileNameSet.has(t.filePath))continue;const u=i.get(t.filePath)??G(r,t.filePath);i.set(t.filePath,u);const l=c.get(t.serviceName),g=l?.suites.find(F=>F.testType===s&&F.name===t.suiteName);if(l&&(!g||g.engineId!==u.engineId||g.profileId!==u.profileId))throw new Error(`Normalized suite ${t.serviceName}/${E({name:t.suiteName,testType:s})} conflicts with file ${t.filePath}`);const I=l&&(u.skipReason||l.testkit.skip?.fileReasonByPath.get(t.filePath)||ce(l,s,t.suiteName))||null;if(o.runnableOnly&&I)continue;const O=l?[...new Set([...le(l,s,t.suiteName),...l.testkit.requirements.fileLocksByPath.get(t.filePath)||[],...u.locks])].sort():[],v=oe({groupName:t.serviceName,suiteName:t.suiteName,testType:s,filePath:t.filePath,engineId:u.engineId,profileId:u.profileId,skipReason:I,locks:O,runtimeIsolation:l&&g?q(l,g,t.filePath):U});f.push(v);const k=[t.serviceName,s??"",t.suiteName].join("|"),N=d.get(k);N?N.files.push(v):d.set(k,{groupName:t.serviceName,testType:s,suiteName:t.suiteName,files:[v]})}const y=[...d.values()].map(t=>te(t.groupName,t.testType,t.suiteName,t.files));for(const t of y){const s=p.get(t.group);if(s===void 0)throw new Error(`Discovered suite ${t.id} belongs to no declared group`);s.suiteCount+=1,s.fileCount+=t.fileCount,s.activeFileCount+=t.activeFileCount,s.skippedFileCount+=t.skippedFileCount}return{groups:[...p.values()].sort((t,s)=>t.name.localeCompare(s.name)),suites:y.sort(ue),files:f.sort(pe)}}function oe(e){const i=testTypeContract(e.testType,e.engineId,e.profileId);return{id:R(e.groupName,e.testType,e.engineId,e.profileId,M(e.filePath)),path:e.filePath,displayName:fileDisplayName(e.filePath),group:e.groupName,suiteName:e.suiteName,suiteLabel:formatDisplayName(e.suiteName),...e.testType===void 0?{}:{testType:e.testType},engineId:e.engineId,profileId:e.profileId,skipped:!!e.skipReason,skipReason:e.skipReason,locks:e.locks,runtimeIsolation:e.runtimeIsolation,contract:i}}function te(e,i,o,n){const r=ne(e,i,o,n),a=n.filter(c=>c.skipped).length;return{id:R(e,i,r.engineId,r.profileId,o),group:e,name:o,displayName:formatDisplayName(o),...i===void 0?{}:{testType:i},engineId:r.engineId,profileId:r.profileId,suiteLabel:formatDisplayName(o),fileCount:n.length,activeFileCount:n.length-a,skippedFileCount:a,locks:[...new Set(n.flatMap(c=>c.locks))].sort(),filePaths:n.map(c=>c.path),contract:r.contract}}function ne(e,i,o,n){const r=n[0];for(const a of n.slice(1))if(a.engineId!==r.engineId||a.profileId!==r.profileId)throw new Error(`Discovery suite ${e}/${E({name:o,testType:i})} mixes engine profiles ${r.engineId}/${r.profileId} and ${a.engineId}/${a.profileId}`);return{contract:r.contract,engineId:r.engineId,profileId:r.profileId}}function T(e){return{...e,diagnostics:e.diagnostics.sort(de),summary:K({diagnostics:e.diagnostics,files:e.files,groupCount:e.groups.length,suiteCount:e.suites.length})}}function re(e,i){if(!e||i.some(n=>n.name===e))return;const o=i.map(n=>n.name).sort((n,r)=>n.localeCompare(r)).join(", ");throw new Error(`Group "${e}" not found. Available: ${o}`)}function se(e){const i=ae(Q(C(e.type))),o=W(C(e.suite)),n=C(e.file).map(M);return{typeValues:i,suiteSelectors:o,fileNames:n,fileNameSet:new Set(n),groupFilter:e.group||null,runnableOnly:!!e.runnableOnly,diagnosticsMode:e.diagnostics==="error"?"error":"report"}}function ae(e){const i=[];for(const o of e){if(!L(o))throw new Error(`Discovery produced unsupported test type "${o}".`);i.push(o)}return i}function ce(e,i,o){for(const n of e.testkit.skip?.suites||[])if(w(i,o,[n.selector]))return n.reason;return null}function le(e,i,o){const n=new Set;for(const r of e.testkit.requirements.suites)if(w(i,o,[r.selector]))for(const a of r.locks)n.add(a);return[...n].sort()}function C(e){return Array.isArray(e)?e.filter(o=>o!=null).map(o=>h(o)):e==null||e===""?[]:[h(e)]}function M(e){return h(e).split(m.sep).join("/").replace(/^\.\/+/,"")}export function fileDisplayName(e){const i=new RegExp(`\\.(${A.join("|")})\\.testkit\\.ts$`),o=m.posix.basename(e).replace(i,"");return formatDisplayName(o)}function R(e,i,o,n,r){return[e,...i===void 0?[]:[i],o,n,r].join("|")}function ue(e,i){return e.group.localeCompare(i.group)||(e.testType??"").localeCompare(i.testType??"")||e.name.localeCompare(i.name)}function pe(e,i){return e.group.localeCompare(i.group)||(e.testType??"").localeCompare(i.testType??"")||e.suiteName.localeCompare(i.suiteName)||e.path.localeCompare(i.path)}function de(e,i){return $(e.severity)-$(i.severity)||e.code.localeCompare(i.code)||(e.path||"").localeCompare(i.path||"")}function $(e){return e==="error"?1:2}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function buildDiscoverySummary(s){const i={},r={};for(const e of s.files)i[e.
|
|
1
|
+
export function buildDiscoverySummary(s){const i={},r={};for(const e of s.files)i[e.group]=(i[e.group]||0)+1,e.testType!==void 0&&(r[e.testType]=(r[e.testType]||0)+1);return{activeFiles:s.files.filter(e=>!e.skipped).length,byGroup:i,byTestType:r,diagnostics:{errors:s.diagnostics.filter(e=>e.severity==="error").length,warnings:s.diagnostics.filter(e=>e.severity==="warning").length},files:s.files.length,groups:s.groupCount,skippedFiles:s.files.filter(e=>e.skipped).length,suites:s.suiteCount}}export function emptyDiscoverySummary(){return{activeFiles:0,byGroup:{},byTestType:{},diagnostics:{errors:0,warnings:0},files:0,groups:0,skippedFiles:0,suites:0}}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
`))}function
|
|
1
|
+
import k from"fs";import y from"path";import{recordWork as v}from"../../kernel/work-metrics.js";import{DEFAULT_DISCOVERY_EXCLUDES as F,normalizeDiscoveryPath as C,resolveDiscoveryRoots as D,shouldExcludeDiscoveryPath as E}from"./path-policy.js";const P=String,w="__testkit__",N=/\.(?:test|spec)\.[cm]?[jt]sx?$/u,$=[{suffix:".contract.testkit.ts",testType:"contract"},{suffix:".data.testkit.ts",testType:"data"},{suffix:".ui.testkit.ts",testType:"ui"}];export function scanTestFiles(o,e={}){const i=[],n=[],t=[],u=[...new Set([...F,...(e.exclude||[]).map(b)])],l=D(o,e.roots,".");for(;l.length>0;){const c=l.pop();if(c!==void 0){v("discovery.directoriesRead");for(const s of k.readdirSync(c,{withFileTypes:!0})){v("discovery.entriesVisited");const r=y.join(c,s.name);if(s.isSymbolicLink())continue;if(s.isDirectory()){const p=C(y.relative(o,r));if(E(p,u))continue;l.push(r);continue}if(!s.isFile())continue;const a=b(y.relative(o,r));if(!x(a)){a.endsWith(".testkit.ts")&&t.push(a);continue}a.split("/").includes(w)?i.push(a):n.push(a)}}}return{suiteFiles:i.sort((c,s)=>c.localeCompare(s)),legacyFiles:n.sort((c,s)=>c.localeCompare(s)),untypedFiles:t.sort((c,s)=>c.localeCompare(s))}}export function buildDiscoveryProject(o,e,i={}){const n=i.strict!==!1,t=I(o),u=new Map;for(const s of[...e].sort((r,a)=>r.filePath.localeCompare(a.filePath))){const r=s.filePath;if(s.kind==="ambiguous"){const g=[...s.owners].sort((S,T)=>S.localeCompare(T));t.push({code:"ambiguous_test",severity:"error",message:`Ambiguous test file: ${r} -> ${g.join(", ")}`,path:r,groupNames:g});continue}const a=x(r),p=`${s.owner}|${a?.testType??""}`,m=u.get(p)??new Map;u.set(p,m);const f=L(s.relativePath,a),d=f.join("/"),h=a===null?{}:{testType:a.testType},_=m.get(d)??{_suiteKey:d,_suitePath:f,serviceName:s.owner,suite:{files:[],name:"",...h},type:h};m.set(d,_),_.suite.files.push(r)}if(n&&hasDiscoveryErrors(t))throw buildDiscoveryErrorFromDiagnostics(t);const l=[],c={};for(const s of u.values()){const r=j([...s.values()]);for(const{_suiteKey:a,_suitePath:p,serviceName:m,suite:f,type:d}of s.values()){f.name=K(r,a),f.files.sort((h,_)=>h.localeCompare(_));for(const h of f.files)l.push({...d,filePath:h,serviceName:m,suiteName:f.name,suitePath:[...p]});(c[m]??=[]).push(f)}}for(const s of Object.values(c))s?.sort((r,a)=>(r.testType??"").localeCompare(a.testType??"")||r.name.localeCompare(a.name));return{suitesByService:c,files:l.sort((s,r)=>s.serviceName.localeCompare(r.serviceName)||(s.testType??"").localeCompare(r.testType??"")||s.suiteName.localeCompare(r.suiteName)||s.filePath.localeCompare(r.filePath)),diagnostics:t}}export function hasDiscoveryErrors(o=[]){return o.some(e=>e?.severity==="error")}export function buildDiscoveryErrorFromDiagnostics(o=[]){const e=["Filesystem discovery failed for one or more .testkit.ts files."],i=o.filter(t=>t.code==="legacy_path").map(t=>t.path),n=o.filter(t=>t.code==="ambiguous_test");if(i.length>0){e.push(""),e.push("Legacy test files outside __testkit__:");for(const t of i)e.push(`- ${t}`)}if(n.length>0){e.push(""),e.push("Ambiguous test files:");for(const t of n)e.push(`- ${t.path} -> ${t.groupNames.join(", ")}`)}return e.push(""),e.push('Expected test files to live under a "__testkit__" directory within a group root.'),new Error(e.join(`
|
|
2
|
+
`))}function j(o){const e=new Map,i=new Map;for(const n of o){const t=n._suitePath;let u="";for(let l=1;l<=t.length;l+=1){u=t.slice(-l).join("-");const c=e.get(u);if(!c){e.set(u,n._suiteKey);break}if(c===n._suiteKey)break;u=""}u||(u=t.join("-")),i.set(n._suiteKey,u)}if(new Set(i.values()).size!==o.length){const n=new Set;for(const t of o){const u=t._suitePath.join("-");let l=u;for(let c=2;n.has(l);c+=1)l=`${u}-${P(c)}`;n.add(l),i.set(t._suiteKey,l)}}return i}function K(o,e){const i=o.get(e);if(i===void 0)throw new Error(`Discovery suite name was not resolved for "${e}"`);return i}function L(o,e){const i=o.split("/").slice(0,-1);if(e===null)return i.length>0?i:[y.posix.basename(o).replace(N,"")];const n=i.indexOf(w),t=n===-1?[]:[...i.slice(0,n),...i.slice(n+1,n+2)];return t.length>0?t:[y.posix.basename(o,e.suffix)]}function x(o){return $.find(e=>o.endsWith(e.suffix))||null}function b(o){const e=P(o).split(y.sep).join("/");return e==="."||e==="./"?".":e.replace(/^\.\/+/,"").replace(/\/+$/,"")||"."}function I(o){return o.map(e=>({code:"legacy_path",severity:"error",message:`Legacy test file outside __testkit__: ${e}`,path:e}))}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import h from"fs";import f from"path";import{parseDotenv as l}from"../../process/files/dotenv.js";import{resolveServiceCwd as m}from"./paths.js";import{isUnknownArray as d}from"../../kernel/unknown-values.js";import{normalizeOptionalRecord as v}from"../../evidence/artifact-config.js";export{l as parseDotenv};export function inferEnvFiles(e,t,n){const o=v(t,"service config"),a=v(n,"local config"),s=u(o?.envFile,"service.envFile"),p=w(o?.envFiles,"service.envFiles");if(s||p){const r=[];return s&&r.push(s),p&&r.push(...p),r}const i=[],c=u(a?.cwd,"service.local.cwd")??".";return c!=="."&&(i.push(f.posix.join(c,".env.testkit")),i.push(f.posix.join(c,".env"))),i.push(".env.testkit"),i.push(".env"),[...new Set(i)].map(r=>r.split(f.sep).join("/")).filter(r=>h.existsSync(m(e,r)))}export function loadServiceEnv(e,t){const n={};for(const o of t)Object.assign(n,l(m(e,o)));return n}export function withEnvFileValues(e){const t=e.testkit.envFiles??[];return t.length===0?e:{...e,testkit:{...e.testkit,serviceEnv:{...loadServiceEnv(e.productDir,t),...e.testkit.serviceEnv}}}}function u(e,t){if(e!=null){if(typeof e!="string"||e.trim().length===0)throw new Error(`${t} must be a non-empty string`);return e.trim()}}function w(e,t){if(e!=null){if(!d(e))throw new Error(`${t} must be an array of non-empty strings`);return e.map(n=>{if(typeof n!="string"||n.trim().length===0)throw new Error(`${t} must be an array of non-empty strings`);return n.trim()})}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isWorkObserved as M,recordWork as L}from"../../kernel/work-metrics.js";import{isPathWithin as h}from"../../process/files/paths.js";import d from"fs";import E from"path";import{createRequire as A}from"node:module";import{fileURLToPath as O}from"node:url";import{ENGINE_IDS as j,PUBLIC_TEST_TYPES as B,isEngineId as K}from"../../domain/identifiers.js";import{normalizeRuntimeIsolationPolicy as V}from"../../domain/runtime-isolation-contract.js";import{resolveEngineProfile as _,expectedEngineAuthoringModule as W,invalidEngineAuthoringImport as z,requireMatchingHostImport as U}from"../../engines/catalog.js";const G=A(import.meta.url),J=O(import.meta.resolve("typescript"));let H;function a(){return H??=G(J)}const g="@gfdelarue/testkit",X="@gfdelarue/testkit-engine-";export function loadTestFileMetadataMap(e,t={},i=new Map){for(const r of Object.values(t||{}))for(const s of Object.values(r||{}))for(const n of s||[])for(const o of n.files||[])i.has(o)||i.set(o,readTestFileMetadata(e,o));return i}export function readTestFileMetadata(e,t){const i=a(),r=Ee(e,t),s=ke(t);let n;if(M()){const m=d.readFileSync(r);L("metadata.filesRead",1),L("metadata.bytesRead",m.byteLength),n=m.toString("utf8")}else n=d.readFileSync(r,"utf8");const o=i.createSourceFile(r,n,i.ScriptTarget.Latest,!0,i.ScriptKind.TS),u=Ie(o);if(u.length>0){const m=u.map(f=>i.flattenDiagnosticMessageText(f.messageText," ")).join("; ");throw c(t,`TypeScript syntax is invalid: ${m}`)}let l=null,p=null;for(const m of o.statements)if(!(!i.isVariableStatement(m)||!ie(m))){for(const f of m.declarationList.declarations)if(!(!i.isIdentifier(f.name)||f.name.text!=="testkit")){if(l)throw c(t,'exported "testkit" metadata must be declared exactly once');if(!re(m))throw c(t,'exported "testkit" metadata must be const');l=f,p=m}}if(!l||!p)throw c(t,'export const testkit = defineFile({ engine: "..." }) is required');se(o,p,t);const S=Y(l.initializer,t,s);return requireMatchingEngineAuthoringImports(o,t,S),S}function Y(e,t,i){const r=a();if(!e)throw c(t,'exported "testkit" metadata has no value');if(!r.isCallExpression(e))throw c(t,"testkit metadata must use defineFile({ ... })");if(te(e.expression)!=="defineFile")throw c(t,"testkit metadata must call defineFile");if(e.arguments.length!==1)throw c(t,"defineFile metadata must receive exactly one object literal");const s=e.arguments[0];if(!r.isObjectLiteralExpression(s))throw c(t,"defineFile metadata must receive an object literal");return Q(s,t,i)}function Q(e,t,i){const r=a(),s={locks:[],runtimeIsolation:null,skipReason:null};let n=null;const o=new Set;for(const l of e.properties){if(r.isSpreadAssignment(l))throw c(t,"testkit metadata may not contain spread properties");if(!r.isPropertyAssignment(l))throw c(t,"testkit metadata properties must use key: value assignments");const p=b(l.name,t,"testkit metadata");if(!ne(p))throw c(t,`unknown metadata property "${p}"`);if(o.has(p))throw c(t,`duplicate metadata property "${p}"`);if(o.add(p),p==="engine"){n=I(l.initializer,t,'metadata property "engine"');continue}if(p==="locks"){s.locks=Z(l.initializer,t);continue}if(p==="skip"){s.skipReason=P(l.initializer,t);continue}s.runtimeIsolation=ee(l.initializer,t)}if(!n)throw c(t,'a literal "engine" property is required');if(!K(n))throw c(t,`unsupported engine "${n}"; expected one of: ${j.join(", ")}`);let u;try{u=_(i,n)}catch(l){throw c(t,$(l),l)}return{engineId:n,locks:s.locks,profileId:u.id,runtimeIsolation:s.runtimeIsolation,skipReason:s.skipReason}}function Z(e,t){const i=a();if(!i.isArrayLiteralExpression(e))throw c(t,'metadata property "locks" must be an array');const r=[];for(const s of e.elements){if(i.isSpreadElement(s)||i.isOmittedExpression(s))throw c(t,'metadata property "locks" must contain only string literals');r.push(T(s,t,'metadata property "locks" entry'))}return[...new Set(r)].sort()}function P(e,t){const i=a(),r=x(e);if(r!==null)return D(r,t,'metadata property "skip"').trim();if(!i.isObjectLiteralExpression(e))throw c(t,'metadata property "skip" must be a string literal or { reason: string literal }');if(e.properties.length!==1)throw c(t,'metadata property "skip" object must contain exactly one reason property');const s=e.properties[0];if(!i.isPropertyAssignment(s))throw c(t,'metadata property "skip" reason must use a string-literal assignment');if(b(s.name,t,'metadata property "skip"')!=="reason")throw c(t,'metadata property "skip" object only accepts "reason"');return T(s.initializer,t,'metadata property "skip.reason"')}function ee(e,t){const i=I(e,t,'metadata property "runtimeIsolation"');try{return V(i,"defineFile runtimeIsolation")}catch(r){throw c(t,$(r),r)}}function te(e){return a().isIdentifier(e)?e.text:null}function b(e,t,i){const r=a();if(r.isIdentifier(e)||r.isStringLiteral(e))return e.text;throw c(t,`${i} property names must be plain identifiers or string literals`)}function x(e){const t=a();return t.isStringLiteral(e)||t.isNoSubstitutionTemplateLiteral(e)?e.text:null}function I(e,t,i){const r=x(e);if(r===null)throw c(t,`${i} must be a string literal`);return D(r,t,i)}function T(e,t,i){return I(e,t,i).trim()}function D(e,t,i){if(e.trim().length===0)throw c(t,`${i} must not be empty`);return e}function ie(e){const t=a();return(e.modifiers||[]).some(i=>i.kind===t.SyntaxKind.ExportKeyword)}function re(e){const t=a();return(e.declarationList.flags&t.NodeFlags.Const)!==0}function ne(e){return["engine","locks","runtimeIsolation","skip"].includes(e)}function se(e,t,i){const r=a();let s=null,n=0;for(const o of e.statements){if(r.isImportDeclaration(o)){const u=o.importClause;if(!u||u.phaseModifier===r.SyntaxKind.TypeKeyword)continue;u.name?.text==="defineFile"&&(n+=1);const l=u.namedBindings;if(l&&r.isNamespaceImport(l)){l.name.text==="defineFile"&&(n+=1);continue}if(!l||!r.isNamedImports(l))continue;for(const p of l.elements){if(p.isTypeOnly||p.name.text!=="defineFile")continue;if(n+=1,(p.propertyName?.text??p.name.text)==="defineFile"&&r.isStringLiteral(o.moduleSpecifier)&&o.moduleSpecifier.text===g){if(s)throw c(i,`defineFile must have exactly one named value import from "${g}"`);s=o}}continue}n+=Se(o)}if(!s)throw c(i,`defineFile must be a named value import from "${g}"`);if(n!==1)throw c(i,"the imported defineFile binding may not be shadowed or redeclared");if(s.getStart(e)>t.getStart(e))throw c(i,"the defineFile import must precede metadata")}export function requireMatchingEngineAuthoringImports(e,t,i){oe(e,t,i);const r=W(i.profileId);for(const s of collectModuleSpecifiers(e))if(U(t,i,s),!(s===g||s===r||!s.startsWith(`${g}/`)&&!s.startsWith(X)))throw z(t,i,s,r)}function oe(e,t,i){const r=a(),s=N(e),n=o=>{if(ae(o,t,i),ce(o,s,t,i),r.isCallExpression(o)&&F(o,s)){const u=o.arguments.at(0);if(!u||!r.isStringLiteralLike(u)){const l=o.expression.kind===r.SyntaxKind.ImportKeyword?"import()":"require()";throw new Error(`Invalid Testkit authoring in "${t}": ${i.engineId}/${i.profileId} may not use non-literal ${l}; module specifiers must be string literals so engine boundaries can be verified`)}}for(const u of C(o))n(u);r.forEachChild(o,n)};n(e)}function F(e,t){const i=a();return e.expression.kind===i.SyntaxKind.ImportKeyword||i.isIdentifier(e.expression)&&e.expression.text==="require"&&!k(e.expression,t)}function ae(e,t,i){const r=a();if(r.isImportDeclaration(e)){const n=e.importClause?.namedBindings;if(n&&r.isNamedImports(n)&&n.elements.find(u=>!u.isTypeOnly&&(u.propertyName?.text??u.name.text)==="createRequire"))throw y(t,i,"createRequire")}if(r.isPropertyAccessExpression(e)&&e.name.text==="createRequire"||r.isElementAccessExpression(e)&&x(e.argumentExpression)==="createRequire"||r.isBindingElement(e)&&(me(e)==="createRequire"||r.isIdentifier(e.name)&&e.name.text==="createRequire"))throw y(t,i,"createRequire")}function ce(e,t,i,r){const s=a();if(s.isPropertyAccessExpression(e)&&e.name.text==="require"&&q(e.expression,t)||s.isElementAccessExpression(e)&&x(e.argumentExpression)==="require"&&q(e.expression,t))throw y(i,r,e.getText());if(s.isIdentifier(e)&&e.text==="require"&&!k(e,t)&&!ue(e)&&!le(e))throw y(i,r,"global require")}function y(e,t,i){return new Error(`Invalid Testkit authoring in "${e}": ${t.engineId}/${t.profileId} may not alias or indirectly access the module loader through ${i}; use literal import and require specifiers so engine boundaries can be verified`)}function q(e,t){return a().isIdentifier(e)&&(e.text==="globalThis"||e.text==="module")&&!k(e,t)}function ue(e){return a().isCallExpression(e.parent)&&e.parent.expression===e}function le(e){const t=a(),i=e.parent;return pe(e)||t.isPropertyAccessExpression(i)&&i.name===e||t.isPropertyAssignment(i)&&i.name===e||t.isImportSpecifier(i)&&i.propertyName===e||t.isExportSpecifier(i)&&i.parent.parent.moduleSpecifier!==void 0}function pe(e){const t=a(),i=e.parent;return i.name===e&&!t.isShorthandPropertyAssignment(i)&&!t.isExportSpecifier(i)}function me(e){const t=a(),i=e.propertyName;return i&&(t.isIdentifier(i)||t.isStringLiteralLike(i))?i.text:null}function N(e){const t=a(),i=new WeakMap,r=(n,o)=>{let u=i.get(n);u||(u=new Set,i.set(n,u)),v(u,o)},s=n=>{if(t.isImportDeclaration(n))fe(n,e,r);else if(t.isImportEqualsDeclaration(n)&&!n.isTypeOnly)r(e,n.name);else if(t.isVariableDeclaration(n)){const o=n.parent,u=t.isVariableDeclarationList(o)&&(o.flags&t.NodeFlags.BlockScoped)===0?de(n):w(n);r(u,n.name)}else t.isParameter(n)?r(ge(n),n.name):t.isFunctionDeclaration(n)&&n.name?r(w(n),n.name):t.isFunctionExpression(n)&&n.name?r(n,n.name):(t.isClassDeclaration(n)||t.isEnumDeclaration(n)||t.isModuleDeclaration(n))&&n.name&&t.isIdentifier(n.name)?r(w(n),n.name):t.isClassExpression(n)&&n.name?r(n,n.name):t.isCatchClause(n)&&n.variableDeclaration&&r(n,n.variableDeclaration.name);t.forEachChild(n,s)};return s(e),i}function fe(e,t,i){const r=a(),s=e.importClause;if(!s||s.phaseModifier===r.SyntaxKind.TypeKeyword)return;s.name&&i(t,s.name);const n=s.namedBindings;if(n&&r.isNamespaceImport(n))i(t,n.name);else if(n&&r.isNamedImports(n))for(const o of n.elements)o.isTypeOnly||i(t,o.name)}function v(e,t){const i=a();if(i.isIdentifier(t)){e.add(t.text);return}for(const r of t.elements)i.isOmittedExpression(r)||v(e,r.name)}function k(e,t){const i=a();let r=e;for(;;){if(t.get(r)?.has(e.text))return!0;if(i.isSourceFile(r))return!1;r=r.parent}}function w(e){let t=e.parent;for(;;){if(ye(t))return t;t=t.parent}}function de(e){const t=a();let i=e.parent;for(;;){if(t.isFunctionLike(i)||t.isSourceFile(i))return i;i=i.parent}}function ge(e){const t=a();let i=e.parent;for(;;){if(t.isFunctionLike(i)||t.isSourceFile(i))return i;i=i.parent}}function ye(e){const t=a();return t.isSourceFile(e)||t.isBlock(e)||t.isCaseBlock(e)||t.isCatchClause(e)||t.isForStatement(e)||t.isForInStatement(e)||t.isForOfStatement(e)||t.isFunctionLike(e)||t.isClassStaticBlockDeclaration(e)}export function collectModuleSpecifiers(e){const t=a(),i=new Set,r=N(e),s=n=>{const o=xe(n,r);o&&i.add(o);for(const u of C(n))s(u);t.forEachChild(n,s)};return s(e),i}function C(e){return e.jsDoc??[]}function xe(e,t){const i=a();if(i.isJSDocImportTag(e)&&i.isStringLiteralLike(e.moduleSpecifier)||(i.isImportDeclaration(e)||i.isExportDeclaration(e))&&e.moduleSpecifier&&i.isStringLiteralLike(e.moduleSpecifier))return e.moduleSpecifier.text;if(i.isImportEqualsDeclaration(e)&&i.isExternalModuleReference(e.moduleReference)&&i.isStringLiteralLike(e.moduleReference.expression))return e.moduleReference.expression.text;if(i.isImportTypeNode(e)){const s=e.argument;if(i.isLiteralTypeNode(s)&&i.isStringLiteralLike(s.literal))return s.literal.text}if(!i.isCallExpression(e)||!F(e,t))return null;const r=e.arguments[0];return i.isStringLiteralLike(r)?r.text:null}function Se(e){const t=a();return t.isVariableStatement(e)?e.declarationList.declarations.reduce((i,r)=>i+R(r.name,"defineFile"),0):(t.isClassDeclaration(e)||t.isEnumDeclaration(e)||t.isFunctionDeclaration(e))&&e.name?.text==="defineFile"?1:0}function R(e,t){const i=a();return i.isIdentifier(e)?e.text===t?1:0:e.elements.reduce((r,s)=>i.isOmittedExpression(s)?r:r+R(s.name,t),0)}function Ee(e,t){const i=E.resolve(e);if(E.isAbsolute(t))throw new Error(`Test file metadata path must be product-relative: ${t}`);const r=E.resolve(i,t);if(!h(i,r))throw new Error(`Test file metadata path escapes the product root: ${t}`);if(!d.existsSync(r))throw new Error(`Test file metadata source does not exist: ${t}`);const s=d.realpathSync(i),n=d.realpathSync(r);if(!h(s,n))throw new Error(`Test file metadata path resolves outside the product root: ${t}`);return n}function Ie(e){return e.parseDiagnostics??[]}function ke(e){const t=B.find(i=>e.endsWith(`.${i}.testkit.ts`));if(t)return t;throw new Error(`Cannot read Testkit file metadata from noncanonical path: ${e}`)}function c(e,t,i){return new Error(`Invalid testkit metadata in "${e}": ${t}.`,{cause:i})}function $(e){return e instanceof Error?e.message.replace(/\.$/u,""):String(e)}
|
|
1
|
+
import{isWorkObserved as $,recordWork as L}from"../../kernel/work-metrics.js";import{retiredEngineMessage as A}from"../../domain/retired-test-types.js";import{isPathWithin as h}from"../../process/files/paths.js";import g from"fs";import S from"path";import{createRequire as B}from"node:module";import{fileURLToPath as O}from"node:url";import{ENGINE_IDS as j,PUBLIC_TEST_TYPES as K,isEngineId as V}from"../../domain/identifiers.js";import{normalizeRuntimeIsolationPolicy as W}from"../../domain/runtime-isolation-contract.js";import{resolveEngineProfile as _,allowsEngineAuthoringImport as z,expectedEngineAuthoringModule as U,invalidEngineAuthoringImport as G,requireMatchingEngineImport as J}from"../../engines/catalog.js";const Y=B(import.meta.url),H=O(import.meta.resolve("typescript"));let Q;function a(){return Q??=Y(H)}const I="@gfdelarue/testkit";export function loadTestFileMetadataMap(e,t={},i=new Map){for(const r of Object.values(t||{}).flatMap(s=>s??[]))for(const s of r.files||[])i.has(s)||i.set(s,readTestFileMetadata(e,s));return i}export function readTestFileMetadata(e,t){const i=K.find(f=>t.endsWith(`.${f}.testkit.ts`));if(i===void 0)return{engineId:"node-vitest",locks:[],profileId:"node-vitest",runtimeIsolation:null,skipReason:null};const r=a(),s=ke(e,t);let n;if($()){const f=g.readFileSync(s);L("metadata.filesRead",1),L("metadata.bytesRead",f.byteLength),n=f.toString("utf8")}else n=g.readFileSync(s,"utf8");const o=r.createSourceFile(s,n,r.ScriptTarget.Latest,!0,r.ScriptKind.TS),l=Ee(o);if(l.length>0){const f=l.map(d=>r.flattenDiagnosticMessageText(d.messageText," ")).join("; ");throw c(t,`TypeScript syntax is invalid: ${f}`)}let p=null,u=null;for(const f of o.statements)if(!(!r.isVariableStatement(f)||!re(f))){for(const d of f.declarationList.declarations)if(!(!r.isIdentifier(d.name)||d.name.text!=="testkit")){if(p)throw c(t,'exported "testkit" metadata must be declared exactly once');if(!ne(f))throw c(t,'exported "testkit" metadata must be const');p=d,u=f}}if(!p||!u)throw c(t,'export const testkit = defineFile({ engine: "..." }) is required');oe(o,u,t);const m=X(p.initializer,t,i);return requireMatchingEngineAuthoringImports(o,t,m),m}function X(e,t,i){const r=a();if(!e)throw c(t,'exported "testkit" metadata has no value');if(!r.isCallExpression(e))throw c(t,"testkit metadata must use defineFile({ ... })");if(ie(e.expression)!=="defineFile")throw c(t,"testkit metadata must call defineFile");if(e.arguments.length!==1)throw c(t,"defineFile metadata must receive exactly one object literal");const s=e.arguments[0];if(!r.isObjectLiteralExpression(s))throw c(t,"defineFile metadata must receive an object literal");return Z(s,t,i)}function Z(e,t,i){const r=a(),s={locks:[],runtimeIsolation:null,skipReason:null};let n=null;const o=new Set;for(const u of e.properties){if(r.isSpreadAssignment(u))throw c(t,"testkit metadata may not contain spread properties");if(!r.isPropertyAssignment(u))throw c(t,"testkit metadata properties must use key: value assignments");const m=b(u.name,t,"testkit metadata");if(!se(m))throw c(t,`unknown metadata property "${m}"`);if(o.has(m))throw c(t,`duplicate metadata property "${m}"`);if(o.add(m),m==="engine"){n=k(u.initializer,t,'metadata property "engine"');continue}if(m==="locks"){s.locks=P(u.initializer,t);continue}if(m==="skip"){s.skipReason=ee(u.initializer,t);continue}s.runtimeIsolation=te(u.initializer,t)}if(!n)throw c(t,'a literal "engine" property is required');const l=A(n);if(l!==null)throw c(t,l);if(!V(n))throw c(t,`unsupported engine "${n}"; expected one of: ${j.join(", ")}`);let p;try{p=_(i,n)}catch(u){throw c(t,R(u),u)}return{engineId:n,locks:s.locks,profileId:p.id,runtimeIsolation:s.runtimeIsolation,skipReason:s.skipReason}}function P(e,t){const i=a();if(!i.isArrayLiteralExpression(e))throw c(t,'metadata property "locks" must be an array');const r=[];for(const s of e.elements){if(i.isSpreadElement(s)||i.isOmittedExpression(s))throw c(t,'metadata property "locks" must contain only string literals');r.push(D(s,t,'metadata property "locks" entry'))}return[...new Set(r)].sort()}function ee(e,t){const i=a(),r=x(e);if(r!==null)return F(r,t,'metadata property "skip"').trim();if(!i.isObjectLiteralExpression(e))throw c(t,'metadata property "skip" must be a string literal or { reason: string literal }');if(e.properties.length!==1)throw c(t,'metadata property "skip" object must contain exactly one reason property');const s=e.properties[0];if(!i.isPropertyAssignment(s))throw c(t,'metadata property "skip" reason must use a string-literal assignment');if(b(s.name,t,'metadata property "skip"')!=="reason")throw c(t,'metadata property "skip" object only accepts "reason"');return D(s.initializer,t,'metadata property "skip.reason"')}function te(e,t){const i=k(e,t,'metadata property "runtimeIsolation"');try{return W(i,"defineFile runtimeIsolation")}catch(r){throw c(t,R(r),r)}}function ie(e){return a().isIdentifier(e)?e.text:null}function b(e,t,i){const r=a();if(r.isIdentifier(e)||r.isStringLiteral(e))return e.text;throw c(t,`${i} property names must be plain identifiers or string literals`)}function x(e){const t=a();return t.isStringLiteral(e)||t.isNoSubstitutionTemplateLiteral(e)?e.text:null}function k(e,t,i){const r=x(e);if(r===null)throw c(t,`${i} must be a string literal`);return F(r,t,i)}function D(e,t,i){return k(e,t,i).trim()}function F(e,t,i){if(e.trim().length===0)throw c(t,`${i} must not be empty`);return e}function re(e){const t=a();return(e.modifiers||[]).some(i=>i.kind===t.SyntaxKind.ExportKeyword)}function ne(e){const t=a();return(e.declarationList.flags&t.NodeFlags.Const)!==0}function se(e){return["engine","locks","runtimeIsolation","skip"].includes(e)}function oe(e,t,i){const r=a();let s=null,n=0;for(const o of e.statements){if(r.isImportDeclaration(o)){const l=o.importClause;if(!l||l.phaseModifier===r.SyntaxKind.TypeKeyword)continue;l.name?.text==="defineFile"&&(n+=1);const p=l.namedBindings;if(p&&r.isNamespaceImport(p)){p.name.text==="defineFile"&&(n+=1);continue}if(!p||!r.isNamedImports(p))continue;for(const u of p.elements){if(u.isTypeOnly||u.name.text!=="defineFile")continue;if(n+=1,(u.propertyName?.text??u.name.text)==="defineFile"&&r.isStringLiteral(o.moduleSpecifier)&&o.moduleSpecifier.text===I){if(s)throw c(i,`defineFile must have exactly one named value import from "${I}"`);s=o}}continue}n+=Ie(o)}if(!s)throw c(i,`defineFile must be a named value import from "${I}"`);if(n!==1)throw c(i,"the imported defineFile binding may not be shadowed or redeclared");if(s.getStart(e)>t.getStart(e))throw c(i,"the defineFile import must precede metadata")}export function requireMatchingEngineAuthoringImports(e,t,i){ae(e,t,i);const r=U(i.profileId);for(const s of collectModuleSpecifiers(e))if(J(t,i,s),!z(r,s))throw G(t,i,s,r)}function ae(e,t,i){const r=a(),s=q(e),n=o=>{if(ce(o,t,i),le(o,s,t,i),r.isCallExpression(o)&&T(o,s)){const l=o.arguments.at(0);if(!l||!r.isStringLiteralLike(l)){const p=o.expression.kind===r.SyntaxKind.ImportKeyword?"import()":"require()";throw new Error(`Invalid Testkit authoring in "${t}": ${i.engineId}/${i.profileId} may not use non-literal ${p}; module specifiers must be string literals so engine boundaries can be verified`)}}for(const l of C(o))n(l);r.forEachChild(o,n)};n(e)}function T(e,t){const i=a();return e.expression.kind===i.SyntaxKind.ImportKeyword||i.isIdentifier(e.expression)&&e.expression.text==="require"&&!E(e.expression,t)}function ce(e,t,i){const r=a();if(r.isImportDeclaration(e)){const n=e.importClause?.namedBindings;if(n&&r.isNamedImports(n)&&n.elements.find(l=>!l.isTypeOnly&&(l.propertyName?.text??l.name.text)==="createRequire"))throw y(t,i,"createRequire")}if(r.isPropertyAccessExpression(e)&&e.name.text==="createRequire"||r.isElementAccessExpression(e)&&x(e.argumentExpression)==="createRequire"||r.isBindingElement(e)&&(fe(e)==="createRequire"||r.isIdentifier(e.name)&&e.name.text==="createRequire"))throw y(t,i,"createRequire")}function le(e,t,i,r){const s=a();if(s.isPropertyAccessExpression(e)&&e.name.text==="require"&&v(e.expression,t)||s.isElementAccessExpression(e)&&x(e.argumentExpression)==="require"&&v(e.expression,t))throw y(i,r,e.getText());if(s.isIdentifier(e)&&e.text==="require"&&!E(e,t)&&!ue(e)&&!pe(e))throw y(i,r,"global require")}function y(e,t,i){return new Error(`Invalid Testkit authoring in "${e}": ${t.engineId}/${t.profileId} may not alias or indirectly access the module loader through ${i}; use literal import and require specifiers so engine boundaries can be verified`)}function v(e,t){return a().isIdentifier(e)&&(e.text==="globalThis"||e.text==="module")&&!E(e,t)}function ue(e){return a().isCallExpression(e.parent)&&e.parent.expression===e}function pe(e){const t=a(),i=e.parent;return me(e)||t.isPropertyAccessExpression(i)&&i.name===e||t.isPropertyAssignment(i)&&i.name===e||t.isImportSpecifier(i)&&i.propertyName===e||t.isExportSpecifier(i)&&i.parent.parent.moduleSpecifier!==void 0}function me(e){const t=a(),i=e.parent;return i.name===e&&!t.isShorthandPropertyAssignment(i)&&!t.isExportSpecifier(i)}function fe(e){const t=a(),i=e.propertyName;return i&&(t.isIdentifier(i)||t.isStringLiteralLike(i))?i.text:null}function q(e){const t=a(),i=new WeakMap,r=(n,o)=>{let l=i.get(n);l||(l=new Set,i.set(n,l)),N(l,o)},s=n=>{if(t.isImportDeclaration(n))de(n,e,r);else if(t.isImportEqualsDeclaration(n)&&!n.isTypeOnly)r(e,n.name);else if(t.isVariableDeclaration(n)){const o=n.parent,l=t.isVariableDeclarationList(o)&&(o.flags&t.NodeFlags.BlockScoped)===0?ge(n):w(n);r(l,n.name)}else t.isParameter(n)?r(ye(n),n.name):t.isFunctionDeclaration(n)&&n.name?r(w(n),n.name):t.isFunctionExpression(n)&&n.name?r(n,n.name):(t.isClassDeclaration(n)||t.isEnumDeclaration(n)||t.isModuleDeclaration(n))&&n.name&&t.isIdentifier(n.name)?r(w(n),n.name):t.isClassExpression(n)&&n.name?r(n,n.name):t.isCatchClause(n)&&n.variableDeclaration&&r(n,n.variableDeclaration.name);t.forEachChild(n,s)};return s(e),i}function de(e,t,i){const r=a(),s=e.importClause;if(!s||s.phaseModifier===r.SyntaxKind.TypeKeyword)return;s.name&&i(t,s.name);const n=s.namedBindings;if(n&&r.isNamespaceImport(n))i(t,n.name);else if(n&&r.isNamedImports(n))for(const o of n.elements)o.isTypeOnly||i(t,o.name)}function N(e,t){const i=a();if(i.isIdentifier(t)){e.add(t.text);return}for(const r of t.elements)i.isOmittedExpression(r)||N(e,r.name)}function E(e,t){const i=a();let r=e;for(;;){if(t.get(r)?.has(e.text))return!0;if(i.isSourceFile(r))return!1;r=r.parent}}function w(e){let t=e.parent;for(;;){if(xe(t))return t;t=t.parent}}function ge(e){const t=a();let i=e.parent;for(;;){if(t.isFunctionLike(i)||t.isSourceFile(i))return i;i=i.parent}}function ye(e){const t=a();let i=e.parent;for(;;){if(t.isFunctionLike(i)||t.isSourceFile(i))return i;i=i.parent}}function xe(e){const t=a();return t.isSourceFile(e)||t.isBlock(e)||t.isCaseBlock(e)||t.isCatchClause(e)||t.isForStatement(e)||t.isForInStatement(e)||t.isForOfStatement(e)||t.isFunctionLike(e)||t.isClassStaticBlockDeclaration(e)}export function collectModuleSpecifiers(e){const t=a(),i=new Set,r=q(e),s=n=>{const o=Se(n,r);o&&i.add(o);for(const l of C(n))s(l);t.forEachChild(n,s)};return s(e),i}function C(e){return e.jsDoc??[]}function Se(e,t){const i=a();if(i.isJSDocImportTag(e)&&i.isStringLiteralLike(e.moduleSpecifier)||(i.isImportDeclaration(e)||i.isExportDeclaration(e))&&e.moduleSpecifier&&i.isStringLiteralLike(e.moduleSpecifier))return e.moduleSpecifier.text;if(i.isImportEqualsDeclaration(e)&&i.isExternalModuleReference(e.moduleReference)&&i.isStringLiteralLike(e.moduleReference.expression))return e.moduleReference.expression.text;if(i.isImportTypeNode(e)){const s=e.argument;if(i.isLiteralTypeNode(s)&&i.isStringLiteralLike(s.literal))return s.literal.text}if(!i.isCallExpression(e)||!T(e,t))return null;const r=e.arguments[0];return i.isStringLiteralLike(r)?r.text:null}function Ie(e){const t=a();return t.isVariableStatement(e)?e.declarationList.declarations.reduce((i,r)=>i+M(r.name,"defineFile"),0):(t.isClassDeclaration(e)||t.isEnumDeclaration(e)||t.isFunctionDeclaration(e))&&e.name?.text==="defineFile"?1:0}function M(e,t){const i=a();return i.isIdentifier(e)?e.text===t?1:0:e.elements.reduce((r,s)=>i.isOmittedExpression(s)?r:r+M(s.name,t),0)}function ke(e,t){const i=S.resolve(e);if(S.isAbsolute(t))throw new Error(`Test file metadata path must be product-relative: ${t}`);const r=S.resolve(i,t);if(!h(i,r))throw new Error(`Test file metadata path escapes the product root: ${t}`);if(!g.existsSync(r))throw new Error(`Test file metadata source does not exist: ${t}`);const s=g.realpathSync(i),n=g.realpathSync(r);if(!h(s,n))throw new Error(`Test file metadata path resolves outside the product root: ${t}`);return n}function Ee(e){return e.parseDiagnostics??[]}function c(e,t,i){return new Error(`Invalid testkit metadata in "${e}": ${t}.`,{cause:i})}function R(e){return e instanceof Error?e.message.replace(/\.$/u,""):String(e)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import l from"node:path";import{requireServiceName as S}from"../../domain/service-name.js";import{errorMessage as y}from"../../kernel/error-serialization.js";import{isUnknownRecord as v,readDynamicProperty as d}from"../../kernel/unknown-values.js";import{normalizeDiscoveryConfig as b}from"./decode-discovery.js";import{DEFAULT_DISCOVERY_EXCLUDES as C,shouldExcludeDiscoveryPath as w}from"./path-policy.js";const j=String;export const ROOT_GROUP="root",LEGACY_OWNERSHIP_NOTICE="testkit.config.ts has services but no groups, so each service owns the tests under its directory as a group of the same name. Legacy ownership will be removed; declare groups with roots and uses instead.";export function resolveGroups(e,r){const t=[],s=m(d(e,"discovery"),null,t),n=L(e,t),o=e&&Object.hasOwn(e,"groups")?D(d(e,"groups"),n,t):O(n,t);e&&Object.hasOwn(e,"groups")&&t.push(...z(n,o.groups));const u=(s.exclude??[]).map(f),p=[...C,...u],a=r.map(c=>P(c,o.rules,c.kind==="typed"?p:u)),i=new Set(o.groups.filter(c=>c.source==="services").map(c=>c.name));return{assignments:a,groups:[...o.groups,{name:ROOT_GROUP,roots:["."],source:"implicit",uses:[]}],notice:a.some(c=>c.status==="owned"&&i.has(c.group))?LEGACY_OWNERSHIP_NOTICE:null,problems:t}}export function readDiscoveryScan(e){return m(d(e,"discovery"),null,[])}export function repoDiscoveryProblem(e){const r=[];return m(d(e,"discovery"),null,r),r[0]??null}export function legacyServiceProblem(e,r){const t=[];return O({[e]:r},t),t[0]??null}function P(e,r,t){const s=I(e.path);if(w(s,t))return{path:s,status:"excluded"};const n=r.filter(i=>(e.kind==="typed"||!i.typedOnly)&&(i.prefix===null||x(s,i.prefix))),o=n.filter(i=>!w(s,i.exclude));if(n.length>0&&o.length===0)return{path:s,status:"excluded"};if(o.length===0)return{group:ROOT_GROUP,path:s,relativePath:s,status:"owned"};const u=Math.max(...o.map(i=>i.depth)),p=o.filter(i=>i.depth===u),a=[...new Set(p.map(i=>i.group))].sort((i,c)=>i.localeCompare(c));return a.length>1?{groups:a,path:s,status:"ambiguous"}:{group:a[0],path:s,relativePath:R(p[0],s),status:"owned"}}function D(e,r,t){const s={groups:[],rules:[]};if(!v(e))return t.push("testkit.config.ts groups must be an object"),s;for(const[n,o]of Object.entries(e)){const u=`groups.${n}`;if(n===ROOT_GROUP){t.push(`${u} is reserved for the implicit group that owns files no other group claims; rename it`);continue}try{S(n,`Group name "${n}"`)}catch(i){t.push(y(i));continue}if(!v(o)){t.push(`${u} must be an object with roots`);continue}const p=$(o.roots,`${u}.roots`,!0,t),a=$(o.exclude,`${u}.exclude`,!1,t);s.groups.push({name:n,roots:p,source:"groups",uses:A(o.uses,u,r,t)});for(const i of p)s.rules.push({depth:i==="."?0:i.split("/").length,exclude:a,group:n,legacyCwd:null,prefix:i==="."?null:i,typedOnly:!1})}return s}const E=["skip","requirements","runtimeIsolation"];function z(e,r){return Object.entries(e).flatMap(([t,s])=>E.filter(n=>d(s,n)!==void 0).map(n=>{const o=r.find(u=>u.uses.includes(t))?.name??t;return`services.${t}.${n} applies to tests, and services own no tests when groups is set; move it to groups.${o}.${n}`}))}function $(e,r,t,s){if(e===void 0&&!t)return[];if(!Array.isArray(e)||t&&e.length===0)return s.push(`${r} must be ${t?"a non-empty array":"an array"} of repo-relative paths`),[];const n=e,o=new Set;for(const u of n){const p=k(u);p===null?s.push(`${r} entry ${JSON.stringify(u)} must be a relative path inside the product directory`):o.add(p)}return[...o]}function A(e,r,t,s){if(e===void 0)return[];if(!_(e))return s.push(`${r}.uses must be an array of service names`),[];const n=[];for(const o of new Set(e))Object.hasOwn(t,o)?n.push(o):s.push(`${r}.uses names "${o}", which is not a service; declare services.${o} or remove it from ${r}.uses`);return n}function O(e,r){const t={groups:[],rules:[]};for(const[s,n]of Object.entries(e)){if(s===ROOT_GROUP){r.push("services.root is reserved for the implicit group that owns files no other group claims; rename the service");continue}const o=m(d(n,"discovery"),s,r),u=G(n),p=o.roots&&o.roots.length>0?o.roots:["."],a=(o.exclude??[]).map(c=>f(u==="."?c:l.posix.join(u,c))),i=p.map(c=>{const g=f(c),h=u==="."?g:g==="."?u:f(l.posix.join(u,g));return{depth:h==="."?0:h.split("/").filter(Boolean).length,exclude:a,group:s,legacyCwd:u==="."?null:u,prefix:h==="."?null:h,typedOnly:!0}});t.rules.push(...i),t.groups.push({name:s,roots:[...new Set(i.map(c=>c.prefix??"."))],source:"services",uses:[s]})}return t}function G(e){return f(j(d(d(e,"local"),"cwd")||"."))}function L(e,r){const t=d(e,"services");return t==null?{}:v(t)?t:(r.push("testkit.config.ts services must be an object"),{})}function m(e,r,t){try{return b(e,{allowRoots:!0})}catch(s){return t.push(r===null?y(s):`Service "${r}" has invalid discovery config: ${y(s)}`),{}}}function R(e,r){return e.prefix!==null&&x(r,e.prefix)?l.posix.relative(e.prefix,r):e.legacyCwd!==null&&x(r,e.legacyCwd)?l.posix.relative(e.legacyCwd,r):r}function _(e){return Array.isArray(e)&&e.every(r=>typeof r=="string")}function x(e,r){return e===r||e.startsWith(`${r}/`)}function k(e){if(typeof e!="string")return null;const r=e.trim(),t=r.replaceAll("\\","/");if(t===""||l.posix.isAbsolute(t)||l.win32.isAbsolute(r))return null;const s=l.posix.normalize(t).replace(/\/+$/u,"")||".";return s===".."||s.startsWith("../")?null:s}function I(e){return l.posix.normalize(e.split(l.sep).join("/")).replace(/\/+$/u,"")}function f(e){const r=e.split(l.sep).join("/");return r==="."||r==="./"?".":r.replace(/^\.\/+/u,"").replace(/\/+$/u,"")||"."}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export{loadConfigContext,loadConfigs,parseDotenv,resolveProductDir,resolveServiceCwd}from"./load.js";export{discoverTests,loadDiscoveredConfigContext,loadDiscoveryContext,fileDisplayName,formatDisplayName,testTypeContract}from"./discover-tests.js";export{findConfigFile,loadTestkitConfig}from"./config-loader.js";export{materializeDatabaseConfig}from"./database-materialization.js";export{detectNextApp}from"./runtime.js";export{DEFAULT_RUNTIME_ISOLATION_POLICY
|
|
1
|
+
export{loadConfigContext,loadConfigs,parseDotenv,resolveProductDir,resolveServiceCwd}from"./load.js";export{discoverTests,loadDiscoveredConfigContext,loadDiscoveryContext,fileDisplayName,formatDisplayName,testTypeContract}from"./discover-tests.js";export{findConfigFile,loadTestkitConfig}from"./config-loader.js";export{materializeDatabaseConfig}from"./database-materialization.js";export{detectNextApp}from"./runtime.js";export{DEFAULT_RUNTIME_ISOLATION_POLICY}from"./runtime-isolation.js";export{collectModuleSpecifiers,requireMatchingEngineAuthoringImports}from"./file-metadata.js";export{hasDiscoveryErrors,buildDiscoveryErrorFromDiagnostics}from"./discovery.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{selectDiscoveredSuites as J,discoveredRuleSuites as Q}from"./test-selection.js";import V from"path";import{isUnknownRecord as w}from"../../kernel/unknown-values.js";import{buildEngineConfigurations as W}from"../../engines/catalog.js";import{isPublicTestType as X}from"../../domain/identifiers.js";import{discoverProject as Y}from"./discovery.js";import{loadTestkitConfig as Z}from"./config-loader.js";import{normalizeToolchainRegistry as N}from"../../toolchains/index.js";import{loadTestFileMetadataMap as ee}from"./file-metadata.js";import{mergeDiscoveryConfigs as re}from"./path-policy.js";import{normalizeDiscoveryConfig as I}from"./decode-discovery.js";import{normalizeFingerprintPolicy as te}from"../../repo/fingerprint-policy.js";import{normalizeDatabaseConfig as oe}from"./database.js";import{inferEnvFiles as ie,loadServiceEnv as ne,parseDotenv as se}from"./env.js";import{normalizeRuntimeIsolationConfig as ce}from"./runtime-isolation.js";import{resolveProductDir as U,resolveServiceCwd as ae}from"./paths.js";import{normalizeRepoExecution as fe,normalizeRuntimeConfig as le}from"./runtime.js";import{normalizeServiceRequirements as de,normalizeSkipConfig as ue}from"./skip-config.js";import{normalizeArtifactArchiveConfig as pe}from"../../evidence/index.js";import{validateConfigCoverage as me,validateServiceConfig as ge}from"./validation.js";import{readProperty as n}from"./values.js";import{assertPortableServiceNameSet as we,requireServiceName as ye}from"../../domain/service-name.js";import{resolveEngineProfile as he}from"../../engines/catalog.js";const k=["65533","65534"],be=/\{(?:baseUrl|readyUrl|publicBaseUrl|privateBaseUrl|serviceContextUrl)(?::[^}]+)?\}/gu;export{se as parseDotenv,U as resolveProductDir,ae as resolveServiceCwd};export async function loadConfigContext(e={}){const r=U(process.cwd(),e.dir),t=e.configContext||await Z(r,{importCacheSalt:e.configImportCacheSalt??""}),{config:o,configFile:i}=xe(t),c=fe(ke(n(o,"execution"))),f=pe(n(o,"artifacts")),l=N(n(o,"toolchains")),a=te(n(o,"fingerprints")),p=I(n(o,"discovery"),{allowRoots:!0}),d=Ce(n(o,"services")),u=e.preparedDiscovery?.project??Y(r,je(d),{...e.discoveryOptions||{},discovery:p}),v=e.testSelection?J(u.suitesByService,e.testSelection):u.suitesByService,y=ee(r,v,e.preparedDiscovery?.fileMetadataByPath),s=Se(v,y),h=new Set([...Object.keys(d),...Object.keys(s)]),m=[];for(const g of[...h].sort((E,$)=>E.localeCompare($)))m.push(await $e({name:g,productDir:r,config:o,configFile:i,execution:c,discovery:p,artifacts:f,toolchains:l,fingerprints:a,explicitService:d[g],suites:s[g]||{},discoveredSuites:u.suitesByService[g]||{},fileMetadataByPath:y}));return me(m),{productDir:r,config:o,configFile:i,execution:c,toolchains:l,fingerprints:a,explicitServices:d,discovery:u,configs:m}}function Se(e,r){return Object.fromEntries(Object.entries(e).map(([t,o])=>[t,ve(t,o||{},r)]))}function ve(e,r,t){const o={};for(const[i,c]of Object.entries(r)){if(!X(i))throw new Error(`Discovered service "${e}" contains unknown test type "${i}"`);o[i]=c.map(f=>{const l=f.files[0];if(!l)throw new Error(`Discovered suite ${e}/${i}:${f.name} contains no files`);const a=P(t,l),p=he(i,a.engineId);if(p.id!==a.profileId)throw new Error(`Discovered file ${l} resolved conflicting engine profile ${a.profileId}; expected ${p.id}`);for(const d of f.files.slice(1)){const u=P(t,d);if(u.engineId!==a.engineId||u.profileId!==a.profileId)throw new Error(`Discovered suite ${e}/${i}:${f.name} mixes engine profiles ${a.engineId}/${a.profileId} and ${u.engineId}/${u.profileId}`)}return{...f,testType:i,engineId:a.engineId,profileId:a.profileId}})}return o}function P(e,r){const t=e.get(r);if(!t)throw new Error(`Missing validated testkit metadata for discovered file: ${r}`);return t}export async function loadConfigs(e={}){const r=await loadConfigContext(e),{configs:t}=r,o=e.service?t.filter(i=>i.name===e.service):t;if(e.service&&o.length===0){const i=t.map(c=>c.name).join(", ");throw new Error(`Service "${e.service}" not found. Available: ${i}`)}return o}async function $e({name:e,productDir:r,config:t,configFile:o,execution:i,discovery:c,artifacts:f,toolchains:l,fingerprints:a,explicitService:p,suites:d,discoveredSuites:u,fileMetadataByPath:v}){const y=await W(t,new Set(Object.values(d).flatMap(b=>b.map(C=>C.engineId)))),s=p??{},h=Object.hasOwn(s,"local")?M(n(s,"local"),e):void 0,m=p===void 0?[]:ie(r,s,h),g={...ne(r,m),...A(n(s,"env"),`Service "${e}" env`)},E=re(c,L(n(s,"discovery"),e));if(n(s,"migrate")||n(s,"seed"))throw new Error(`Service "${e}" uses removed migrate/seed hooks. Move template lifecycle to database.template.{migrate,seed,verify}.`);const $=Oe(s,e),x=le(n(s,"runtime"),e,l),O=Q(u),q=ue(n(s,"skip"),{name:e,suites:O}),_=de(n(s,"requirements"),{name:e,suites:O}),K=ce(n(s,"runtimeIsolation"),{name:e,suites:O}),G=new Set(Object.values(d).flatMap(b=>b.flatMap(C=>C.files))),H=new Map([...v.entries()].filter(([b])=>G.has(b))),z=ze(n(s,"dependsOn"),`Service "${e}" dependsOn`),T=S(n(s,"databaseFrom"),`Service "${e}" databaseFrom`);return ge({name:e,local:h,database:$,databaseFrom:T,runtime:x,dependsOn:z,suites:d,productDir:r}),{name:e,productDir:r,configFile:o,...y===void 0?{}:{engineConfigurations:y},stateDir:V.join(r,".testkit",e),artifacts:f,suites:d,testkit:{execution:i,dependsOn:z,discovery:E,database:$,databaseFrom:T,envFiles:m,requirements:_,serviceEnv:g,skip:q,runtime:x,runtimeIsolation:K,ui:n(t,"ui")||null,fingerprints:a,fileMetadataByPath:H,local:h}}}function M(e,r){if(e===!1)return;if(!w(e))throw new Error(`Service "${r}" local must be an object or false`);if(Object.prototype.hasOwnProperty.call(e,"port"))throw new Error(`Service "${r}" sets local.port. Testkit assigns every service a free port from the OS. Delete the line, or the port option of app.node or app.next, and use {port} in start, baseUrl, and readyUrl.`);const t=B(e.baseUrl,`Service "${r}" local.baseUrl`);F(t,`Service "${r}" local.baseUrl`);const o=new RegExp(`\\{port(?::${Ee(r)})?\\}`,"gu");if(!k.every(l=>D(t,o,l,!1)===l))throw new Error(`Service "${r}" local.baseUrl must use {port} for its port, for example http://127.0.0.1:{port}. Testkit assigns every service a free port from the OS.`);const i=B(e.start,`Service "${r}" local.start`),{shutdownTimeoutMs:c,...f}=e;return{...f,...Ie(c,r),baseUrl:t,start:i,cwd:S(e.cwd,`Service "${r}" local.cwd`)||".",env:A(e.env,`Service "${r}" local.env`),...Te(e.readyTimeoutMs,`Service "${r}" local.readyTimeoutMs`),...Ue(e.readyUrl,r)}}function j(e){return e.replace(/[\t\n\r]/gu,"").trim()}function R(e){return/^[a-z][a-z0-9+.-]*:[\\/]{2}(?![\\/])([^/\\?#]*)/iu.exec(j(e))?.[1]}function D(e,r,t,o){const i=j(e).replace(r,t).replace(be,o?`http://template.invalid:${t}`:"http://template.invalid").replace(/\{[^}]+\}/gu,"template");try{return new URL(i).port}catch{return}}function Ee(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")}function F(e,r){if(/^[a-z][a-z0-9+.-]*:/iu.test(j(e))&&R(e)===void 0)throw new Error(`${r} must be an absolute URL with a host, for example http://127.0.0.1:{port}/health.`);const[t,o]=k.map(c=>D(e,/\{port(?::[^}]+)?\}/gu,c,!0)),i=/:(\d+)$/u.exec(R(e)??"")?.[1]??(t&&t===o?t:void 0);if(i!==void 0)throw new Error(`${r} has a literal port (${i}). Testkit assigns every service a free port from the OS. Replace the port with {port}.`)}function Oe(e,r){const t=oe(e,r);if(!t)return;const o=S(n(t,"image"),`Service "${r}" database.image`),i=S(n(t,"password"),`Service "${r}" database.password`),c=S(n(t,"user"),`Service "${r}" database.user`);return{...t,...Object.prototype.hasOwnProperty.call(t,"image")?{image:o}:{},...Object.prototype.hasOwnProperty.call(t,"password")?{password:i}:{},...Object.prototype.hasOwnProperty.call(t,"user")?{user:c}:{}}}function L(e,r){try{return I(e,{allowRoots:!0})}catch(t){const o=t instanceof Error?t.message:String(t);throw new Error(`Service "${r}" has invalid discovery config: ${o}`,{cause:t})}}function Ce(e){if(e==null)return{};if(!w(e))throw new Error("testkit.config.ts services must be an object");const r=Object.fromEntries(Object.entries(e).map(([t,o])=>{if(ye(t,`Service name "${t}"`),o==null)return[t,{}];if(!w(o))throw new Error(`Service "${t}" config must be an object`);return[t,o]}));return we(Object.keys(r)),r}function je(e){return Object.fromEntries(Object.entries(e).map(([r,t])=>{const o=t||{},i={discovery:L(n(o,"discovery"),r),local:Object.prototype.hasOwnProperty.call(o,"local")?M(n(o,"local"),r)||!1:void 0};return[r,i]}))}function xe(e){if(!w(e))throw new Error("Loaded Testkit config context must be an object");const r=e.config;if(typeof r!="object"||r===null)throw new Error("Loaded Testkit config must be an object");const t=e.configFile;if(t!==null&&typeof t!="string")throw new Error("Loaded Testkit config file must be a string or null");return{config:r,configFile:t}}function ze(e,r){if(e==null)return[];if(!Array.isArray(e))throw new Error(`${r} must be an array of strings`);return e.map((t,o)=>{if(typeof t!="string")throw new Error(`${r}[${String(o)}] must be a string`);return t})}function A(e,r){if(e==null)return{};if(!w(e))throw new Error(`${r} must be an object of strings`);return Object.fromEntries(Object.entries(e).map(([t,o])=>{if(typeof o!="string")throw new Error(`${r}.${t} must be a string`);return[t,o]}))}function Te(e,r){if(e===void 0)return{};if(typeof e!="number")throw new Error(`${r} must be a number`);return{readyTimeoutMs:e}}function Ie(e,r){if(e===void 0)return{};if(typeof e!="number"||!Number.isInteger(e)||e<=0)throw new Error(`Service "${r}" local.shutdownTimeoutMs must be a positive finite integer in milliseconds`);return{shutdownTimeoutMs:e}}function Ue(e,r){if(e===void 0)return{};if(typeof e=="string")return F(e,`Service "${r}" local.readyUrl`),{readyUrl:e};if(e===!1||e===null)return{readyUrl:e};throw new Error(`Service "${r}" local.readyUrl must be a string, false, or null`)}function S(e,r){if(e!==void 0){if(typeof e!="string")throw new Error(`${r} must be a string`);return e}}function B(e,r){if(typeof e!="string")throw new Error(`${r} must be a string`);return e}function ke(e){if(e){if(!w(e))throw new Error("testkit.config.ts execution must be an object");return e}}
|
|
1
|
+
import{selectDiscoveredSuites as L,selectsOnlyTypedFiles as B}from"./test-selection.js";import q from"path";import{isUnknownRecord as w,readDynamicProperty as i}from"../../kernel/unknown-values.js";import{suiteKey as T}from"../../domain/suite-selection.js";import{legacyServiceProblem as k,repoDiscoveryProblem as G}from"./groups.js";import{discoverOwnedTests as K}from"./owned-discovery.js";import{loadTestkitConfig as _}from"./config-loader.js";import{normalizeToolchainRegistry as V}from"../../toolchains/index.js";import{loadTestFileMetadataMap as H}from"./file-metadata.js";import{normalizeFingerprintPolicy as J}from"../../repo/fingerprint-policy.js";import{normalizeDatabaseConfig as Q}from"./database.js";import{inferEnvFiles as W,parseDotenv as X}from"./env.js";import{normalizeRuntimeIsolationConfig as Y}from"./runtime-isolation.js";import{resolveProductDir as z,resolveServiceCwd as Z}from"./paths.js";import{normalizeRepoExecution as N,normalizeRuntimeConfig as ee}from"./runtime.js";import{normalizeServiceRequirements as re,normalizeSkipConfig as te}from"./skip-config.js";import{normalizeArtifactArchiveConfig as oe}from"../../evidence/index.js";import{validateConfigCoverage as ne,validateServiceConfig as ie}from"./validation.js";import{assertPortableServiceNameSet as se,requireServiceName as ae}from"../../domain/service-name.js";import{resolveExecutionProfile as ce}from"../../engines/catalog.js";import{optionalStringValue as S}from"../../evidence/read-fields.js";const U=["65533","65534"],fe=/\{(?:baseUrl|readyUrl|publicBaseUrl|privateBaseUrl|serviceContextUrl)(?::[^}]+)?\}/gu;export{X as parseDotenv,z as resolveProductDir,Z as resolveServiceCwd};export async function loadConfigContext(e={}){const r=z(process.cwd(),e.dir),t=e.configContext||await _(r,{importCacheSalt:e.configImportCacheSalt??""}),{config:o,configFile:n}=Se(t),a=N(Ce(i(o,"execution"))),f=oe(i(o,"artifacts")),p=V(i(o,"toolchains")),s=J(i(o,"fingerprints")),h=$e(i(o,"redact"));$(G(o));const c=ye(i(o,"services")),u=!Object.hasOwn(o,"groups");e.preparedDiscovery||be(c,u);const g=e.plain??!B(e.testSelection??{}),l=e.preparedDiscovery?.owned??await K(r,o,{...e.discoveryOptions,plain:g,retired:e.retired,selection:e.vitest}),d=l.project,b=e.testSelection?L(d.suitesByService,e.testSelection):d.suitesByService,y=H(r,b,e.preparedDiscovery?.fileMetadataByPath),A=le(b,y),E=[];for(const m of Object.keys(c).sort((v,O)=>v.localeCompare(O)))E.push(pe({name:m,productDir:r,config:o,configFile:n,execution:a,artifacts:f,toolchains:p,fingerprints:s,explicitService:c[m]??{},legacy:u}));$(l.problems[0]??null),ne(E);const C=[];for(const m of[...l.groups].sort((v,O)=>v.name.localeCompare(O.name)))C.push(de({declaration:m,productDir:r,configFile:n,execution:a,artifacts:f,policy:me(o,m),redact:h,suites:A[m.name]||[],discoveredSuites:d.suitesByService[m.name]||[],fileMetadataByPath:y,plainListed:g}));return{productDir:r,config:o,configFile:n,execution:a,toolchains:p,fingerprints:s,explicitServices:c,discovery:d,groups:C,ownershipNotice:l.notice,services:E}}function le(e,r){return Object.fromEntries(Object.entries(e).map(([t,o])=>[t,(o??[]).map(n=>ue(t,n,r))]))}function ue(e,r,t){const o=r.files[0];if(!o)throw new Error(`Discovered suite ${e}/${T(r)} contains no files`);const n=P(t,o);ce({...r,...n});for(const a of r.files.slice(1)){const f=P(t,a);if(f.engineId!==n.engineId||f.profileId!==n.profileId)throw new Error(`Discovered suite ${e}/${T(r)} mixes engine profiles ${n.engineId}/${n.profileId} and ${f.engineId}/${f.profileId}`)}return{...r,engineId:n.engineId,profileId:n.profileId}}function P(e,r){const t=e.get(r);if(!t)throw new Error(`Missing validated testkit metadata for discovered file: ${r}`);return t}export async function loadConfigs(e={}){const{services:r}=await loadConfigContext(e),t=e.service?r.filter(o=>o.name===e.service):r;if(e.service&&t.length===0){const o=r.map(n=>n.name).join(", ");throw new Error(`Service "${e.service}" not found. Available: ${o}`)}return t}function pe({name:e,productDir:r,config:t,configFile:o,execution:n,artifacts:a,toolchains:f,fingerprints:p,explicitService:s,legacy:h}){const c=Object.hasOwn(s,"local")?I(i(s,"local"),e):void 0,u=W(r,s,c),g=D(i(s,"env"),`Service "${e}" env`);if(h&&$(k(e,s)),i(s,"migrate")||i(s,"seed"))throw new Error(`Service "${e}" uses removed migrate/seed hooks. Move template lifecycle to database.template.{migrate,seed,verify}.`);const l=he(s,e),d=ee(i(s,"runtime"),e,f),b=Ee(i(s,"dependsOn"),`Service "${e}" dependsOn`),y=S(i(s,"databaseFrom"),`Service "${e}" databaseFrom`);return ie({name:e,local:c,database:l,databaseFrom:y,runtime:d,dependsOn:b,productDir:r}),{name:e,productDir:r,configFile:o,stateDir:q.join(r,".testkit",e),artifacts:a,testkit:{execution:n,dependsOn:b,database:l,databaseFrom:y,envFiles:u,serviceEnv:g,runtime:d,ui:i(t,"ui")||null,fingerprints:p,local:c}}}function de({declaration:e,productDir:r,configFile:t,execution:o,artifacts:n,policy:a,redact:f,suites:p,discoveredSuites:s,fileMetadataByPath:h,plainListed:c}){const u=e.source==="services"?`Service "${e.name}"`:`Group "${e.name}"`,g=new Set(p.flatMap(l=>l.files));return{...e,roots:[...e.roots],uses:[...e.uses],artifacts:n,configFile:t,productDir:r,redact:f,suites:p,testkit:{execution:o,fileMetadataByPath:new Map([...h.entries()].filter(([l])=>g.has(l))),requirements:re(i(a,"requirements"),{owner:u,plainListed:c,suites:s}),runtimeIsolation:Y(i(a,"runtimeIsolation"),{owner:u,plainListed:c,suites:s}),skip:te(i(a,"skip"),{owner:u,plainListed:c,suites:s})}}}function me(e,r){if(r.source!=="implicit")return i(i(e,r.source==="groups"?"groups":"services"),r.name)}function I(e,r){if(e===!1)return;if(!w(e))throw new Error(`Service "${r}" local must be an object or false`);if(Object.prototype.hasOwnProperty.call(e,"port"))throw new Error(`Service "${r}" sets local.port. Testkit assigns every service a free port from the OS. Delete the line, or the port option of app.node or app.next, and use {port} in start, baseUrl, and readyUrl.`);const t=F(e.start,`Service "${r}" local.start`),{baseUrl:o,shutdownTimeoutMs:n,...a}=e;return{...a,...Oe(n,r),...ge(o,r),start:t,cwd:S(e.cwd,`Service "${r}" local.cwd`)||".",env:D(e.env,`Service "${r}" local.env`),...ve(e.readyTimeoutMs,`Service "${r}" local.readyTimeoutMs`),...je(e.readyUrl,r)}}function ge(e,r){if(e==null)return{};const t=F(e,`Service "${r}" local.baseUrl`);x(t,`Service "${r}" local.baseUrl`);const o=new RegExp(`\\{port(?::${we(r)})?\\}`,"gu");if(!U.every(n=>R(t,o,n,!1)===n))throw new Error(`Service "${r}" local.baseUrl must use {port} for its port, for example http://127.0.0.1:{port}. Testkit assigns every service a free port from the OS.`);return{baseUrl:t}}function j(e){return e.replace(/[\t\n\r]/gu,"").trim()}function M(e){return/^[a-z][a-z0-9+.-]*:[\\/]{2}(?![\\/])([^/\\?#]*)/iu.exec(j(e))?.[1]}function R(e,r,t,o){const n=j(e).replace(r,t).replace(fe,o?`http://template.invalid:${t}`:"http://template.invalid").replace(/\{[^}]+\}/gu,"template");try{return new URL(n).port}catch{return}}function we(e){return e.replace(/[.*+?^${}()|[\]\\]/gu,"\\$&")}function x(e,r){if(/^[a-z][a-z0-9+.-]*:/iu.test(j(e))&&M(e)===void 0)throw new Error(`${r} must be an absolute URL with a host, for example http://127.0.0.1:{port}/health.`);const[t,o]=U.map(a=>R(e,/\{port(?::[^}]+)?\}/gu,a,!0)),n=/:(\d+)$/u.exec(M(e)??"")?.[1]??(t&&t===o?t:void 0);if(n!==void 0)throw new Error(`${r} has a literal port (${n}). Testkit assigns every service a free port from the OS. Replace the port with {port}.`)}function he(e,r){const t=Q(e,r);if(!t)return;const o=S(i(t,"image"),`Service "${r}" database.image`),n=S(i(t,"password"),`Service "${r}" database.password`),a=S(i(t,"user"),`Service "${r}" database.user`);return{...t,...Object.prototype.hasOwnProperty.call(t,"image")?{image:o}:{},...Object.prototype.hasOwnProperty.call(t,"password")?{password:n}:{},...Object.prototype.hasOwnProperty.call(t,"user")?{user:a}:{}}}function be(e,r){for(const[t,o]of Object.entries(e))r&&$(k(t,o)),o&&Object.hasOwn(o,"local")&&I(i(o,"local"),t)}function $(e){if(e!==null)throw new Error(e)}function ye(e){if(e==null)return{};if(!w(e))throw new Error("testkit.config.ts services must be an object");const r=Object.fromEntries(Object.entries(e).map(([t,o])=>{if(ae(t,`Service name "${t}"`),o==null)return[t,{}];if(!w(o))throw new Error(`Service "${t}" config must be an object`);return[t,o]}));return se(Object.keys(r)),r}function Se(e){if(!w(e))throw new Error("Loaded Testkit config context must be an object");const r=e.config;if(typeof r!="object"||r===null)throw new Error("Loaded Testkit config must be an object");const t=e.configFile;if(t!==null&&typeof t!="string")throw new Error("Loaded Testkit config file must be a string or null");return{config:r,configFile:t}}function $e(e){if(e==null)return[];if(!Array.isArray(e))throw new Error("testkit.config.ts redact must be an array of env key names");return e.map((r,t)=>{if(typeof r!="string")throw new Error(`testkit.config.ts redact[${String(t)}] must be a string`);if(r.trim().length===0)throw new Error(`testkit.config.ts redact[${String(t)}] must not be empty`);return r.trim()})}function Ee(e,r){if(e==null)return[];if(!Array.isArray(e))throw new Error(`${r} must be an array of strings`);return e.map((t,o)=>{if(typeof t!="string")throw new Error(`${r}[${String(o)}] must be a string`);return t})}function D(e,r){if(e==null)return{};if(!w(e))throw new Error(`${r} must be an object of strings`);return Object.fromEntries(Object.entries(e).map(([t,o])=>{if(typeof o!="string")throw new Error(`${r}.${t} must be a string`);return[t,o]}))}function ve(e,r){if(e===void 0)return{};if(typeof e!="number")throw new Error(`${r} must be a number`);return{readyTimeoutMs:e}}function Oe(e,r){if(e===void 0)return{};if(typeof e!="number"||!Number.isInteger(e)||e<=0)throw new Error(`Service "${r}" local.shutdownTimeoutMs must be a positive finite integer in milliseconds`);return{shutdownTimeoutMs:e}}function je(e,r){if(e===void 0)return{};if(typeof e=="string")return x(e,`Service "${r}" local.readyUrl`),{readyUrl:e};if(e===!1||e===null)return{readyUrl:e};throw new Error(`Service "${r}" local.readyUrl must be a string, false, or null`)}function F(e,r){if(typeof e!="string")throw new Error(`${r} must be a string`);return e}function Ce(e){if(e){if(!w(e))throw new Error("testkit.config.ts execution must be an object");return e}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{loadConfigs as d}from"./load.js";export async function loadManagedConfigs(e={}){const
|
|
1
|
+
import{loadConfigContext as c,loadConfigs as d}from"./load.js";export async function loadManagedConfigs(e={}){const n=await d({dir:e.dir,plain:!1,retired:[]}),i=filterConfigsByService(n,e.service||null);return{allConfigs:n,configs:i}}export async function loadRunConfigs(e={}){const n=await c(e),i=e.group?n.groups.filter(t=>t.name===e.group):n.groups.filter(t=>t.source!=="implicit"||Object.hasOwn(n.discovery.suitesByService,t.name));if(e.group&&i.length===0){const t=n.groups.map(r=>r.name).join(", ");throw new Error(`Group "${e.group}" not found. Available: ${t}`)}return{groups:i,ownershipNotice:n.ownershipNotice,services:n.services}}export function filterConfigsByService(e,n){if(!n)return e;const i=e.filter(r=>r.name===n);if(i.length>0)return i;const t=e.map(r=>r.name).join(", ");throw new Error(`Service "${n}" not found. Available: ${t}`)}export function resolveTargetConfig(e,n=null){if(n){const r=e.find(a=>a.name===n);if(!r){const a=e.map(o=>o.name).join(", ");throw new Error(`Service "${n}" not found. Available: ${a}`)}return r}if(e.length===1)return e[0];const i=e.filter(r=>r.testkit.database);if(i.length===1)return i[0];const t=e.map(r=>r.name).join(", ");throw new Error(`Multiple services available. Pass --service. Available: ${t}`)}export function collectRequiredConfigs(e,n){const i=new Map(e.map(a=>[a.name,a])),t=new Set,r=a=>{if(t.has(a))return;const o=i.get(a);if(!o)throw new Error(`Missing config for dependency "${a}"`);t.add(a);for(const s of o.testkit.dependsOn)r(s)};return r(n),e.filter(a=>t.has(a.name))}export function topologicallySortConfigs(e){const n=new Map(e.map(o=>[o.name,o])),i=new Set,t=new Set,r=[],a=o=>{if(!i.has(o.name)){if(t.has(o.name))throw new Error(`Dependency cycle while resolving configs for "${o.name}"`);t.add(o.name);for(const s of o.testkit.dependsOn){const l=n.get(s);l&&a(l)}t.delete(o.name),i.add(o.name),r.push(o)}};for(const o of e)a(o);return r}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{rejectRetiredTestFile as d}from"../../domain/retired-test-types.js";import{listPlainVitestFiles as f,resolveVitestSelection as h}from"../../engines/catalog.js";import{buildDiscoveryProject as m,scanTestFiles as v}from"./discovery.js";import{readDiscoveryScan as y,resolveGroups as l}from"./groups.js";export async function discoverOwnedTests(e,o,{plain:p=!0,selection:u=h({},e),...n}={}){const r=v(e,y(o)),c=r.untypedFiles.map(t=>({kind:"typed",path:t}));for(const t of l(o,c).assignments)t.status!=="excluded"&&d(t.path,n.retired);const i=new Map;for(const t of r.suiteFiles)i.set(t,{kind:"typed",path:t});const a=p?await f(e,u):[];for(const{file:t}of a)i.set(t,{kind:"plain",path:t});const s=l(o,[...i.values()]);return{groups:s.groups,notice:s.notice,plainFiles:a,problems:s.problems,project:m(r.legacyFiles,s.assignments.flatMap(w),n)}}function w(e){return e.status==="excluded"?[]:e.status==="ambiguous"?[{filePath:e.path,kind:"ambiguous",owners:e.groups}]:[{filePath:e.path,kind:"owned",owner:e.group,relativePath:e.relativePath}]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import l from"fs";import u from"path";const f=String;export const DEFAULT_DISCOVERY_EXCLUDES=Object.freeze([".cache",".git",".hg",".next",".nuxt",".playwright-browsers",".svn",".testkit",".turbo","build","coverage","dist","node_modules","playwright-report","test-results"]);export function resolveDiscoveryRoots(e,t,o="."){const s=Array.isArray(t)&&t.length>0?t:[o],c=new Set,a=[];for(const i of s){const r=normalizeDiscoveryPath(i);if(!r)continue;const n=u.resolve(e,r==="."?".":r);!l.existsSync(n)||!l.statSync(n).isDirectory()||c.has(n)||(c.add(n),a.push(n))}return a.sort((i,r)=>i.localeCompare(r))}export function shouldExcludeDiscoveryPath(e,t=[]){const o=normalizeDiscoveryPath(e);return!o||o==="."?!1:t.some(s=>h(o,s))}export function normalizeDiscoveryPath(e){return f(e||"").trim().split(u.sep).join("/").replace(/^\.\/+/u,"").replace(/\/+/gu,"/").replace(/\/+$/u,"")||"."}function h(e,t){return e===t||e.startsWith(`${t}/`)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{matchesSuiteSelectors as
|
|
1
|
+
import{matchesSuiteSelectors as E,parseSuiteSelectors as T}from"../../domain/suite-selection.js";import{isTypedTestFile as O}from"../../domain/identifiers.js";import{isUnknownRecord as I}from"../../kernel/unknown-values.js";import{DEFAULT_RUNTIME_ISOLATION_POLICY as g,normalizeRuntimeIsolationPolicy as m}from"../../domain/runtime-isolation-contract.js";import{normalizePath as y}from"./paths.js";import{optionalArray as R}from"./skip-config.js";export{DEFAULT_RUNTIME_ISOLATION_POLICY,isRuntimeIsolationPolicy,normalizeRuntimeIsolationPolicy,RUNTIME_ISOLATION_POLICIES}from"../../domain/runtime-isolation-contract.js";const L=String;export function normalizeRuntimeIsolationConfig(i,{owner:t,plainListed:p=!0,suites:u}){if(!i)return h();if(typeof i=="string")return{...h(),defaultPolicy:m(i,`${t} runtimeIsolation`)};if(!I(i))throw new Error(`${t} runtimeIsolation must be a policy string or object`);const c=u??[],n=new Set(c.flatMap(o=>(o.files??[]).map(y))),f=i.default==null?g:m(i.default,`${t} runtimeIsolation.default`),l=[],$=new Set;for(const[o,a]of R(i.suites,`${t} runtimeIsolation.suites`).entries()){if(!I(a))throw new Error(`${t} runtimeIsolation.suites entries must be objects`);const r=a,e=L(r.selector||"").trim();if(!e)throw new Error(`${t} runtimeIsolation.suites[${o.toString()}] requires a selector`);const S=T([e]);if(S.length!==1)throw new Error(`${t} runtimeIsolation.suites["${e}"] is invalid`);const s=S[0];if(s.kind!=="typed")throw new Error(`${t} runtimeIsolation.suites["${e}"] must use a typed selector like ui:auth`);if($.has(s.raw))throw new Error(`${t} defines duplicate runtimeIsolation.suites selector "${s.raw}"`);if(!c.some(w=>E(w.testType,w.name,[s])))throw new Error(`${t} runtimeIsolation.suites selector "${s.raw}" did not match any discovered suite`);$.add(s.raw),l.push({selector:s,policy:m(r.policy||r.runtimeIsolation,`${t} runtimeIsolation.suites["${s.raw}"].policy`)})}const d=[],P=new Set;for(const[o,a]of R(i.files,`${t} runtimeIsolation.files`).entries()){if(!I(a))throw new Error(`${t} runtimeIsolation.files entries must be objects`);const r=a,e=y(_(r.path,`${t} runtimeIsolation.files[${o.toString()}].path`));if(!e)throw new Error(`${t} runtimeIsolation.files[${o.toString()}] requires a path`);if(!n.has(e)&&(p||O(e)))throw new Error(`${t} runtimeIsolation.files["${e}"] did not match any discovered test file`);if(P.has(e))throw new Error(`${t} defines duplicate runtimeIsolation.files path "${e}"`);P.add(e),d.push({path:e,policy:m(r.policy||r.runtimeIsolation,`${t} runtimeIsolation.files["${e}"].policy`)})}return{defaultPolicy:f,suites:l,files:d,filePolicyByPath:new Map(d.map(o=>[o.path,o.policy]))}}export function resolveRuntimeIsolationPolicy(i,t,p){const u=y(p),c=i.testkit?.fileMetadataByPath?.get(u)||null,n=i.testkit?.runtimeIsolation||h(),f=c?.runtimeIsolation||n.filePolicyByPath.get(u);if(f)return f;for(const l of n.suites)if(E(t.testType,t.name,[l.selector]))return l.policy;return n.defaultPolicy}function h(){return{defaultPolicy:g,suites:[],files:[],filePolicyByPath:new Map}}function _(i,t){if(i==null||typeof i=="string")return i;throw new Error(`${t} must be a string`)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"fs";import i from"path";import{DEFAULT_FILE_TIMEOUT_SECONDS as
|
|
1
|
+
import t from"fs";import i from"path";import{DEFAULT_FILE_TIMEOUT_SECONDS as c}from"../../domain/file-timeout.js";import{normalizeExecutionConfig as u,normalizeRuntimeMaxConcurrentTasks as f,normalizeRuntimeInstances as l}from"./decode-execution.js";import"./execution-model.js";import{normalizeConfiguredInputs as S,normalizeConfiguredSteps as x}from"../../steps/configured-steps.js";import{buildConfigToPrepare as C,normalizeBuildConfig as T}from"../../steps/build-config.js";import{normalizeRuntimeToolchain as z}from"../../toolchains/index.js";import{isNonNullObject as m}from"../../kernel/unknown-values.js";export function normalizeRuntimeConfig(e,n,a){if(!e)return{build:null,instances:1,maxConcurrentTasks:Number.POSITIVE_INFINITY,prepare:{inputs:[],steps:[]},toolchain:null};const r=m(e)?e:{},o=T(r.build,`Service "${n}" runtime.build`),s=normalizeRuntimePrepareConfig(r.prepare,n),p=C(o);return{build:o,instances:l(r.instances??1,`Service "${n}" runtime.instances`),maxConcurrentTasks:f(r.maxConcurrentTasks,`Service "${n}" runtime.maxConcurrentTasks`),prepare:{inputs:[...new Set([...p.inputs,...s.inputs])],steps:[...p.steps,...s.steps]},toolchain:z(r.toolchain,`Service "${n}" runtime.toolchain`,a||{})}}export function normalizeRuntimePrepareConfig(e,n){if(e==null)return{inputs:[],steps:[]};if(!m(e))throw new Error(`Service "${n}" runtime.prepare must be an object`);return{inputs:S(e.inputs,`Service "${n}" runtime.prepare`),steps:x(e.steps,`Service "${n}" runtime.prepare.steps`)}}export function normalizeRepoExecution(e){return e?u(e):u({workers:1,fileTimeoutSeconds:c})}export function detectNextApp(e){return t.existsSync(i.join(e,"next.config.js"))||t.existsSync(i.join(e,"next.config.mjs"))||t.existsSync(i.join(e,"next.config.ts"))}export{normalizeConfiguredStep as normalizeTemplateLifecycleStep,normalizeConfiguredSteps as normalizeTemplateLifecycleSteps,parseModuleSpecifier}from"../../steps/configured-steps.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{matchesSuiteSelectors as
|
|
1
|
+
import{isTypedTestFile as y}from"../../domain/identifiers.js";import{matchesSuiteSelectors as q,parseSuiteSelectors as S}from"../../domain/suite-selection.js";import{normalizePath as E}from"./paths.js";import{isUnknownRecord as b}from"../../kernel/unknown-values.js";import{requireObjectRecord as g}from"../../evidence/read-fields.js";const $=String;export function normalizeSkipReason(r,e){const a=$(r||"").trim();if(!a)throw new Error(`${e} requires a non-empty reason`);return a}export function normalizeSkipConfig(r,{owner:e,plainListed:a=!0,suites:u}){if(!r)return;const l=g(r,`${e} skip`),p=new Set(u.flatMap(s=>s.files.map(E))),c=new Set,f=[];for(const s of optionalArray(l.files,`${e} skip.files`)){const n=k(s,`${e} skip.files entries must be objects`),t=E(typeof n.path=="string"?n.path:void 0),i=normalizeSkipReason(n.reason,`${e} skip.files["${t}"]`);if(!t)throw new Error(`${e} skip.files entries require a non-empty path`);if(c.has(t))throw new Error(`${e} defines duplicate skip.files path "${t}"`);if(!p.has(t)&&(a||y(t)))throw new Error(`${e} skip.files path "${t}" did not match any discovered suite file`);c.add(t),f.push({path:t,reason:i})}const m=optionalArray(l.suites,`${e} skip.suites`).map((s,n)=>{const t=k(s,`${e} skip.suites entries must be objects`),i=$(t.selector||"").trim();if(!i)throw new Error(`${e} skip.suites[${String(n)}] requires a non-empty selector`);const w=normalizeSkipReason(t.reason,`${e} skip.suites["${i}"]`),h=S([i]),R=h[0];if(h.length!==1)throw new Error(`${e} skip.suites["${i}"] is invalid`);return{selector:R,reason:w}}),d=new Set,o=[];for(const s of m){if(d.has(s.selector.raw))throw new Error(`${e} defines duplicate skip.suites selector "${s.selector.raw}"`);if(!u.some(t=>q(t.testType,t.name,[s.selector]))&&(a||s.selector.kind==="typed"))throw new Error(`${e} skip.suites selector "${s.selector.raw}" did not match any discovered suite`);d.add(s.selector.raw),o.push(s)}if(!(f.length===0&&o.length===0))return{files:f,fileReasonByPath:new Map(f.map(s=>[s.path,s.reason])),suites:o}}export function normalizeServiceRequirements(r,{owner:e,plainListed:a=!0,suites:u}){if(!r)return x();const l=g(r,`${e} requirements`),p=new Set(u.flatMap(o=>o.files)),c=[],f=new Set;for(const o of optionalArray(l.suites,`${e} requirements.suites`)){const s=k(o,`${e} requirements.suites entries must be objects`),n=$(s.selector||"").trim();if(!n)throw new Error(`${e} requirements.suites entries require a selector`);const t=S([n]),i=t[0];if(t.length!==1)throw new Error(`${e} requirements.suites["${n}"] is invalid`);if(i.kind!=="typed")throw new Error(`${e} requirements.suites["${n}"] must use a typed selector like contract:health`);if(f.has(i.raw))throw new Error(`${e} defines duplicate requirements.suites selector "${i.raw}"`);if(!u.some(h=>q(h.testType,h.name,[i])))throw new Error(`${e} requirements.suites selector "${i.raw}" did not match any discovered suite`);f.add(i.raw),c.push({selector:i,locks:normalizeRequirementLocks(s.locks,`${e} requirements.suites["${i.raw}"].locks`)})}const m=[],d=new Set;for(const[o,s]of optionalArray(l.files,`${e} requirements.files`).entries()){const n=k(s,`${e} requirements.files entries must be objects`),t=$(n.path||"").trim();if(!t)throw new Error(`${e} requirements.files[${String(o)}] requires a path`);if(!p.has(t)&&(a||y(t)))throw new Error(`${e} requirements.files["${t}"] did not match any discovered test file`);if(d.has(t))throw new Error(`${e} defines duplicate requirements.files path "${t}"`);d.add(t),m.push({path:t,locks:normalizeRequirementLocks(n.locks,`${e} requirements.files["${t}"].locks`)})}return{suites:c,files:m,fileLocksByPath:new Map(m.map(o=>[o.path,o.locks]))}}export function normalizeRequirementLocks(r,e){const a=Array.isArray(r)?r:r==null?[]:[r],u=new Set,l=[];for(const p of a){const c=$(p||"").trim();if(!c)throw new Error(`${e} entries must be non-empty strings`);u.has(c)||(u.add(c),l.push(c))}return l.sort()}function x(){return{suites:[],files:[],fileLocksByPath:new Map}}function k(r,e){if(!b(r))throw new Error(e);return r}export function optionalArray(r,e){if(r==null)return[];if(!Array.isArray(r))throw new Error(`${e} must be an array`);return r}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{matchesSuiteSelectors as a}from"../../domain/suite-selection.js";import{normalizePath as l}from"./paths.js";import{resolveRuntimeIsolationPolicy as i}from"./runtime-isolation.js";export function resolveTaskPolicy(o,t,r){return{locks:m(o,t,r),runtimeIsolation:i({testkit:o},t,r)}}function m(o,t,r){const n=l(r),s=new Set;for(const e of o.requirements.suites)if(a(t.testType,t.name,[e.selector]))for(const c of e.locks)s.add(c);for(const e of o.requirements.fileLocksByPath.get(n)??[])s.add(e);for(const e of o.fileMetadataByPath.get(n)?.locks??[])s.add(e);return[...s].sort()}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{isTypedTestFile as o}from"../../domain/identifiers.js";import{matchesSelectedTypes as i,matchesSuiteSelectors as a}from"../../domain/suite-selection.js";export function selectDiscoveredSuites(r,e){const l=new Set(e.fileNames?.map(p));return Object.fromEntries(Object.entries(r).map(([s,f])=>[s,e.group&&s!==e.group?[]:(f??[]).filter(t=>i(t.testType,e.typeValues??[])&&a(t.testType,t.name,e.suiteSelectors??[])).flatMap(t=>{const n=l.size?t.files.filter(c=>l.has(p(c))):t.files;return n.length?[{...t,files:n}]:[]})]))}export function selectsOnlyTypedFiles({fileNames:r=[],typeValues:e=[]}){return!i(void 0,e)||r.length>0&&r.every(o)}function p(r){return r.replaceAll("\\","/")}
|