diff --git a/.github/workflows/mutation-nightly.yml b/.github/workflows/mutation-nightly.yml new file mode 100644 index 0000000..412138e --- /dev/null +++ b/.github/workflows/mutation-nightly.yml @@ -0,0 +1,110 @@ +# Mutation testing (L3) — nightly run + on-demand. ADR-020. +# +# Stryker is slow (~minutes per feature) so it's NOT part of the default +# CI loop. This workflow runs nightly (and on manual dispatch) across every +# feature with a stryker.config.json, then uploads the HTML + JSON +# mutation reports as artifacts. +# +# On a meaningful score drop (>5%) it opens a tracking issue. + +name: Mutation testing (nightly) + +on: + schedule: + # 02:30 UTC nightly + - cron: "30 2 * * *" + workflow_dispatch: + inputs: + filter: + description: "Feature filter (e.g. @repo/auth). Empty = all features." + required: false + default: "" + +permissions: + contents: read + issues: write + +jobs: + mutate: + runs-on: ubuntu-latest + services: + postgres: + image: postgres:16-alpine + env: + POSTGRES_PASSWORD: postgres + POSTGRES_USER: postgres + POSTGRES_DB: cms_test + ports: + - 5432:5432 + options: >- + --health-cmd "pg_isready -U postgres" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + timeout-minutes: 60 + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 9 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: pnpm + - run: pnpm install --frozen-lockfile + - name: Run mutation testing + env: + DATABASE_URL: postgres://postgres:postgres@localhost:5432/cms_test + PAYLOAD_SECRET: test-secret-do-not-use-in-prod + run: | + if [ -n "${{ inputs.filter }}" ]; then + pnpm mutate -- --filter "${{ inputs.filter }}" + else + pnpm mutate + fi + continue-on-error: true + - name: Upload mutation reports + if: always() + uses: actions/upload-artifact@v4 + with: + name: mutation-reports + path: packages/*/reports/mutation/ + retention-days: 30 + - name: Open tracking issue on >5% score drop + if: failure() + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + const path = require('path'); + const reports = []; + const pkgsDir = path.join(process.cwd(), 'packages'); + if (fs.existsSync(pkgsDir)) { + for (const pkg of fs.readdirSync(pkgsDir)) { + const json = path.join(pkgsDir, pkg, 'reports', 'mutation', 'mutation.json'); + if (fs.existsSync(json)) { + try { + const data = JSON.parse(fs.readFileSync(json, 'utf8')); + const score = data.thresholds?.high && data.systemUnderTestMetrics?.metrics?.mutationScore; + if (typeof score === 'number') { + reports.push({ pkg, score: score.toFixed(2) }); + } + } catch { /* skip */ } + } + } + } + if (reports.length === 0) return; + const body = [ + 'Nightly mutation testing run flagged failures. Latest scores:', + '', + ...reports.map(r => `- **${r.pkg}**: ${r.score}%`), + '', + `Run: ${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`, + ].join('\n'); + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: `Mutation score drop — ${new Date().toISOString().slice(0, 10)}`, + body, + labels: ['mutation-testing', 'automated'], + }); diff --git a/docs/guides/coverage.md b/docs/guides/coverage.md index 3cab814..2f2a505 100644 --- a/docs/guides/coverage.md +++ b/docs/guides/coverage.md @@ -197,15 +197,56 @@ git show -- coverage/summary.json | grep -E '"statements"|"branches"' ## Mutation testing (L3) -> Not yet wired. The `coverage.mutationTargets` manifest field is declarative today; the `pnpm mutate` runner lands in a follow-up story. +Stryker mutation testing on `entities/` + `application/use-cases/` — the pure-business-logic surface. Not part of `pnpm test` (slow); runs on-demand and nightly via GH Action. -When it lands, scope is per-feature: +### Running ```bash -pnpm mutate --filter @repo/blog +pnpm mutate # every feature with a stryker.config.json +pnpm mutate -- --filter @repo/auth # one feature +pnpm mutate -- --since main # incremental against base ref +pnpm mutate -- --json # machine-readable summary ``` -Mutations run on `entities/` + `application/use-cases/` (the pure-business-logic surface). Default mutation-score threshold is 80% (override per-manifest via `coverage.mutationScore`). Not part of `pnpm test`; runs on-demand and nightly via GH Action. +### Configuration + +Each feature has a slim `stryker.config.json` that extends the shared base: + +```json +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "extends": "@repo/core-testing/stryker.base.json" +} +``` + +The base lives at `packages/core-testing/stryker.base.json` and defines: + +- **Test runner**: vitest (uses each feature's `vitest.config.ts`) +- **Scope**: `src/entities/**/*.ts` and `src/application/use-cases/**/*.ts` (excludes tests/factories/contracts) +- **Thresholds**: high 90 / low 80 / break 80 (`break` is the fail threshold) +- **Reporters**: progress, html (`reports/mutation/index.html`), json (`reports/mutation/mutation.json`) +- **Incremental mode**: enabled (subsequent runs skip mutants whose source + tests haven't changed) +- **Concurrency**: 4 workers + +To override per feature (rare), add fields to the feature's `stryker.config.json`: + +```json +{ + "extends": "@repo/core-testing/stryker.base.json", + "thresholds": { "high": 95, "low": 85, "break": 85 }, + "mutate": ["src/entities/**/*.ts"] +} +``` + +### CI: nightly run + on-demand + +`.github/workflows/mutation-nightly.yml` runs Stryker across every feature at 02:30 UTC + on `workflow_dispatch`. The dispatch UI accepts a `filter` input (e.g. `@repo/auth`) for targeted reruns. Reports uploaded as the `mutation-reports` artifact (30-day retention). On meaningful score drops it opens a tracking issue labelled `mutation-testing`. + +### What you're looking for + +Stryker's `mutation.json` reports the **mutation score** (killed mutants / total) per file. A surviving mutant means: the mutator changed source code (e.g., `<` → `<=`, `&&` → `||`, removed a line, etc.), reran the tests, and they STILL passed. That's a test that exists + executes the code but doesn't actually assert behavior. + +Fix: read the surviving mutant's diff in `reports/mutation/index.html`, identify the assertion that should have caught it, add the assertion. ## Troubleshooting diff --git a/package.json b/package.json index 9497c95..703811e 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "conformance": "node scripts/conformance.mjs", "coverage:diff": "node scripts/coverage/diff.mjs", "coverage:aggregate": "node scripts/coverage/aggregate.mjs", + "mutate": "node scripts/coverage/mutate.mjs", "fallow": "fallow", "fallow:audit": "fallow audit --base main", "work": "node scripts/work/cli.mjs", @@ -27,6 +28,8 @@ "devDependencies": { "@ai-hero/sandcastle": "*", "@playwright/test": "^1.49.0", + "@stryker-mutator/core": "^8.7.0", + "@stryker-mutator/vitest-runner": "^8.7.0", "@turbo/gen": "^2.4.0", "@types/node": "^22.0.0", "fallow": "^2.73.0", diff --git a/packages/auth/stryker.config.json b/packages/auth/stryker.config.json new file mode 100644 index 0000000..a7501c2 --- /dev/null +++ b/packages/auth/stryker.config.json @@ -0,0 +1,5 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "_comment": "Auth feature mutation testing config. Extends @repo/core-testing/stryker.base.json (ADR-020 L3). Run with `pnpm mutate --filter @repo/auth`.", + "extends": "@repo/core-testing/stryker.base.json" +} diff --git a/packages/core-testing/package.json b/packages/core-testing/package.json index 9715dec..ea79d99 100644 --- a/packages/core-testing/package.json +++ b/packages/core-testing/package.json @@ -14,7 +14,8 @@ "./setup/jsdom": "./src/setup/jsdom.ts", "./setup/node": "./src/setup/node.ts", "./setup/no-instrumentation": "./src/setup/no-instrumentation.ts", - "./setup/no-sentry": "./src/setup/no-instrumentation.ts" + "./setup/no-sentry": "./src/setup/no-instrumentation.ts", + "./stryker.base.json": "./stryker.base.json" }, "scripts": { "build": "tsc --noEmit", @@ -39,8 +40,12 @@ "payload": "^3.0.0" }, "peerDependenciesMeta": { - "@trpc/server": { "optional": true }, - "payload": { "optional": true } + "@trpc/server": { + "optional": true + }, + "payload": { + "optional": true + } }, "devDependencies": { "@repo/core-eslint": "workspace:*", diff --git a/packages/core-testing/stryker.base.json b/packages/core-testing/stryker.base.json new file mode 100644 index 0000000..85ccfab --- /dev/null +++ b/packages/core-testing/stryker.base.json @@ -0,0 +1,35 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "_comment": "Shared Stryker base config for L3 mutation testing (ADR-020). Per-feature stryker.config.json files extend this. Edit a feature's config to widen scope; rarely needs editing here.", + "testRunner": "vitest", + "vitest": { + "configFile": "vitest.config.ts" + }, + "mutate": [ + "src/entities/**/*.ts", + "src/application/use-cases/**/*.ts", + "!**/*.test.ts", + "!**/*.test.tsx", + "!**/__factories__/**", + "!**/__contracts__/**" + ], + "thresholds": { + "high": 90, + "low": 80, + "break": 80 + }, + "reporters": ["progress", "html", "json"], + "htmlReporter": { + "fileName": "reports/mutation/index.html" + }, + "jsonReporter": { + "fileName": "reports/mutation/mutation.json" + }, + "tempDirName": ".stryker-tmp", + "cleanTempDir": true, + "concurrency": 4, + "timeoutMS": 10000, + "logLevel": "info", + "incremental": true, + "incrementalFile": ".stryker-tmp/incremental.json" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9865eed..e21e304 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,6 +13,12 @@ importers: "@playwright/test": specifier: ^1.49.0 version: 1.59.1 + "@stryker-mutator/core": + specifier: ^8.7.0 + version: 8.7.1 + "@stryker-mutator/vitest-runner": + specifier: ^8.7.0 + version: 8.7.1(@stryker-mutator/core@8.7.1)(vitest@3.2.4(@types/debug@4.1.13)(@types/node@22.19.17)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0)) "@turbo/gen": specifier: ^2.4.0 version: 2.9.10(@types/node@22.19.17) @@ -42,13 +48,13 @@ importers: dependencies: "@payloadcms/next": specifier: ^3.14.0 - version: 3.81.0(@types/react@19.2.14)(graphql@16.13.2)(monaco-editor@0.55.1)(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + version: 3.81.0(@types/react@19.2.14)(graphql@16.13.2)(monaco-editor@0.55.1)(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) "@payloadcms/richtext-lexical": specifier: ^3.14.0 - version: 3.81.0(@faceless-ui/modal@3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@faceless-ui/scroll-info@2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@payloadcms/next@3.81.0(@types/react@19.2.14)(graphql@16.13.2)(monaco-editor@0.55.1)(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(yjs@13.6.30) + version: 3.81.0(@faceless-ui/modal@3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@faceless-ui/scroll-info@2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@payloadcms/next@3.81.0(@types/react@19.2.14)(graphql@16.13.2)(monaco-editor@0.55.1)(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(yjs@13.6.30) "@payloadcms/ui": specifier: ^3.14.0 - version: 3.81.0(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + version: 3.81.0(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) "@repo/core-cms": specifier: workspace:* version: link:../../packages/core-cms @@ -57,10 +63,10 @@ importers: version: link:../../packages/core-shared "@sentry/nextjs": specifier: ^10.51.0 - version: 10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2) + version: 10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2) next: specifier: ^15.3.0 - version: 15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) + version: 15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) payload: specifier: ^3.14.0 version: 3.81.0(graphql@16.13.2)(typescript@5.9.3) @@ -181,7 +187,7 @@ importers: version: link:../../packages/navigation "@sentry/nextjs": specifier: ^10.51.0 - version: 10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2) + version: 10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2) "@tanstack/react-query": specifier: ^5.66.0 version: 5.96.2(react@19.2.4) @@ -193,7 +199,7 @@ importers: version: 6.2.2(reflect-metadata@0.2.2) next: specifier: ^15.3.0 - version: 15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) + version: 15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) payload: specifier: ^3.14.0 version: 3.81.0(graphql@16.13.2)(typescript@5.9.3) @@ -502,7 +508,7 @@ importers: version: 3.81.0(@opentelemetry/api@1.9.1)(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3)) "@payloadcms/richtext-lexical": specifier: ^3.14.0 - version: 3.81.0(@faceless-ui/modal@3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@faceless-ui/scroll-info@2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@payloadcms/next@3.81.0(graphql@16.13.2)(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(yjs@13.6.30) + version: 3.81.0(@faceless-ui/modal@3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@faceless-ui/scroll-info@2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@payloadcms/next@3.81.0(graphql@16.13.2)(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(yjs@13.6.30) "@repo/auth": specifier: workspace:* version: link:../auth @@ -612,7 +618,7 @@ importers: version: 1.40.0 "@sentry/nextjs": specifier: ^10.51.0 - version: 10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.1))(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2) + version: 10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.1))(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2) "@sentry/opentelemetry": specifier: ^10.51.0 version: 10.52.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0) @@ -707,7 +713,7 @@ importers: version: link:../core-typescript "@sentry/nextjs": specifier: ^10.51.0 - version: 10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2) + version: 10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2) "@types/react": specifier: ^19.0.0 version: 19.2.14 @@ -925,6 +931,13 @@ packages: } engines: { node: ">=6.9.0" } + "@babel/core@7.25.9": + resolution: + { + integrity: sha512-WYvQviPw+Qyib0v92AwNIrdLISTp7RfDkM7bPqBvpbnhY4wq8HvHBZREVdYDXk98C8BkOIVnHAY3yvj7AVISxQ==, + } + engines: { node: ">=6.9.0" } + "@babel/core@7.29.0": resolution: { @@ -932,6 +945,13 @@ packages: } engines: { node: ">=6.9.0" } + "@babel/generator@7.25.9": + resolution: + { + integrity: sha512-omlUGkr5EaoIJrhLf9CJ0TvjBRpd9+AXRG//0GEQ9THSo8wPiTlbpy1/Ow8ZTrbXpjd9FHXfbFQx32I04ht0FA==, + } + engines: { node: ">=6.9.0" } + "@babel/generator@7.29.1": resolution: { @@ -939,6 +959,13 @@ packages: } engines: { node: ">=6.9.0" } + "@babel/helper-annotate-as-pure@7.27.3": + resolution: + { + integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==, + } + engines: { node: ">=6.9.0" } + "@babel/helper-compilation-targets@7.28.6": resolution: { @@ -946,6 +973,15 @@ packages: } engines: { node: ">=6.9.0" } + "@babel/helper-create-class-features-plugin@7.29.3": + resolution: + { + integrity: sha512-RpLYy2sb51oNLjuu1iD3bwBqCBWUzjO0ocp+iaCP/lJtb2CPLcnC2Fftw+4sAzaMELGeWTgExSKADbdo0GFVzA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + "@babel/helper-globals@7.28.0": resolution: { @@ -953,6 +989,13 @@ packages: } engines: { node: ">=6.9.0" } + "@babel/helper-member-expression-to-functions@7.28.5": + resolution: + { + integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==, + } + engines: { node: ">=6.9.0" } + "@babel/helper-module-imports@7.28.6": resolution: { @@ -969,6 +1012,13 @@ packages: peerDependencies: "@babel/core": ^7.0.0 + "@babel/helper-optimise-call-expression@7.27.1": + resolution: + { + integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==, + } + engines: { node: ">=6.9.0" } + "@babel/helper-plugin-utils@7.28.6": resolution: { @@ -976,6 +1026,22 @@ packages: } engines: { node: ">=6.9.0" } + "@babel/helper-replace-supers@7.28.6": + resolution: + { + integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/helper-skip-transparent-expression-wrappers@7.27.1": + resolution: + { + integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==, + } + engines: { node: ">=6.9.0" } + "@babel/helper-string-parser@7.27.1": resolution: { @@ -1004,6 +1070,14 @@ packages: } engines: { node: ">=6.9.0" } + "@babel/parser@7.25.9": + resolution: + { + integrity: sha512-aI3jjAAO1fh7vY/pBGsn1i9LDbRP43+asrRlkPuTXW5yHXtd1NgTEMudbBoDDxrf1daEEfPJqR+JBMakzrR4Dg==, + } + engines: { node: ">=6.0.0" } + hasBin: true + "@babel/parser@7.29.2": resolution: { @@ -1012,6 +1086,25 @@ packages: engines: { node: ">=6.0.0" } hasBin: true + "@babel/plugin-proposal-decorators@7.24.7": + resolution: + { + integrity: sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-proposal-explicit-resource-management@7.27.4": + resolution: + { + integrity: sha512-1SwtCDdZWQvUU1i7wt/ihP7W38WjC3CSTOHAl+Xnbze8+bbMNjRvRQydnj0k9J1jPqCAZctBFp6NHJXkrVVmEA==, + } + engines: { node: ">=6.9.0" } + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-explicit-resource-management instead. + peerDependencies: + "@babel/core": ^7.0.0-0 + "@babel/plugin-syntax-async-generators@7.8.4": resolution: { @@ -1045,6 +1138,15 @@ packages: peerDependencies: "@babel/core": ^7.0.0-0 + "@babel/plugin-syntax-decorators@7.28.6": + resolution: + { + integrity: sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + "@babel/plugin-syntax-import-attributes@7.28.6": resolution: { @@ -1154,6 +1256,42 @@ packages: peerDependencies: "@babel/core": ^7.0.0-0 + "@babel/plugin-transform-destructuring@7.28.5": + resolution: + { + integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-modules-commonjs@7.28.6": + resolution: + { + integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-typescript@7.28.6": + resolution: + { + integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/preset-typescript@7.24.7": + resolution: + { + integrity: sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + "@babel/runtime@7.29.2": resolution: { @@ -2874,6 +3012,13 @@ packages: } engines: { node: ">=18" } + "@inquirer/checkbox@3.0.1": + resolution: + { + integrity: sha512-0hm2nrToWUdD6/UHnel/UKGdk1//ke5zGUpHIvk5ZWmaKezlGxZkOJXNSWsdxO/rEqTkbB3lNC2J6nBElV2aAQ==, + } + engines: { node: ">=18" } + "@inquirer/checkbox@4.3.2": resolution: { @@ -2886,6 +3031,13 @@ packages: "@types/node": optional: true + "@inquirer/confirm@4.0.1": + resolution: + { + integrity: sha512-46yL28o2NJ9doViqOy0VDcoTzng7rAb6yPQKU7VDLqkmbCaH4JqK4yk4XqlzNWy9PVC5pG1ZUXPBQv+VqnYs2w==, + } + engines: { node: ">=18" } + "@inquirer/confirm@5.1.21": resolution: { @@ -2910,6 +3062,20 @@ packages: "@types/node": optional: true + "@inquirer/core@9.2.1": + resolution: + { + integrity: sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==, + } + engines: { node: ">=18" } + + "@inquirer/editor@3.0.1": + resolution: + { + integrity: sha512-VA96GPFaSOVudjKFraokEEmUQg/Lub6OXvbIEZU1SDCmBzRkHGhxoFAVaF30nyiB4m5cEbDgiI2QRacXZ2hw9Q==, + } + engines: { node: ">=18" } + "@inquirer/editor@4.2.23": resolution: { @@ -2922,6 +3088,13 @@ packages: "@types/node": optional: true + "@inquirer/expand@3.0.1": + resolution: + { + integrity: sha512-ToG8d6RIbnVpbdPdiN7BCxZGiHOTomOX94C2FaT5KOHupV40tKEDozp12res6cMIfRKrXLJyexAZhWVHgbALSQ==, + } + engines: { node: ">=18" } + "@inquirer/expand@4.0.23": resolution: { @@ -2953,6 +3126,13 @@ packages: } engines: { node: ">=18" } + "@inquirer/input@3.0.1": + resolution: + { + integrity: sha512-BDuPBmpvi8eMCxqC5iacloWqv+5tQSJlUafYWUe31ow1BVXjW2a5qe3dh4X/Z25Wp22RwvcaLCc2siHobEOfzg==, + } + engines: { node: ">=18" } + "@inquirer/input@4.3.1": resolution: { @@ -2965,6 +3145,13 @@ packages: "@types/node": optional: true + "@inquirer/number@2.0.1": + resolution: + { + integrity: sha512-QpR8jPhRjSmlr/mD2cw3IR8HRO7lSVOnqUvQa8scv1Lsr3xoAMMworcYW3J13z3ppjBFBD2ef1Ci6AE5Qn8goQ==, + } + engines: { node: ">=18" } + "@inquirer/number@3.0.23": resolution: { @@ -2977,6 +3164,13 @@ packages: "@types/node": optional: true + "@inquirer/password@3.0.1": + resolution: + { + integrity: sha512-haoeEPUisD1NeE2IanLOiFr4wcTXGWrBOyAyPZi1FfLJuXOzNmxCJPgUrGYKVh+Y8hfGJenIfz5Wb/DkE9KkMQ==, + } + engines: { node: ">=18" } + "@inquirer/password@4.0.23": resolution: { @@ -2989,6 +3183,13 @@ packages: "@types/node": optional: true + "@inquirer/prompts@6.0.1": + resolution: + { + integrity: sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A==, + } + engines: { node: ">=18" } + "@inquirer/prompts@7.10.1": resolution: { @@ -3001,6 +3202,13 @@ packages: "@types/node": optional: true + "@inquirer/rawlist@3.0.1": + resolution: + { + integrity: sha512-VgRtFIwZInUzTiPLSfDXK5jLrnpkuSOh1ctfaoygKAdPqjcjKYmGh6sCY1pb0aGnCGsmhUxoqLDUAU0ud+lGXQ==, + } + engines: { node: ">=18" } + "@inquirer/rawlist@4.1.11": resolution: { @@ -3013,6 +3221,13 @@ packages: "@types/node": optional: true + "@inquirer/search@2.0.1": + resolution: + { + integrity: sha512-r5hBKZk3g5MkIzLVoSgE4evypGqtOannnB3PKTG9NRZxyFRKcfzrdxXXPcoJQsxJPzvdSU2Rn7pB7lw0GCmGAg==, + } + engines: { node: ">=18" } + "@inquirer/search@3.2.2": resolution: { @@ -3025,6 +3240,13 @@ packages: "@types/node": optional: true + "@inquirer/select@3.0.1": + resolution: + { + integrity: sha512-lUDGUxPhdWMkN/fHy1Lk7pF3nK1fh/gqeyWXmctefhxLYxlDsc7vsPBEpxrfVGDsVdyYJsiJoD4bJ1b623cV1Q==, + } + engines: { node: ">=18" } + "@inquirer/select@4.4.2": resolution: { @@ -3037,6 +3259,13 @@ packages: "@types/node": optional: true + "@inquirer/type@2.0.0": + resolution: + { + integrity: sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==, + } + engines: { node: ">=18" } + "@inquirer/type@3.0.10": resolution: { @@ -4757,6 +4986,12 @@ packages: cpu: [x64] os: [win32] + "@sec-ant/readable-stream@0.4.1": + resolution: + { + integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==, + } + "@sentry-internal/browser-utils@10.51.0": resolution: { @@ -5118,6 +5353,13 @@ packages: integrity: sha512-brySQQs7Jtn0joV8Xh9ZV/hZb9Ozb0pmazDIASBkYKCjXrXU3mpcFahmK/z4YDhGkQvP9mWJbVyahdtU5wQA+A==, } + "@sindresorhus/merge-streams@4.0.0": + resolution: + { + integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==, + } + engines: { node: ">=18" } + "@sinonjs/commons@3.0.1": resolution: { @@ -5399,6 +5641,44 @@ packages: peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 + "@stryker-mutator/api@8.7.1": + resolution: + { + integrity: sha512-56vxcVxIfW0jxJhr7HB9Zx6Xr5/M95RG9MUK1DtbQhlmQesjpfBBsrPLOPzBJaITPH/vOYykuJ69vgSAMccQyw==, + } + engines: { node: ">=18.0.0" } + + "@stryker-mutator/core@8.7.1": + resolution: + { + integrity: sha512-r2AwhHWkHq6yEe5U8mAzPSWewULbv9YMabLHRzLjZnjj+Ipxtg+Zo22rrUc2Zl7mnYvb9w34bdlEzGz6MKgX2g==, + } + engines: { node: ">=18.0.0" } + hasBin: true + + "@stryker-mutator/instrumenter@8.7.1": + resolution: + { + integrity: sha512-HSq4VHXesQCMR3hr6bn41DAeJ0yuP2vp9KSnls2TySNawFVWOCaKXpBX29Skj3zJQh7dnm7HuQg8HuXvJK15oA==, + } + engines: { node: ">=18.0.0" } + + "@stryker-mutator/util@8.7.1": + resolution: + { + integrity: sha512-Oj/sIHZI1GLfGOHKnud4Gw0ZRufm7ONoQYNnhcaAYEXTWraYVcV7mue/th8fZComTHvDPA8Ge8U16FvWYEb8dg==, + } + + "@stryker-mutator/vitest-runner@8.7.1": + resolution: + { + integrity: sha512-vNRTM6MEy+0hNK5UhJ44euEIRjluDV43UROcMAKIMbT9ELdp8XgM/tA5GrTcp5QadnvrBwvEcCRQk+ARL+e0sg==, + } + engines: { node: ">=14.18.0" } + peerDependencies: + "@stryker-mutator/core": ~8.7.0 + vitest: ">=0.31.2" + "@swc/core-darwin-arm64@1.15.33": resolution: { @@ -6019,6 +6299,12 @@ packages: integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==, } + "@types/mute-stream@0.0.4": + resolution: + { + integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==, + } + "@types/mysql@2.15.27": resolution: { @@ -6161,6 +6447,12 @@ packages: integrity: sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA==, } + "@types/wrap-ansi@3.0.0": + resolution: + { + integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==, + } + "@types/ws@8.18.1": resolution: { @@ -6511,12 +6803,25 @@ packages: integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==, } + ajv@8.17.1: + resolution: + { + integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==, + } + ajv@8.18.0: resolution: { integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==, } + angular-html-parser@6.0.2: + resolution: + { + integrity: sha512-8+sH1TwYxv8XsQes1psxTHMtWRBbJFA/jY0ThqpT4AgCiRdhTtRxru0vlBfyRJpL9CHd3G06k871bR2vyqaM6A==, + } + engines: { node: ">= 14" } + ansi-escapes@4.3.2: resolution: { @@ -6926,6 +7231,13 @@ packages: } engines: { node: ">=10" } + chalk@5.3.0: + resolution: + { + integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==, + } + engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } + chalk@5.6.2: resolution: { @@ -6971,6 +7283,12 @@ packages: integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==, } + chardet@0.7.0: + resolution: + { + integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==, + } + chardet@2.1.1: resolution: { @@ -7451,6 +7769,12 @@ packages: } engines: { node: ">=6" } + des.js@1.1.0: + resolution: + { + integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==, + } + detect-libc@2.1.2: resolution: { @@ -7471,6 +7795,12 @@ packages: integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==, } + diff-match-patch@1.0.5: + resolution: + { + integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==, + } + diff-sequences@29.6.3: resolution: { @@ -7693,6 +8023,12 @@ packages: } engines: { node: ">=12" } + emoji-regex@10.4.0: + resolution: + { + integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==, + } + emoji-regex@10.6.0: resolution: { @@ -8080,6 +8416,13 @@ packages: } engines: { node: ">=10" } + execa@9.4.1: + resolution: + { + integrity: sha512-5eo/BRqZm3GYce+1jqX/tJ7duA2AnE39i88fuedNFUV8XxGxUpF3aWkBRfbUcjV49gCkvS/pzc0YrCPhaIewdg==, + } + engines: { node: ^18.19.0 || >=20.5.0 } + exit@0.1.2: resolution: { @@ -8115,6 +8458,13 @@ packages: } engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + external-editor@3.1.0: + resolution: + { + integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==, + } + engines: { node: ">=4" } + fallow@2.73.0: resolution: { @@ -8202,6 +8552,13 @@ packages: picomatch: optional: true + figures@6.1.0: + resolution: + { + integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==, + } + engines: { node: ">=18" } + file-entry-cache@8.0.0: resolution: { @@ -8216,6 +8573,13 @@ packages: } engines: { node: ">=20" } + file-url@4.0.0: + resolution: + { + integrity: sha512-vRCdScQ6j3Ku6Kd7W1kZk9c++5SqD6Xz5Jotrjr/nkY714M14RFHy/AAVA2WQvpsqVAVgTbDrYyBpU205F0cLw==, + } + engines: { node: ">=12" } + fill-range@7.1.1: resolution: { @@ -8439,6 +8803,13 @@ packages: } engines: { node: ">=10" } + get-stream@9.0.1: + resolution: + { + integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==, + } + engines: { node: ">=18" } + get-tsconfig@4.13.7: resolution: { @@ -8722,6 +9093,13 @@ packages: } engines: { node: ">=10.17.0" } + human-signals@8.0.1: + resolution: + { + integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==, + } + engines: { node: ">=18.18.0" } + husky@9.1.7: resolution: { @@ -8730,6 +9108,13 @@ packages: engines: { node: ">=18" } hasBin: true + iconv-lite@0.4.24: + resolution: + { + integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==, + } + engines: { node: ">=0.10.0" } + iconv-lite@0.6.3: resolution: { @@ -9000,6 +9385,13 @@ packages: } engines: { node: ">=0.12.0" } + is-plain-obj@4.1.0: + resolution: + { + integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==, + } + engines: { node: ">=12" } + is-potential-custom-element-name@1.0.1: resolution: { @@ -9026,6 +9418,13 @@ packages: } engines: { node: ">=8" } + is-stream@4.0.1: + resolution: + { + integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==, + } + engines: { node: ">=18" } + is-typed-array@1.1.15: resolution: { @@ -9039,6 +9438,13 @@ packages: integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==, } + is-unicode-supported@2.1.0: + resolution: + { + integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==, + } + engines: { node: ">=18" } + is-what@5.5.0: resolution: { @@ -9457,6 +9863,12 @@ packages: } engines: { node: ">=10" } + js-md4@0.3.2: + resolution: + { + integrity: sha512-/GDnfQYsltsjRswQhN9fhv3EMw2sCpUdrdxyWDOUK7eyD++r3gRhzgiQgc/x4MAv2i1iuQ4lxO5mvqM3vj4bwA==, + } + js-tokens@10.0.0: resolution: { @@ -9782,6 +10194,12 @@ packages: integrity: sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==, } + lodash.groupby@4.6.0: + resolution: + { + integrity: sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==, + } + lodash.merge@4.6.2: resolution: { @@ -10182,6 +10600,12 @@ packages: } engines: { node: ">=4" } + minimalistic-assert@1.0.1: + resolution: + { + integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==, + } + minimatch@10.2.5: resolution: { @@ -10260,6 +10684,31 @@ packages: integrity: sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA==, } + mutation-testing-elements@3.4.0: + resolution: + { + integrity: sha512-zFJtGlobq+Fyq95JoJj0iqrmwLSLQyIJuDATLwFMDSJCxpGN8kHCA6S4LoLJnkSL6bg4Aqultp8OBSMxGbW3EA==, + } + + mutation-testing-metrics@3.3.0: + resolution: + { + integrity: sha512-vZEJ84SpK3Rwyk7k28SORS5o6ZDtehwifLPH6fQULrozJqlz2Nj8vi52+CjA+aMZCyyKB+9eYUh1HtiWVo4o/A==, + } + + mutation-testing-report-schema@3.3.0: + resolution: + { + integrity: sha512-DF56q0sb0GYzxYUYNdzlfQzyE5oJBEasz8zL76bt3OFJU8q4iHSdUDdihPWWJD+4JLxSs3neM/R968zYdy0SWQ==, + } + + mute-stream@1.0.0: + resolution: + { + integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==, + } + engines: { node: ^14.17.0 || ^16.13.0 || >=18.0.0 } + mute-stream@2.0.0: resolution: { @@ -10393,6 +10842,13 @@ packages: } engines: { node: ">=8" } + npm-run-path@6.0.0: + resolution: + { + integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==, + } + engines: { node: ">=18" } + nwsapi@2.2.23: resolution: { @@ -10488,6 +10944,13 @@ packages: } engines: { node: ">=0.10.0" } + os-tmpdir@1.0.2: + resolution: + { + integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==, + } + engines: { node: ">=0.10.0" } + p-limit@2.3.0: resolution: { @@ -10563,6 +11026,13 @@ packages: } engines: { node: ">=8" } + parse-ms@4.0.0: + resolution: + { + integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==, + } + engines: { node: ">=18" } + parse-passwd@1.0.0: resolution: { @@ -10597,6 +11067,13 @@ packages: } engines: { node: ">=8" } + path-key@4.0.0: + resolution: + { + integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==, + } + engines: { node: ">=12" } + path-parse@1.0.7: resolution: { @@ -10934,6 +11411,13 @@ packages: } engines: { node: ^14.15.0 || ^16.10.0 || >=18.0.0 } + pretty-ms@9.3.0: + resolution: + { + integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==, + } + engines: { node: ">=18" } + prismjs@1.30.0: resolution: { @@ -11436,6 +11920,14 @@ packages: } hasBin: true + semver@7.6.3: + resolution: + { + integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==, + } + engines: { node: ">=10" } + hasBin: true + semver@7.7.4: resolution: { @@ -11655,6 +12147,13 @@ packages: } engines: { node: ">=0.10.0" } + source-map@0.7.6: + resolution: + { + integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==, + } + engines: { node: ">= 12" } + spawn-wrap@2.0.0: resolution: { @@ -11828,6 +12327,13 @@ packages: } engines: { node: ">=6" } + strip-final-newline@4.0.0: + resolution: + { + integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==, + } + engines: { node: ">=18" } + strip-indent@3.0.0: resolution: { @@ -12064,6 +12570,13 @@ packages: } hasBin: true + tmp@0.0.33: + resolution: + { + integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==, + } + engines: { node: ">=0.6.0" } + tmpl@1.0.5: resolution: { @@ -12175,6 +12688,12 @@ packages: } engines: { node: ">=6" } + tslib@2.7.0: + resolution: + { + integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==, + } + tslib@2.8.1: resolution: { @@ -12189,6 +12708,13 @@ packages: engines: { node: ">=18.0.0" } hasBin: true + tunnel@0.0.6: + resolution: + { + integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==, + } + engines: { node: ">=0.6.11 <=0.7.0 || >=0.7.3" } + turbo@2.9.4: resolution: { @@ -12238,6 +12764,20 @@ packages: } engines: { node: ">=12.20" } + typed-inject@4.0.0: + resolution: + { + integrity: sha512-OuBL3G8CJlS/kjbGV/cN8Ni32+ktyyi6ADDZpKvksbX0fYBV5WcukhRCYa7WqLce7dY/Br2dwtmJ9diiadLFpg==, + } + engines: { node: ">=16" } + + typed-rest-client@2.1.0: + resolution: + { + integrity: sha512-Nel9aPbgSzRxfs1+4GoSB4wexCF+4Axlk7OSGVQCMa+4fWcyxIsN/YNmkp0xTT2iQzMD98h8yFLav/cNaULmRA==, + } + engines: { node: ">= 16.0.0" } + typedarray-to-buffer@3.1.5: resolution: { @@ -12269,6 +12809,12 @@ packages: } engines: { node: ">=18" } + underscore@1.13.8: + resolution: + { + integrity: sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==, + } + undici-types@6.21.0: resolution: { @@ -12288,6 +12834,13 @@ packages: } engines: { node: ">=20.18.1" } + unicorn-magic@0.3.0: + resolution: + { + integrity: sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==, + } + engines: { node: ">=18" } + union@0.5.0: resolution: { @@ -12570,6 +13123,12 @@ packages: } engines: { node: ">=10.13.0" } + weapon-regex@1.3.6: + resolution: + { + integrity: sha512-wsf1m1jmMrso5nhwVFJJHSubEBf3+pereGd7+nBKtYJ18KoB/PWJOHS3WRkwS04VrOU0iJr2bZU+l1QaTJ+9nA==, + } + webidl-conversions@3.0.1: resolution: { @@ -12874,6 +13433,13 @@ packages: } engines: { node: ">=18" } + yoctocolors@2.1.2: + resolution: + { + integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==, + } + engines: { node: ">=18" } + zod@3.25.76: resolution: { @@ -12933,6 +13499,26 @@ snapshots: "@babel/compat-data@7.29.0": {} + "@babel/core@7.25.9": + dependencies: + "@ampproject/remapping": 2.3.0 + "@babel/code-frame": 7.29.0 + "@babel/generator": 7.29.1 + "@babel/helper-compilation-targets": 7.28.6 + "@babel/helper-module-transforms": 7.28.6(@babel/core@7.25.9) + "@babel/helpers": 7.29.2 + "@babel/parser": 7.29.2 + "@babel/template": 7.28.6 + "@babel/traverse": 7.29.0 + "@babel/types": 7.29.0 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + "@babel/core@7.29.0": dependencies: "@babel/code-frame": 7.29.0 @@ -12953,6 +13539,13 @@ snapshots: transitivePeerDependencies: - supports-color + "@babel/generator@7.25.9": + dependencies: + "@babel/types": 7.29.0 + "@jridgewell/gen-mapping": 0.3.13 + "@jridgewell/trace-mapping": 0.3.31 + jsesc: 3.1.0 + "@babel/generator@7.29.1": dependencies: "@babel/parser": 7.29.2 @@ -12961,6 +13554,10 @@ snapshots: "@jridgewell/trace-mapping": 0.3.31 jsesc: 3.1.0 + "@babel/helper-annotate-as-pure@7.27.3": + dependencies: + "@babel/types": 7.29.0 + "@babel/helper-compilation-targets@7.28.6": dependencies: "@babel/compat-data": 7.29.0 @@ -12969,8 +13566,28 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 + "@babel/helper-create-class-features-plugin@7.29.3(@babel/core@7.25.9)": + dependencies: + "@babel/core": 7.25.9 + "@babel/helper-annotate-as-pure": 7.27.3 + "@babel/helper-member-expression-to-functions": 7.28.5 + "@babel/helper-optimise-call-expression": 7.27.1 + "@babel/helper-replace-supers": 7.28.6(@babel/core@7.25.9) + "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 + "@babel/traverse": 7.29.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + "@babel/helper-globals@7.28.0": {} + "@babel/helper-member-expression-to-functions@7.28.5": + dependencies: + "@babel/traverse": 7.29.0 + "@babel/types": 7.29.0 + transitivePeerDependencies: + - supports-color + "@babel/helper-module-imports@7.28.6": dependencies: "@babel/traverse": 7.29.0 @@ -12978,6 +13595,15 @@ snapshots: transitivePeerDependencies: - supports-color + "@babel/helper-module-transforms@7.28.6(@babel/core@7.25.9)": + dependencies: + "@babel/core": 7.25.9 + "@babel/helper-module-imports": 7.28.6 + "@babel/helper-validator-identifier": 7.28.5 + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + "@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)": dependencies: "@babel/core": 7.29.0 @@ -12987,8 +13613,28 @@ snapshots: transitivePeerDependencies: - supports-color + "@babel/helper-optimise-call-expression@7.27.1": + dependencies: + "@babel/types": 7.29.0 + "@babel/helper-plugin-utils@7.28.6": {} + "@babel/helper-replace-supers@7.28.6(@babel/core@7.25.9)": + dependencies: + "@babel/core": 7.25.9 + "@babel/helper-member-expression-to-functions": 7.28.5 + "@babel/helper-optimise-call-expression": 7.27.1 + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/helper-skip-transparent-expression-wrappers@7.27.1": + dependencies: + "@babel/traverse": 7.29.0 + "@babel/types": 7.29.0 + transitivePeerDependencies: + - supports-color + "@babel/helper-string-parser@7.27.1": {} "@babel/helper-validator-identifier@7.28.5": {} @@ -13000,10 +13646,31 @@ snapshots: "@babel/template": 7.28.6 "@babel/types": 7.29.0 + "@babel/parser@7.25.9": + dependencies: + "@babel/types": 7.29.0 + "@babel/parser@7.29.2": dependencies: "@babel/types": 7.29.0 + "@babel/plugin-proposal-decorators@7.24.7(@babel/core@7.25.9)": + dependencies: + "@babel/core": 7.25.9 + "@babel/helper-create-class-features-plugin": 7.29.3(@babel/core@7.25.9) + "@babel/helper-plugin-utils": 7.28.6 + "@babel/plugin-syntax-decorators": 7.28.6(@babel/core@7.25.9) + transitivePeerDependencies: + - supports-color + + "@babel/plugin-proposal-explicit-resource-management@7.27.4(@babel/core@7.25.9)": + dependencies: + "@babel/core": 7.25.9 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/plugin-transform-destructuring": 7.28.5(@babel/core@7.25.9) + transitivePeerDependencies: + - supports-color + "@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.0)": dependencies: "@babel/core": 7.29.0 @@ -13024,6 +13691,11 @@ snapshots: "@babel/core": 7.29.0 "@babel/helper-plugin-utils": 7.28.6 + "@babel/plugin-syntax-decorators@7.28.6(@babel/core@7.25.9)": + dependencies: + "@babel/core": 7.25.9 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)": dependencies: "@babel/core": 7.29.0 @@ -13039,6 +13711,11 @@ snapshots: "@babel/core": 7.29.0 "@babel/helper-plugin-utils": 7.28.6 + "@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.25.9)": + dependencies: + "@babel/core": 7.25.9 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)": dependencies: "@babel/core": 7.29.0 @@ -13084,11 +13761,54 @@ snapshots: "@babel/core": 7.29.0 "@babel/helper-plugin-utils": 7.28.6 + "@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.25.9)": + dependencies: + "@babel/core": 7.25.9 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)": dependencies: "@babel/core": 7.29.0 "@babel/helper-plugin-utils": 7.28.6 + "@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.25.9)": + dependencies: + "@babel/core": 7.25.9 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.25.9)": + dependencies: + "@babel/core": 7.25.9 + "@babel/helper-module-transforms": 7.28.6(@babel/core@7.25.9) + "@babel/helper-plugin-utils": 7.28.6 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-typescript@7.28.6(@babel/core@7.25.9)": + dependencies: + "@babel/core": 7.25.9 + "@babel/helper-annotate-as-pure": 7.27.3 + "@babel/helper-create-class-features-plugin": 7.29.3(@babel/core@7.25.9) + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 + "@babel/plugin-syntax-typescript": 7.28.6(@babel/core@7.25.9) + transitivePeerDependencies: + - supports-color + + "@babel/preset-typescript@7.24.7(@babel/core@7.25.9)": + dependencies: + "@babel/core": 7.25.9 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-validator-option": 7.27.1 + "@babel/plugin-syntax-jsx": 7.28.6(@babel/core@7.25.9) + "@babel/plugin-transform-modules-commonjs": 7.28.6(@babel/core@7.25.9) + "@babel/plugin-transform-typescript": 7.28.6(@babel/core@7.25.9) + transitivePeerDependencies: + - supports-color + "@babel/runtime@7.29.2": {} "@babel/template@7.28.6": @@ -13927,6 +14647,14 @@ snapshots: "@inquirer/ansi@1.0.2": {} + "@inquirer/checkbox@3.0.1": + dependencies: + "@inquirer/core": 9.2.1 + "@inquirer/figures": 1.0.15 + "@inquirer/type": 2.0.0 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.3 + "@inquirer/checkbox@4.3.2(@types/node@22.19.17)": dependencies: "@inquirer/ansi": 1.0.2 @@ -13947,6 +14675,11 @@ snapshots: optionalDependencies: "@types/node": 25.5.2 + "@inquirer/confirm@4.0.1": + dependencies: + "@inquirer/core": 9.2.1 + "@inquirer/type": 2.0.0 + "@inquirer/confirm@5.1.21(@types/node@22.19.17)": dependencies: "@inquirer/core": 10.3.2(@types/node@22.19.17) @@ -13987,6 +14720,27 @@ snapshots: optionalDependencies: "@types/node": 25.5.2 + "@inquirer/core@9.2.1": + dependencies: + "@inquirer/figures": 1.0.15 + "@inquirer/type": 2.0.0 + "@types/mute-stream": 0.0.4 + "@types/node": 22.19.17 + "@types/wrap-ansi": 3.0.0 + ansi-escapes: 4.3.2 + cli-width: 4.1.0 + mute-stream: 1.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + + "@inquirer/editor@3.0.1": + dependencies: + "@inquirer/core": 9.2.1 + "@inquirer/type": 2.0.0 + external-editor: 3.1.0 + "@inquirer/editor@4.2.23(@types/node@22.19.17)": dependencies: "@inquirer/core": 10.3.2(@types/node@22.19.17) @@ -14003,6 +14757,12 @@ snapshots: optionalDependencies: "@types/node": 25.5.2 + "@inquirer/expand@3.0.1": + dependencies: + "@inquirer/core": 9.2.1 + "@inquirer/type": 2.0.0 + yoctocolors-cjs: 2.1.3 + "@inquirer/expand@4.0.23(@types/node@22.19.17)": dependencies: "@inquirer/core": 10.3.2(@types/node@22.19.17) @@ -14035,6 +14795,11 @@ snapshots: "@inquirer/figures@1.0.15": {} + "@inquirer/input@3.0.1": + dependencies: + "@inquirer/core": 9.2.1 + "@inquirer/type": 2.0.0 + "@inquirer/input@4.3.1(@types/node@22.19.17)": dependencies: "@inquirer/core": 10.3.2(@types/node@22.19.17) @@ -14049,6 +14814,11 @@ snapshots: optionalDependencies: "@types/node": 25.5.2 + "@inquirer/number@2.0.1": + dependencies: + "@inquirer/core": 9.2.1 + "@inquirer/type": 2.0.0 + "@inquirer/number@3.0.23(@types/node@22.19.17)": dependencies: "@inquirer/core": 10.3.2(@types/node@22.19.17) @@ -14063,6 +14833,12 @@ snapshots: optionalDependencies: "@types/node": 25.5.2 + "@inquirer/password@3.0.1": + dependencies: + "@inquirer/core": 9.2.1 + "@inquirer/type": 2.0.0 + ansi-escapes: 4.3.2 + "@inquirer/password@4.0.23(@types/node@22.19.17)": dependencies: "@inquirer/ansi": 1.0.2 @@ -14079,6 +14855,19 @@ snapshots: optionalDependencies: "@types/node": 25.5.2 + "@inquirer/prompts@6.0.1": + dependencies: + "@inquirer/checkbox": 3.0.1 + "@inquirer/confirm": 4.0.1 + "@inquirer/editor": 3.0.1 + "@inquirer/expand": 3.0.1 + "@inquirer/input": 3.0.1 + "@inquirer/number": 2.0.1 + "@inquirer/password": 3.0.1 + "@inquirer/rawlist": 3.0.1 + "@inquirer/search": 2.0.1 + "@inquirer/select": 3.0.1 + "@inquirer/prompts@7.10.1(@types/node@22.19.17)": dependencies: "@inquirer/checkbox": 4.3.2(@types/node@22.19.17) @@ -14109,6 +14898,12 @@ snapshots: optionalDependencies: "@types/node": 25.5.2 + "@inquirer/rawlist@3.0.1": + dependencies: + "@inquirer/core": 9.2.1 + "@inquirer/type": 2.0.0 + yoctocolors-cjs: 2.1.3 + "@inquirer/rawlist@4.1.11(@types/node@22.19.17)": dependencies: "@inquirer/core": 10.3.2(@types/node@22.19.17) @@ -14125,6 +14920,13 @@ snapshots: optionalDependencies: "@types/node": 25.5.2 + "@inquirer/search@2.0.1": + dependencies: + "@inquirer/core": 9.2.1 + "@inquirer/figures": 1.0.15 + "@inquirer/type": 2.0.0 + yoctocolors-cjs: 2.1.3 + "@inquirer/search@3.2.2(@types/node@22.19.17)": dependencies: "@inquirer/core": 10.3.2(@types/node@22.19.17) @@ -14143,6 +14945,14 @@ snapshots: optionalDependencies: "@types/node": 25.5.2 + "@inquirer/select@3.0.1": + dependencies: + "@inquirer/core": 9.2.1 + "@inquirer/figures": 1.0.15 + "@inquirer/type": 2.0.0 + ansi-escapes: 4.3.2 + yoctocolors-cjs: 2.1.3 + "@inquirer/select@4.4.2(@types/node@22.19.17)": dependencies: "@inquirer/ansi": 1.0.2 @@ -14163,6 +14973,10 @@ snapshots: optionalDependencies: "@types/node": 25.5.2 + "@inquirer/type@2.0.0": + dependencies: + mute-stream: 1.0.0 + "@inquirer/type@3.0.10(@types/node@22.19.17)": optionalDependencies: "@types/node": 22.19.17 @@ -15336,14 +16150,14 @@ snapshots: transitivePeerDependencies: - typescript - "@payloadcms/next@3.81.0(@types/react@19.2.14)(graphql@16.13.2)(monaco-editor@0.55.1)(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)": + "@payloadcms/next@3.81.0(@types/react@19.2.14)(graphql@16.13.2)(monaco-editor@0.55.1)(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)": dependencies: "@dnd-kit/core": 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) "@dnd-kit/modifiers": 9.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4) "@dnd-kit/sortable": 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4) "@payloadcms/graphql": 3.81.0(graphql@16.13.2)(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(typescript@5.9.3) "@payloadcms/translations": 3.81.0 - "@payloadcms/ui": 3.81.0(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + "@payloadcms/ui": 3.81.0(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) busboy: 1.6.0 dequal: 2.0.3 file-type: 21.3.4 @@ -15351,7 +16165,7 @@ snapshots: graphql-http: 1.22.4(graphql@16.13.2) graphql-playground-html: 1.6.30 http-status: 2.1.0 - next: 15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) + next: 15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) path-to-regexp: 6.3.0 payload: 3.81.0(graphql@16.13.2)(typescript@5.9.3) qs-esm: 8.0.1 @@ -15365,14 +16179,14 @@ snapshots: - supports-color - typescript - "@payloadcms/next@3.81.0(graphql@16.13.2)(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)": + "@payloadcms/next@3.81.0(graphql@16.13.2)(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)": dependencies: "@dnd-kit/core": 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) "@dnd-kit/modifiers": 9.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4) "@dnd-kit/sortable": 10.0.0(@dnd-kit/core@6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react@19.2.4) "@payloadcms/graphql": 3.81.0(graphql@16.13.2)(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(typescript@5.9.3) "@payloadcms/translations": 3.81.0 - "@payloadcms/ui": 3.81.0(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + "@payloadcms/ui": 3.81.0(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) busboy: 1.6.0 dequal: 2.0.3 file-type: 21.3.4 @@ -15380,7 +16194,7 @@ snapshots: graphql-http: 1.22.4(graphql@16.13.2) graphql-playground-html: 1.6.30 http-status: 2.1.0 - next: 16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) + next: 16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) path-to-regexp: 6.3.0 payload: 3.81.0(graphql@16.13.2)(typescript@5.9.3) qs-esm: 8.0.1 @@ -15394,7 +16208,7 @@ snapshots: - supports-color - typescript - "@payloadcms/richtext-lexical@3.81.0(@faceless-ui/modal@3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@faceless-ui/scroll-info@2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@payloadcms/next@3.81.0(@types/react@19.2.14)(graphql@16.13.2)(monaco-editor@0.55.1)(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(yjs@13.6.30)": + "@payloadcms/richtext-lexical@3.81.0(@faceless-ui/modal@3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@faceless-ui/scroll-info@2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@payloadcms/next@3.81.0(@types/react@19.2.14)(graphql@16.13.2)(monaco-editor@0.55.1)(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(yjs@13.6.30)": dependencies: "@faceless-ui/modal": 3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) "@faceless-ui/scroll-info": 2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -15409,9 +16223,9 @@ snapshots: "@lexical/selection": 0.41.0 "@lexical/table": 0.41.0 "@lexical/utils": 0.41.0 - "@payloadcms/next": 3.81.0(@types/react@19.2.14)(graphql@16.13.2)(monaco-editor@0.55.1)(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + "@payloadcms/next": 3.81.0(@types/react@19.2.14)(graphql@16.13.2)(monaco-editor@0.55.1)(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) "@payloadcms/translations": 3.81.0 - "@payloadcms/ui": 3.81.0(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + "@payloadcms/ui": 3.81.0(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) "@types/uuid": 10.0.0 acorn: 8.16.0 bson-objectid: 2.0.4 @@ -15440,7 +16254,7 @@ snapshots: - utf-8-validate - yjs - "@payloadcms/richtext-lexical@3.81.0(@faceless-ui/modal@3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@faceless-ui/scroll-info@2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@payloadcms/next@3.81.0(graphql@16.13.2)(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(yjs@13.6.30)": + "@payloadcms/richtext-lexical@3.81.0(@faceless-ui/modal@3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@faceless-ui/scroll-info@2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@payloadcms/next@3.81.0(graphql@16.13.2)(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3))(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)(yjs@13.6.30)": dependencies: "@faceless-ui/modal": 3.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) "@faceless-ui/scroll-info": 2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -15455,9 +16269,9 @@ snapshots: "@lexical/selection": 0.41.0 "@lexical/table": 0.41.0 "@lexical/utils": 0.41.0 - "@payloadcms/next": 3.81.0(graphql@16.13.2)(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + "@payloadcms/next": 3.81.0(graphql@16.13.2)(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) "@payloadcms/translations": 3.81.0 - "@payloadcms/ui": 3.81.0(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) + "@payloadcms/ui": 3.81.0(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) "@types/uuid": 10.0.0 acorn: 8.16.0 bson-objectid: 2.0.4 @@ -15490,7 +16304,7 @@ snapshots: dependencies: date-fns: 4.1.0 - "@payloadcms/ui@3.81.0(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)": + "@payloadcms/ui@3.81.0(@types/react@19.2.14)(monaco-editor@0.55.1)(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)": dependencies: "@date-fns/tz": 1.2.0 "@dnd-kit/core": 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -15505,7 +16319,7 @@ snapshots: date-fns: 4.1.0 dequal: 2.0.3 md5: 2.3.0 - next: 15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) + next: 15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) object-to-formdata: 4.5.1 payload: 3.81.0(graphql@16.13.2)(typescript@5.9.3) qs-esm: 8.0.1 @@ -15525,7 +16339,7 @@ snapshots: - supports-color - typescript - "@payloadcms/ui@3.81.0(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)": + "@payloadcms/ui@3.81.0(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(payload@3.81.0(graphql@16.13.2)(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3)": dependencies: "@date-fns/tz": 1.2.0 "@dnd-kit/core": 6.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -15540,7 +16354,7 @@ snapshots: date-fns: 4.1.0 dequal: 2.0.3 md5: 2.3.0 - next: 16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) + next: 16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) object-to-formdata: 4.5.1 payload: 3.81.0(graphql@16.13.2)(typescript@5.9.3) qs-esm: 8.0.1 @@ -15696,6 +16510,8 @@ snapshots: "@rollup/rollup-win32-x64-msvc@4.60.1": optional: true + "@sec-ant/readable-stream@0.4.1": {} + "@sentry-internal/browser-utils@10.51.0": dependencies: "@sentry/core": 10.51.0 @@ -15811,7 +16627,7 @@ snapshots: "@sentry/core@10.52.0": {} - "@sentry/nextjs@10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.1))(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2)": + "@sentry/nextjs@10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.1))(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2)": dependencies: "@opentelemetry/api": 1.9.1 "@opentelemetry/semantic-conventions": 1.40.0 @@ -15824,7 +16640,7 @@ snapshots: "@sentry/react": 10.51.0(react@19.2.4) "@sentry/vercel-edge": 10.51.0 "@sentry/webpack-plugin": 5.2.1(webpack@5.106.2) - next: 16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) + next: 16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) rollup: 4.60.1 stacktrace-parser: 0.1.11 transitivePeerDependencies: @@ -15836,7 +16652,7 @@ snapshots: - supports-color - webpack - "@sentry/nextjs@10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2)": + "@sentry/nextjs@10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2)": dependencies: "@opentelemetry/api": 1.9.1 "@opentelemetry/semantic-conventions": 1.40.0 @@ -15849,7 +16665,7 @@ snapshots: "@sentry/react": 10.51.0(react@19.2.4) "@sentry/vercel-edge": 10.51.0 "@sentry/webpack-plugin": 5.2.1(webpack@5.106.2) - next: 15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) + next: 15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) rollup: 4.60.1 stacktrace-parser: 0.1.11 transitivePeerDependencies: @@ -15861,7 +16677,7 @@ snapshots: - supports-color - webpack - "@sentry/nextjs@10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2)": + "@sentry/nextjs@10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2)": dependencies: "@opentelemetry/api": 1.9.1 "@opentelemetry/semantic-conventions": 1.40.0 @@ -15874,7 +16690,7 @@ snapshots: "@sentry/react": 10.51.0(react@19.2.4) "@sentry/vercel-edge": 10.51.0 "@sentry/webpack-plugin": 5.2.1(webpack@5.106.2) - next: 16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) + next: 16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0) rollup: 4.60.1 stacktrace-parser: 0.1.11 transitivePeerDependencies: @@ -16071,6 +16887,8 @@ snapshots: "@sinclair/typebox@0.34.49": {} + "@sindresorhus/merge-streams@4.0.0": {} + "@sinonjs/commons@3.0.1": dependencies: type-detect: 4.0.8 @@ -16322,6 +17140,69 @@ snapshots: dependencies: storybook: 8.6.18(prettier@3.8.1) + "@stryker-mutator/api@8.7.1": + dependencies: + mutation-testing-metrics: 3.3.0 + mutation-testing-report-schema: 3.3.0 + tslib: 2.7.0 + typed-inject: 4.0.0 + + "@stryker-mutator/core@8.7.1": + dependencies: + "@inquirer/prompts": 6.0.1 + "@stryker-mutator/api": 8.7.1 + "@stryker-mutator/instrumenter": 8.7.1 + "@stryker-mutator/util": 8.7.1 + ajv: 8.17.1 + chalk: 5.3.0 + commander: 12.1.0 + diff-match-patch: 1.0.5 + emoji-regex: 10.4.0 + execa: 9.4.1 + file-url: 4.0.0 + lodash.groupby: 4.6.0 + minimatch: 9.0.9 + mutation-testing-elements: 3.4.0 + mutation-testing-metrics: 3.3.0 + mutation-testing-report-schema: 3.3.0 + npm-run-path: 6.0.0 + progress: 2.0.3 + rxjs: 7.8.2 + semver: 7.7.4 + source-map: 0.7.6 + tree-kill: 1.2.2 + tslib: 2.7.0 + typed-inject: 4.0.0 + typed-rest-client: 2.1.0 + transitivePeerDependencies: + - supports-color + + "@stryker-mutator/instrumenter@8.7.1": + dependencies: + "@babel/core": 7.25.9 + "@babel/generator": 7.25.9 + "@babel/parser": 7.25.9 + "@babel/plugin-proposal-decorators": 7.24.7(@babel/core@7.25.9) + "@babel/plugin-proposal-explicit-resource-management": 7.27.4(@babel/core@7.25.9) + "@babel/preset-typescript": 7.24.7(@babel/core@7.25.9) + "@stryker-mutator/api": 8.7.1 + "@stryker-mutator/util": 8.7.1 + angular-html-parser: 6.0.2 + semver: 7.6.3 + weapon-regex: 1.3.6 + transitivePeerDependencies: + - supports-color + + "@stryker-mutator/util@8.7.1": {} + + "@stryker-mutator/vitest-runner@8.7.1(@stryker-mutator/core@8.7.1)(vitest@3.2.4(@types/debug@4.1.13)(@types/node@22.19.17)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0))": + dependencies: + "@stryker-mutator/api": 8.7.1 + "@stryker-mutator/core": 8.7.1 + "@stryker-mutator/util": 8.7.1 + tslib: 2.7.0 + vitest: 3.2.4(@types/debug@4.1.13)(@types/node@22.19.17)(happy-dom@20.8.9)(jiti@2.6.1)(jsdom@25.0.1)(lightningcss@1.32.0)(sass@1.99.0)(terser@5.46.2)(tsx@4.21.0)(yaml@2.9.0) + "@swc/core-darwin-arm64@1.15.33": optional: true @@ -16673,6 +17554,10 @@ snapshots: "@types/ms@2.1.0": {} + "@types/mute-stream@0.0.4": + dependencies: + "@types/node": 22.19.17 + "@types/mysql@2.15.27": dependencies: "@types/node": 22.19.17 @@ -16753,6 +17638,8 @@ snapshots: "@types/whatwg-mimetype@3.0.2": {} + "@types/wrap-ansi@3.0.0": {} + "@types/ws@8.18.1": dependencies: "@types/node": 22.19.17 @@ -17065,6 +17952,13 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + ajv@8.18.0: dependencies: fast-deep-equal: 3.1.3 @@ -17072,6 +17966,10 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + angular-html-parser@6.0.2: + dependencies: + tslib: 2.8.1 + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 @@ -17324,6 +18222,8 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chalk@5.3.0: {} + chalk@5.6.2: {} char-regex@1.0.2: {} @@ -17338,6 +18238,8 @@ snapshots: character-reference-invalid@2.0.1: {} + chardet@0.7.0: {} + chardet@2.1.1: {} charenc@0.0.2: {} @@ -17574,6 +18476,11 @@ snapshots: dequal@2.0.3: {} + des.js@1.1.0: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + detect-libc@2.1.2: {} detect-newline@3.1.0: {} @@ -17582,6 +18489,8 @@ snapshots: dependencies: dequal: 2.0.3 + diff-match-patch@1.0.5: {} + diff-sequences@29.6.3: {} diffable-html@4.1.0: @@ -17659,6 +18568,8 @@ snapshots: emittery@0.13.1: {} + emoji-regex@10.4.0: {} + emoji-regex@10.6.0: {} emoji-regex@8.0.0: {} @@ -17960,6 +18871,21 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + execa@9.4.1: + dependencies: + "@sindresorhus/merge-streams": 4.0.0 + cross-spawn: 7.0.6 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 8.0.1 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 6.0.0 + pretty-ms: 9.3.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.1.2 + exit@0.1.2: {} expand-tilde@1.2.2: @@ -17978,6 +18904,12 @@ snapshots: jest-message-util: 29.7.0 jest-util: 29.7.0 + external-editor@3.1.0: + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + fallow@2.73.0: dependencies: detect-libc: 2.1.2 @@ -18025,6 +18957,10 @@ snapshots: optionalDependencies: picomatch: 4.0.4 + figures@6.1.0: + dependencies: + is-unicode-supported: 2.1.0 + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -18038,6 +18974,8 @@ snapshots: transitivePeerDependencies: - supports-color + file-url@4.0.0: {} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -18158,6 +19096,11 @@ snapshots: get-stream@6.0.1: {} + get-stream@9.0.1: + dependencies: + "@sec-ant/readable-stream": 0.4.1 + is-stream: 4.0.1 + get-tsconfig@4.13.7: dependencies: resolve-pkg-maps: 1.0.0 @@ -18353,8 +19296,14 @@ snapshots: human-signals@2.1.0: {} + human-signals@8.0.1: {} + husky@9.1.7: {} + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 @@ -18487,6 +19436,8 @@ snapshots: is-number@7.0.0: {} + is-plain-obj@4.1.0: {} + is-potential-custom-element-name@1.0.1: {} is-reference@1.2.1: @@ -18502,12 +19453,16 @@ snapshots: is-stream@2.0.1: {} + is-stream@4.0.1: {} + is-typed-array@1.1.15: dependencies: which-typed-array: 1.1.20 is-typedarray@1.0.0: {} + is-unicode-supported@2.1.0: {} + is-what@5.5.0: {} is-windows@0.2.0: {} @@ -18995,6 +19950,8 @@ snapshots: joycon@3.1.1: {} + js-md4@0.3.2: {} + js-tokens@10.0.0: {} js-tokens@4.0.0: {} @@ -19174,6 +20131,8 @@ snapshots: lodash.flattendeep@4.4.0: {} + lodash.groupby@4.6.0: {} + lodash.merge@4.6.2: {} lodash@4.18.1: {} @@ -19501,6 +20460,8 @@ snapshots: min-indent@1.0.1: {} + minimalistic-assert@1.0.1: {} + minimatch@10.2.5: dependencies: brace-expansion: 5.0.5 @@ -19546,6 +20507,16 @@ snapshots: multipasta@0.2.7: {} + mutation-testing-elements@3.4.0: {} + + mutation-testing-metrics@3.3.0: + dependencies: + mutation-testing-report-schema: 3.3.0 + + mutation-testing-report-schema@3.3.0: {} + + mute-stream@1.0.0: {} + mute-stream@2.0.0: {} nanoid@3.3.11: {} @@ -19554,7 +20525,7 @@ snapshots: neo-async@2.6.2: {} - next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0): + next@15.5.14(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0): dependencies: "@next/env": 15.5.14 "@swc/helpers": 0.5.15 @@ -19562,7 +20533,7 @@ snapshots: postcss: 8.4.31 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - styled-jsx: 5.1.6(react@19.2.4) + styled-jsx: 5.1.6(@babel/core@7.25.9)(react@19.2.4) optionalDependencies: "@next/swc-darwin-arm64": 15.5.14 "@next/swc-darwin-x64": 15.5.14 @@ -19580,7 +20551,7 @@ snapshots: - "@babel/core" - babel-plugin-macros - next@16.2.2(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0): + next@16.2.2(@babel/core@7.25.9)(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0): dependencies: "@next/env": 16.2.2 "@swc/helpers": 0.5.15 @@ -19589,7 +20560,7 @@ snapshots: postcss: 8.4.31 react: 19.2.4 react-dom: 19.2.4(react@19.2.4) - styled-jsx: 5.1.6(react@19.2.4) + styled-jsx: 5.1.6(@babel/core@7.25.9)(react@19.2.4) optionalDependencies: "@next/swc-darwin-arm64": 16.2.2 "@next/swc-darwin-x64": 16.2.2 @@ -19632,6 +20603,11 @@ snapshots: dependencies: path-key: 3.1.1 + npm-run-path@6.0.0: + dependencies: + path-key: 4.0.0 + unicorn-magic: 0.3.0 + nwsapi@2.2.23: {} nyc@15.1.0: @@ -19707,6 +20683,8 @@ snapshots: os-homedir@1.0.2: {} + os-tmpdir@1.0.2: {} + p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -19759,6 +20737,8 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + parse-ms@4.0.0: {} + parse-passwd@1.0.0: {} parse5@7.3.0: @@ -19771,6 +20751,8 @@ snapshots: path-key@3.1.1: {} + path-key@4.0.0: {} + path-parse@1.0.7: {} path-scurry@1.11.1: @@ -19999,6 +20981,10 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.3.1 + pretty-ms@9.3.0: + dependencies: + parse-ms: 4.0.0 + prismjs@1.30.0: {} process-on-spawn@1.1.0: @@ -20321,6 +21307,8 @@ snapshots: semver@6.3.1: {} + semver@7.6.3: {} + semver@7.7.4: {} seroval-plugins@1.5.2(seroval@1.5.2): @@ -20489,6 +21477,8 @@ snapshots: source-map@0.6.1: {} + source-map@0.7.6: {} + spawn-wrap@2.0.0: dependencies: foreground-child: 2.0.0 @@ -20595,6 +21585,8 @@ snapshots: strip-final-newline@2.0.0: {} + strip-final-newline@4.0.0: {} + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 @@ -20613,10 +21605,12 @@ snapshots: dependencies: "@tokenizer/token": 0.3.0 - styled-jsx@5.1.6(react@19.2.4): + styled-jsx@5.1.6(@babel/core@7.25.9)(react@19.2.4): dependencies: client-only: 0.0.1 react: 19.2.4 + optionalDependencies: + "@babel/core": 7.25.9 stylis@4.2.0: {} @@ -20702,6 +21696,10 @@ snapshots: dependencies: tldts-core: 6.1.86 + tmp@0.0.33: + dependencies: + os-tmpdir: 1.0.2 + tmpl@1.0.5: {} to-no-case@1.0.2: {} @@ -20758,6 +21756,8 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 + tslib@2.7.0: {} + tslib@2.8.1: {} tsx@4.21.0: @@ -20767,6 +21767,8 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + tunnel@0.0.6: {} + turbo@2.9.4: optionalDependencies: "@turbo/darwin-64": 2.9.4 @@ -20790,6 +21792,16 @@ snapshots: type-fest@2.19.0: {} + typed-inject@4.0.0: {} + + typed-rest-client@2.1.0: + dependencies: + des.js: 1.1.0 + js-md4: 0.3.2 + qs: 6.15.1 + tunnel: 0.0.6 + underscore: 1.13.8 + typedarray-to-buffer@3.1.5: dependencies: is-typedarray: 1.0.0 @@ -20809,6 +21821,8 @@ snapshots: uint8array-extras@1.5.0: {} + underscore@1.13.8: {} + undici-types@6.21.0: {} undici-types@7.18.2: @@ -20816,6 +21830,8 @@ snapshots: undici@7.24.4: {} + unicorn-magic@0.3.0: {} + union@0.5.0: dependencies: qs: 6.15.1 @@ -21113,6 +22129,8 @@ snapshots: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 + weapon-regex@1.3.6: {} + webidl-conversions@3.0.1: {} webidl-conversions@7.0.0: {} @@ -21303,6 +22321,8 @@ snapshots: yoctocolors-cjs@2.1.3: {} + yoctocolors@2.1.2: {} + zod@3.25.76: {} zwitch@2.0.4: {} diff --git a/scripts/coverage/mutate.mjs b/scripts/coverage/mutate.mjs new file mode 100644 index 0000000..0c462bc --- /dev/null +++ b/scripts/coverage/mutate.mjs @@ -0,0 +1,158 @@ +#!/usr/bin/env node +// scripts/coverage/mutate.mjs — L3 of the coverage architecture (ADR-020). +// +// Driver for Stryker mutation testing. Discovers every package with a +// stryker.config.json, then runs Stryker per-feature with the feature's +// vitest config + a narrowed mutate scope (entities + use-cases by default, +// per the shared base config). +// +// Usage: +// pnpm mutate # run for every feature with a config +// pnpm mutate -- --filter @repo/auth # run for one feature +// pnpm mutate -- --filter @repo/auth --since main # incremental mode +// pnpm mutate -- --json # machine-readable summary only +// +// This runs Stryker as a child process, not via dynamic import — Stryker's +// runtime expects to own the test process and our wrapping logic keeps the +// integration simple. Stryker handles concurrency internally. + +import fs from "node:fs"; +import path from "node:path"; +import { spawnSync } from "node:child_process"; + +const STRYKER_BIN = "node_modules/.bin/stryker"; + +/** + * Walk packages/* and apps/* for stryker.config.json files. + * Returns: [{ packageDir, packageName, configPath }] + */ +export function discoverStrykerConfigs(repoRoot) { + const out = []; + for (const root of ["packages", "apps"]) { + const dir = path.join(repoRoot, root); + if (!fs.existsSync(dir)) continue; + for (const pkg of fs.readdirSync(dir)) { + const configPath = path.join(dir, pkg, "stryker.config.json"); + if (!fs.existsSync(configPath)) continue; + const pkgJsonPath = path.join(dir, pkg, "package.json"); + let packageName = `${root}/${pkg}`; + if (fs.existsSync(pkgJsonPath)) { + try { + packageName = + JSON.parse(fs.readFileSync(pkgJsonPath, "utf8")).name ?? + packageName; + } catch { + // fall through + } + } + out.push({ + packageDir: path.join(root, pkg), + packageName, + configPath, + }); + } + } + return out.sort((a, b) => a.packageDir.localeCompare(b.packageDir)); +} + +function parseArgs(argv) { + const out = { filter: null, since: null, json: false }; + for (let i = 2; i < argv.length; i++) { + const a = argv[i]; + if (a === "--filter") out.filter = argv[++i]; + else if (a === "--since") out.since = argv[++i]; + else if (a === "--json") out.json = true; + else if (a === "--help" || a === "-h") { + console.log( + "Usage: pnpm mutate [-- --filter ] [--since ] [--json]", + ); + process.exit(0); + } + } + return out; +} + +function main() { + const args = parseArgs(process.argv); + const repoRoot = process.cwd(); + const all = discoverStrykerConfigs(repoRoot); + + const targets = args.filter + ? all.filter( + (c) => + c.packageName === args.filter || c.packageDir.endsWith(args.filter), + ) + : all; + + if (targets.length === 0) { + process.stderr.write( + `[mutate] No stryker.config.json found${args.filter ? ` matching ${args.filter}` : ""}.\n` + + `Each feature wanting L3 mutation needs a stryker.config.json. See docs/guides/coverage.md.\n`, + ); + process.exit(args.filter ? 1 : 0); + } + + const strykerBinAbs = path.join(repoRoot, STRYKER_BIN); + if (!fs.existsSync(strykerBinAbs)) { + process.stderr.write( + `[mutate] Stryker binary not found at ${STRYKER_BIN}. Run \`pnpm install\`.\n`, + ); + process.exit(1); + } + + const results = []; + for (const target of targets) { + if (!args.json) { + process.stderr.write( + `\n[mutate] === ${target.packageName} (${target.packageDir}) ===\n`, + ); + } + + const strykerArgs = ["run", target.configPath]; + if (args.since) { + strykerArgs.push("--since", args.since); + } + + const result = spawnSync(strykerBinAbs, strykerArgs, { + cwd: path.join(repoRoot, target.packageDir), + stdio: args.json ? "pipe" : "inherit", + env: { ...process.env, FORCE_COLOR: args.json ? "0" : "1" }, + }); + + results.push({ + package: target.packageName, + packageDir: target.packageDir, + exitCode: result.status, + status: result.status === 0 ? "pass" : "fail", + }); + + // If a feature fails, continue to next. Surface failures at the end so + // a single broken feature doesn't mask state for the others. + } + + const anyFailed = results.some((r) => r.exitCode !== 0); + + if (args.json) { + process.stdout.write( + JSON.stringify( + { status: anyFailed ? "fail" : "pass", results }, + null, + 2, + ) + "\n", + ); + } else { + process.stderr.write("\n[mutate] Summary:\n"); + for (const r of results) { + process.stderr.write( + ` ${r.status === "pass" ? "✓" : "✗"} ${r.package}\n`, + ); + } + } + + process.exit(anyFailed ? 1 : 0); +} + +const invokedDirectly = import.meta.url === `file://${process.argv[1]}`; +if (invokedDirectly) { + main(); +} diff --git a/scripts/coverage/mutate.test.mjs b/scripts/coverage/mutate.test.mjs new file mode 100644 index 0000000..8911e84 --- /dev/null +++ b/scripts/coverage/mutate.test.mjs @@ -0,0 +1,71 @@ +import { test, describe } from "node:test"; +import assert from "node:assert/strict"; +import fs from "node:fs"; +import path from "node:path"; +import os from "node:os"; +import { discoverStrykerConfigs } from "./mutate.mjs"; + +describe("discoverStrykerConfigs", () => { + test("finds stryker.config.json under packages/* and apps/*", () => { + const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "mutate-disc-")); + try { + fs.mkdirSync(path.join(tmpRoot, "packages", "p1"), { recursive: true }); + fs.mkdirSync(path.join(tmpRoot, "apps", "a1"), { recursive: true }); + fs.mkdirSync(path.join(tmpRoot, "packages", "no-stryker"), { + recursive: true, + }); + fs.writeFileSync( + path.join(tmpRoot, "packages", "p1", "stryker.config.json"), + "{}", + ); + fs.writeFileSync( + path.join(tmpRoot, "packages", "p1", "package.json"), + JSON.stringify({ name: "@repo/p1" }), + ); + fs.writeFileSync( + path.join(tmpRoot, "apps", "a1", "stryker.config.json"), + "{}", + ); + fs.writeFileSync( + path.join(tmpRoot, "apps", "a1", "package.json"), + JSON.stringify({ name: "@repo/a1" }), + ); + + const found = discoverStrykerConfigs(tmpRoot); + assert.equal(found.length, 2); + const names = found.map((f) => f.packageName).sort(); + assert.deepEqual(names, ["@repo/a1", "@repo/p1"]); + } finally { + fs.rmSync(tmpRoot, { recursive: true, force: true }); + } + }); + + test("falls back to packageDir when no package.json", () => { + const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "mutate-disc2-")); + try { + fs.mkdirSync(path.join(tmpRoot, "packages", "no-pkg-json"), { + recursive: true, + }); + fs.writeFileSync( + path.join(tmpRoot, "packages", "no-pkg-json", "stryker.config.json"), + "{}", + ); + + const found = discoverStrykerConfigs(tmpRoot); + assert.equal(found.length, 1); + assert.equal(found[0].packageName, "packages/no-pkg-json"); + } finally { + fs.rmSync(tmpRoot, { recursive: true, force: true }); + } + }); + + test("returns empty when nothing matches", () => { + const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "mutate-disc3-")); + try { + const found = discoverStrykerConfigs(tmpRoot); + assert.deepEqual(found, []); + } finally { + fs.rmSync(tmpRoot, { recursive: true, force: true }); + } + }); +}); diff --git a/turbo/generators/config.ts b/turbo/generators/config.ts index 862b2e1..1aba7e9 100644 --- a/turbo/generators/config.ts +++ b/turbo/generators/config.ts @@ -97,6 +97,11 @@ export default function generator(plop: PlopTypes.NodePlopAPI): void { path: "packages/{{kebabCase name}}/vitest.config.ts", templateFile: "templates/feature/vitest.config.ts.hbs", }, + { + type: "add", + path: "packages/{{kebabCase name}}/stryker.config.json", + templateFile: "templates/feature/stryker.config.json.hbs", + }, { type: "add", path: "packages/{{kebabCase name}}/eslint.config.js", diff --git a/turbo/generators/templates/feature/stryker.config.json.hbs b/turbo/generators/templates/feature/stryker.config.json.hbs new file mode 100644 index 0000000..e8435d3 --- /dev/null +++ b/turbo/generators/templates/feature/stryker.config.json.hbs @@ -0,0 +1,5 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "_comment": "{{kebabCase name}} feature mutation testing config. Extends @repo/core-testing/stryker.base.json (ADR-020 L3). Run with `pnpm mutate --filter @repo/{{kebabCase name}}`.", + "extends": "@repo/core-testing/stryker.base.json" +}