From b57c2bce4e7dfb6c1f05f0f39d95f8130c705d6d Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Tue, 2 Dec 2025 18:34:10 -0500 Subject: [PATCH 01/11] ci: setup danger.js --- .github/workflows/ci.yml | 44 + .gitignore | 6 +- util/danger/README.md | 41 + util/danger/dangerfile.ts | 25 + util/danger/fixtures/sample-pr.json | 36 + util/danger/logic.test.ts | 87 + util/danger/logic.ts | 450 ++++ util/danger/package-lock.json | 3356 +++++++++++++++++++++++++++ util/danger/package.json | 21 + util/danger/run-local.ts | 60 + util/danger/runner.ts | 133 ++ util/danger/tsconfig.json | 18 + 12 files changed, 4276 insertions(+), 1 deletion(-) create mode 100644 util/danger/README.md create mode 100644 util/danger/dangerfile.ts create mode 100644 util/danger/fixtures/sample-pr.json create mode 100644 util/danger/logic.test.ts create mode 100644 util/danger/logic.ts create mode 100644 util/danger/package-lock.json create mode 100644 util/danger/package.json create mode 100644 util/danger/run-local.ts create mode 100644 util/danger/runner.ts create mode 100644 util/danger/tsconfig.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f7c7c4432..3d75bb87a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,20 +9,33 @@ on: tags: - "v*.*.*" + # pull_request runs the matrix/build on the PR head with the fork-scoped token + # (no comment perms on base repo). pull_request: branches: - develop + # pull_request_target runs repo-owned checks (e.g., Danger comments) on the base ref with the base repo token; + # never executes PR code. + pull_request_target: + branches: + - develop + concurrency: group: ${{format('{0}:{1}', github.repository, github.ref)}} cancel-in-progress: true jobs: cpp-matrix: + if: github.event_name != 'pull_request_target' runs-on: ubuntu-24.04 container: image: ubuntu:24.04 name: Generate Test Matrix + # Permissions allow Danger to read PR context and post comments. + permissions: + contents: read + pull-requests: write outputs: matrix: ${{ steps.cpp-matrix.outputs.matrix }} llvm-matrix: ${{ steps.llvm-matrix.outputs.llvm-matrix }} @@ -120,6 +133,7 @@ jobs: node .github/releases-matrix.js build: + if: github.event_name != 'pull_request_target' needs: cpp-matrix strategy: @@ -1293,3 +1307,33 @@ jobs: llvm_dir="/var/www/mrdox.com/llvm+clang" chmod 755 ${{ matrix.llvm-archive-filename }} scp -o StrictHostKeyChecking=no $(pwd)/${{ matrix.llvm-archive-filename }} ubuntu@dev-websites.cpp.al:$llvm_dir/ + + repo-checks: + name: Repo checks + # Run under pull_request_target so we can use the base-repo token to comment on forked PRs + # without executing forked code in this job. Declared after the matrix job so the matrix stays first in the UI. + if: github.event_name == 'pull_request_target' + runs-on: ubuntu-24.04 + permissions: + contents: read + pull-requests: write + issues: write + statuses: write + steps: + - name: Checkout base revision + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install repo-check tools + run: npm --prefix util/danger ci + + - name: Repo checks (Danger) + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: npx --prefix util/danger danger ci --dangerfile util/danger/dangerfile.ts diff --git a/.gitignore b/.gitignore index fe65040f97..bc38aa24e9 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,10 @@ /share/mrdocs/libcxx/ /share/mrdocs/clang/ /docs/modules/reference +/node_modules /.gdbinit /.lldbinit -/.github/node_modules/ \ No newline at end of file +/.github/node_modules/ +/util/danger/node_modules/ +/.roadmap +/AGENTS.md diff --git a/util/danger/README.md b/util/danger/README.md new file mode 100644 index 0000000000..a706c4cb9f --- /dev/null +++ b/util/danger/README.md @@ -0,0 +1,41 @@ +# Danger.js checks for MrDocs + +This directory contains the Danger.js rules and fixtures used in CI to add scoped summaries and hygiene warnings on pull requests. + +## What runs in CI + +- Danger executes via `npx danger ci --dangerfile util/danger/dangerfile.ts` in the `Repo checks` job. +- That job runs on `pull_request_target` so forked PRs get comments/status updates using the base-repo token without executing forked code. +- Permissions are scoped to comment and set statuses (`contents: read`, `pull-requests: write`, `issues: write`, `statuses: write`). +- The job lives in `.github/workflows/ci.yml` after the matrix generator so matrix jobs stay first in the UI. + +## Local usage + +```bash +npm --prefix util/danger ci # install dev deps (without touching the repo root) +npm --prefix util/danger test # run Vitest unit tests for rule logic +npm --prefix util/danger run danger:local # print the fixture report from util/danger/fixtures/sample-pr.json +npm --prefix util/danger run danger:ci # run Danger in CI mode (requires GitHub PR context) +``` + +## Key files + +- `logic.ts` — Pure rule logic: scope mapping, conventional commit validation, size and hygiene warnings. +- `runner.ts` — Minimal Danger runtime glue (fetches commits/files and feeds `logic.ts`). +- `dangerfile.ts` — Entry point passed to `danger ci`; keep thin. +- `fixtures/` — Sample PR payloads for local runs; update alongside rule changes. +- `logic.test.ts` — Vitest coverage for the rule logic. +- `package.json`, `package-lock.json`, `tsconfig.json` — Localized Node setup to avoid polluting the repository root. + +## Conventions + +- Scopes reflect the MrDocs tree: `source`, `tests`, `golden-tests`, `docs`, `ci`, `build`, `tooling`, `third-party`, `other`. +- Conventional commit types allowed: `feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert`. +- Non-test commit size warning triggers around 800 lines of churn (tests and golden fixtures ignored). + +## Updating rules + +- Edit `logic.ts`, refresh `fixtures/` as needed, and run `npm test`. +- Keep warnings human-readable; prefer `warn()` over `fail()` until the team decides otherwise. + +> Note: The Danger.js rules for MrDocs are still experimental, so some warnings may be rough or occasionally fire as false positives—feedback is welcome. diff --git a/util/danger/dangerfile.ts b/util/danger/dangerfile.ts new file mode 100644 index 0000000000..f641245223 --- /dev/null +++ b/util/danger/dangerfile.ts @@ -0,0 +1,25 @@ +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com) +// +// Official repository: https://github.com/cppalliance/mrdocs +// +import { runDanger } from "./runner"; + +// Provided globally by Danger at runtime; declared here for editors/typecheckers. +declare function warn(message: string, file?: string, line?: number): void; + +/** + * Entrypoint for Danger; delegates to the rule runner. + * Wraps execution to surface unexpected errors as warnings instead of failing CI. + */ +export default async function dangerfile(): Promise { + try { + await runDanger(); + } catch (error) { + warn(`Danger checks hit an unexpected error: ${String(error)}`); + } +} diff --git a/util/danger/fixtures/sample-pr.json b/util/danger/fixtures/sample-pr.json new file mode 100644 index 0000000000..5231c327d8 --- /dev/null +++ b/util/danger/fixtures/sample-pr.json @@ -0,0 +1,36 @@ +{ + "files": [ + { "filename": "src/lib/example.cpp", "additions": 120, "deletions": 20 }, + { "filename": "include/mrdocs/example.hpp", "additions": 30, "deletions": 5 }, + { "filename": "test-files/golden-tests/foo/output.xml", "additions": 400, "deletions": 10 }, + { "filename": "docs/modules/ROOT/pages/contribute.adoc", "additions": 12, "deletions": 3 }, + { "filename": ".github/workflows/ci.yml", "additions": 5, "deletions": 1 } + ], + "commits": [ + { + "sha": "abc1234", + "message": "fix(core): handle edge case", + "files": [ + { "filename": "src/lib/example.cpp", "additions": 120, "deletions": 20 }, + { "filename": "include/mrdocs/example.hpp", "additions": 30, "deletions": 5 } + ] + }, + { + "sha": "def5678", + "message": "docs: update contributing notes", + "files": [ + { "filename": "docs/modules/ROOT/pages/contribute.adoc", "additions": 12, "deletions": 3 } + ] + }, + { + "sha": "9999999", + "message": "feat: massive change without tests", + "files": [ + { "filename": "src/lib/another.cpp", "additions": 900, "deletions": 200 } + ] + } + ], + "prBody": "Sample rationale\\n\\nTesting: unit tests locally", + "prTitle": "Sample Danger fixture", + "labels": [] +} diff --git a/util/danger/logic.test.ts b/util/danger/logic.test.ts new file mode 100644 index 0000000000..1cf3fe6076 --- /dev/null +++ b/util/danger/logic.test.ts @@ -0,0 +1,87 @@ +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com) +// +// Official repository: https://github.com/cppalliance/mrdocs +// +import { describe, expect, it } from "vitest"; +import { + commitSizeWarnings, + parseCommitSummary, + basicChecks, + summarizeScopes, + validateCommits, + type CommitInfo, + type DangerInputs, +} from "./logic"; + +describe("parseCommitSummary", () => { + // Ensures we correctly extract type, scope, and subject when format is valid. + it("parses valid commit summaries", () => { + const parsed = parseCommitSummary("fix(core): handle edge case"); + expect(parsed?.type).toBe("fix"); + expect(parsed?.scope).toBe("core"); + expect(parsed?.subject).toBe("handle edge case"); + }); + + // Guards against accepting malformed commit first lines. + it("rejects invalid format", () => { + expect(parseCommitSummary("invalid summary")).toBeNull(); + }); +}); + +describe("summarizeScopes", () => { + // Verifies file paths are bucketed into the correct scopes and totals are tallied. + it("aggregates by scope", () => { + const report = summarizeScopes([ + { filename: "src/lib/file.cpp", additions: 10, deletions: 2 }, + { filename: "src/test/file.cpp", additions: 5, deletions: 1 }, + { filename: "test-files/golden-tests/out.xml", additions: 100, deletions: 0 }, + { filename: "docs/index.adoc", additions: 4, deletions: 0 }, + ]); + + expect(report.totals.source.files).toBe(1); + expect(report.totals.tests.files).toBe(1); + expect(report.totals["golden-tests"].files).toBe(1); + expect(report.totals.docs.files).toBe(1); + expect(report.overall.files).toBe(4); + }); +}); + +describe("commitSizeWarnings", () => { + // Confirms that large non-test churn triggers a warning while ignoring test fixtures. + it("flags large non-test commits", () => { + const commits: CommitInfo[] = [ + { + sha: "abc", + message: "feat: huge change", + files: [ + { filename: "src/lib/large.cpp", additions: 900, deletions: 200 }, + { filename: "test-files/golden-tests/out.xml", additions: 1000, deletions: 0 }, + ], + }, + ]; + const warnings = commitSizeWarnings(commits); + expect(warnings.length).toBe(1); + }); +}); + +describe("starterChecks", () => { + // Checks that source changes without accompanying tests produce a warning. + it("requests tests when source changes without coverage", () => { + const inputs: DangerInputs = { + files: [], + commits: [], + prBody: "Summary\n\nTesting: pending", + prTitle: "Test PR", + labels: [], + }; + const summary = summarizeScopes([{ filename: "src/lib/file.cpp", additions: 1, deletions: 0 }]); + const parsed = validateCommits([{ sha: "1", message: "fix: change" }]).parsed; + const warnings = basicChecks(inputs, summary, parsed); + expect(warnings.some((message) => message.includes("Source changed"))).toBe(true); + }); +}); diff --git a/util/danger/logic.ts b/util/danger/logic.ts new file mode 100644 index 0000000000..113ae90eb2 --- /dev/null +++ b/util/danger/logic.ts @@ -0,0 +1,450 @@ +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com) +// +// Official repository: https://github.com/cppalliance/mrdocs +// +/** + * Semantic areas of the repository used to group diff churn in reports and rules. + */ +type ScopeKey = + | "golden-tests" + | "tests" + | "source" + | "docs" + | "ci" + | "build" + | "tooling" + | "third-party" + | "other"; + +/** + * Minimal file change metadata used for scope aggregation and churn counts. + */ +export interface FileChange { + filename: string; + additions: number; + deletions: number; + status?: string; +} + +/** + * Commit metadata including message and optional per-file stats for size checks. + */ +export interface CommitInfo { + sha: string; + message: string; + files?: FileChange[]; +} + +/** + * Parsed Conventional Commit first-line details extracted from a commit message. + */ +export interface ParsedCommit { + sha: string; + summary: string; + type?: string; + scope?: string; + subject?: string; +} + +/** + * Accumulated churn totals for a single scope. + */ +export interface ScopeTotals { + scope: ScopeKey; + files: number; + additions: number; + deletions: number; +} + +/** + * Scope summary output that is rendered into a Markdown table. + */ +export interface ScopeReport { + totals: Record; + overall: { files: number; additions: number; deletions: number }; + markdown: string; + highlights: string[]; +} + +/** + * Data pulled from the PR that the rules evaluate. + */ +export interface DangerInputs { + files: FileChange[]; + commits: CommitInfo[]; + prBody: string; + prTitle: string; + labels: string[]; +} + +/** + * Final result with warnings and the rendered scope summary. + */ +export interface DangerResult { + warnings: string[]; + summary: ScopeReport; +} + +const allowedTypes = [ + "feat", + "fix", + "docs", + "style", + "refactor", + "perf", + "test", + "build", + "ci", + "chore", + "revert", +]; + +const scopeFormat = /^[a-z0-9._/-]+$/i; +const typeSet = new Set(allowedTypes); +const skipTestLabels = new Set(["no-tests-needed", "skip-tests", "tests-not-required"]); +const skipTestMarkers = ["[skip danger tests]", "[danger skip tests]"]; +const nonTestCommitLimit = 800; + +interface ScopeRule { + scope: ScopeKey; + patterns: RegExp[]; +} + +const scopeRules: ScopeRule[] = [ + { scope: "golden-tests", patterns: [/^test-files\/golden-tests\//i] }, + { + scope: "tests", + patterns: [ + /^src\/test\//i, + /^src\/test_suite\//i, + /^test-files\//i, + /^docs\/website\/snippets\//i, + ], + }, + { + scope: "source", + patterns: [/^src\//i, /^include\//i, /^examples\//i, /^share\//i], + }, + { scope: "docs", patterns: [/^docs\//i, /^README\.adoc$/i, /^Doxyfile/i] }, + { scope: "ci", patterns: [/^\.github\//, /^\.roadmap\//] }, + { + scope: "build", + patterns: [ + /^CMakeLists\.txt$/i, + /^CMakePresets\.json$/i, + /^CMakeUserPresets\.json/i, + /^CMakeUserPresets\.json\.example/i, + /^install\//i, + /^bootstrap\.py$/i, + /^mrdocs\.rnc$/i, + /^mrdocs-config\.cmake\.in$/i, + ], + }, + { scope: "tooling", patterns: [/^util\//i, /^tools\//i] }, + { scope: "third-party", patterns: [/^third-party\//i] }, +]; + +/** + * Normalize a file path for consistent scope matching. + * Converts Windows separators to POSIX to make regex checks reliable. + */ +function normalizePath(path: string): string { + return path.replace(/\\/g, "/"); +} + +/** + * Map a file path to its logical scope based on repository layout. + * + * @param path raw file path from GitHub. + * @returns matched ScopeKey or "other" if no rules match. + */ +function getScope(path: string): ScopeKey { + const normalized = normalizePath(path); + for (const rule of scopeRules) { + if (rule.patterns.some((pattern) => pattern.test(normalized))) { + return rule.scope; + } + } + return "other"; +} + +/** + * Aggregate file-level churn into scope totals and produce a Markdown summary table. + * + * @param files changed files with add/delete counts. + * @returns ScopeReport containing totals, markdown table, and highlight notes. + */ +export function summarizeScopes(files: FileChange[]): ScopeReport { + const totals: Record = { + "golden-tests": { scope: "golden-tests", files: 0, additions: 0, deletions: 0 }, + tests: { scope: "tests", files: 0, additions: 0, deletions: 0 }, + source: { scope: "source", files: 0, additions: 0, deletions: 0 }, + docs: { scope: "docs", files: 0, additions: 0, deletions: 0 }, + ci: { scope: "ci", files: 0, additions: 0, deletions: 0 }, + build: { scope: "build", files: 0, additions: 0, deletions: 0 }, + tooling: { scope: "tooling", files: 0, additions: 0, deletions: 0 }, + "third-party": { scope: "third-party", files: 0, additions: 0, deletions: 0 }, + other: { scope: "other", files: 0, additions: 0, deletions: 0 }, + }; + + let fileCount = 0; + let additions = 0; + let deletions = 0; + + for (const file of files) { + const scope = getScope(file.filename); + totals[scope].files += 1; + totals[scope].additions += file.additions || 0; + totals[scope].deletions += file.deletions || 0; + fileCount += 1; + additions += file.additions || 0; + deletions += file.deletions || 0; + } + + const scopesInOrder: ScopeKey[] = [ + "source", + "tests", + "golden-tests", + "docs", + "ci", + "build", + "tooling", + "third-party", + "other", + ]; + + const nonEmptyScopes = scopesInOrder.filter((scope) => totals[scope].files > 0); + const header = "| Scope | Files | + / - |\n| --- | ---: | ---: |\n"; + const rows = + nonEmptyScopes + .map((scope) => { + const scoped = totals[scope]; + return `| ${scope} | ${scoped.files} | +${scoped.additions} / -${scoped.deletions} |`; + }) + .join("\n") || "| (no changes) | 0 | +0 / -0 |"; + + const highlights = []; + if (totals["golden-tests"].files > 0) { + highlights.push("Golden test fixtures changed"); + } + if (totals.tests.files === 0 && totals.source.files > 0) { + highlights.push("Source updated without test coverage changes"); + } + + const markdown = [ + "### Change summary by scope", + `- Files changed: ${fileCount}`, + `- Total churn: +${additions} / -${deletions}`, + "", + header + rows, + ].join("\n"); + + return { + totals, + overall: { files: fileCount, additions, deletions }, + markdown, + highlights, + }; +} + +/** + * Parse the first line of a commit message using a light Conventional Commit rule. + * + * @param summary first line of the commit message. + * @returns ParsedCommit when format matches, otherwise null. + */ +export function parseCommitSummary(summary: string): ParsedCommit | null { + const match = summary.match(/^(\w+)(?:\(([^)]+)\))?:\s+(.+)$/); + if (!match) { + return null; + } + const [, type, scope, subject] = match; + if (scope && !scopeFormat.test(scope)) { + return null; + } + return { sha: "", summary, type, scope, subject }; +} + +/** + * Validate commit first-line formatting and allowed types. + * + * @param commits list of commits to validate. + * @returns warnings and the parsed commit metadata for downstream checks. + */ +export function validateCommits(commits: CommitInfo[]): { warnings: string[]; parsed: ParsedCommit[] } { + const warnings: string[] = []; + const parsed: ParsedCommit[] = []; + const badFormat: string[] = []; + const badType: string[] = []; + + for (const commit of commits) { + const summary = commit.message.split("\n")[0].trim(); + const parsedLine = parseCommitSummary(summary); + if (!parsedLine) { + // === Conventional Commit format warnings === + badFormat.push(`\`${summary}\``); + parsed.push({ sha: commit.sha, summary }); + continue; + } + + const entry: ParsedCommit = { ...parsedLine, sha: commit.sha, summary }; + parsed.push(entry); + + if (!typeSet.has(parsedLine.type || "")) { + // === Conventional Commit type validation warnings === + badType.push(`\`${summary}\``); + } + } + + if (badFormat.length > 0) { + warnings.push( + [ + "Some commits do not follow Conventional Commit first-line formatting (`type(scope): subject`):", + badFormat.join(", "), + "Examples: `fix: adjust docs link`, `feat(api): allow overrides`.", + ].join(" "), + ); + } + + if (badType.length > 0) { + warnings.push( + [ + `Commit types must be one of ${allowedTypes.join(", ")}.`, + "These commits need attention:", + badType.join(", "), + ].join(" "), + ); + } + + return { warnings, parsed }; +} + +/** + * Warn when a single commit changes too many non-test lines to encourage smaller slices. + * + * @param commits commits with per-file stats. + * @returns warning messages for commits that exceed the threshold. + */ +export function commitSizeWarnings(commits: CommitInfo[]): string[] { + const messages: string[] = []; + for (const commit of commits) { + if (!commit.files || commit.files.length === 0) { + continue; + } + + let churn = 0; + for (const file of commit.files) { + const scope = getScope(file.filename); + if (scope === "tests" || scope === "golden-tests") { + continue; + } + churn += (file.additions || 0) + (file.deletions || 0); + } + + if (churn > nonTestCommitLimit) { + const shortSha = commit.sha.substring(0, 7); + // === Commit size warnings (non-test churn) === + messages.push( + `Commit \`${shortSha}\` changes ${churn} non-test lines. Consider splitting it into smaller, reviewable chunks.`, + ); + } + } + return messages; +} + +/** + * Check for explicit signals to skip source-vs-test warnings. + * + * @param prBody pull request body text. + * @param labels labels applied to the pull request. + * @returns true when skip markers or labels are present. + */ +function hasSkipTests(prBody: string, labels: string[]): boolean { + if (labels.some((label) => skipTestLabels.has(label))) { + return true; + } + const body = prBody.toLowerCase(); + return skipTestMarkers.some((marker) => body.includes(marker)); +} + +/** + * Additional hygiene checks around PR description, test coverage signals, and coherence. + * + * @param input PR metadata and labels. + * @param scopes aggregated scope summary. + * @param parsedCommits parsed commit metadata for type checks. + * @returns warning messages for hygiene gaps. + */ +export function basicChecks(input: DangerInputs, scopes: ScopeReport, parsedCommits: ParsedCommit[]): string[] { + const warnings: string[] = []; + + const cleanedBody = (input.prBody || "").trim(); + if (cleanedBody.length < 40) { + // === PR description completeness warnings === + warnings.push("PR description looks empty. Please add a short rationale and testing notes."); + } else if (!/test(ed|ing)?/i.test(cleanedBody)) { + // === Missing testing notes warnings === + warnings.push("Add a brief note about how this change was tested (or why tests are not needed)."); + } + + const skipTests = hasSkipTests(input.prBody || "", input.labels); + if ( + !skipTests && + scopes.totals.source.files > 0 && + scopes.totals.tests.files === 0 && + scopes.totals["golden-tests"].files === 0 + ) { + // === Source changes without tests/fixtures warnings === + warnings.push( + "Source changed but no tests or fixtures were updated. Add coverage or label with `no-tests-needed` / `[skip danger tests]` when appropriate.", + ); + } + + const commitTypes = new Set(parsedCommits.map((commit) => commit.type).filter(Boolean) as string[]); + const totalFiles = Object.values(scopes.totals).reduce((sum, scope) => sum + scope.files, 0); + const nonDocFiles = totalFiles - scopes.totals.docs.files; + const testFiles = scopes.totals.tests.files + scopes.totals["golden-tests"].files; + const nonTestFiles = totalFiles - testFiles; + + const docOnlyChange = + scopes.totals.docs.files > 0 && + nonDocFiles === 0; + + if (docOnlyChange && ["feat", "fix", "refactor", "perf"].some((type) => commitTypes.has(type))) { + // === Docs-only change with feature/fix commit types warnings === + warnings.push("Commits look like feature/fix work, but the PR only changes docs. Double-check commit types."); + } + + const testsOnlyChange = testFiles > 0 && nonTestFiles === 0; + + if (testsOnlyChange && ["feat", "fix"].some((type) => commitTypes.has(type))) { + // === Tests-only change with feature/fix commit types warnings === + warnings.push("Commits are marked as feature/fix, but the diff only touches tests. Consider a `test:` type instead."); + } + + return warnings; +} + +/** + * Entry point: evaluate PR inputs and return scope summary plus warning messages. + * + * @param input files, commits, labels, and PR text gathered by the runner. + * @returns warnings and a scope summary for rendering in Danger. + */ +export function evaluateDanger(input: DangerInputs): DangerResult { + const summary = summarizeScopes(input.files); + const commitValidation = validateCommits(input.commits); + + const warnings = [ + ...commitValidation.warnings, + ...commitSizeWarnings(input.commits), + ...basicChecks(input, summary, commitValidation.parsed), + ]; + + return { warnings, summary }; +} diff --git a/util/danger/package-lock.json b/util/danger/package-lock.json new file mode 100644 index 0000000000..837e77c204 --- /dev/null +++ b/util/danger/package-lock.json @@ -0,0 +1,3356 @@ +{ + "name": "mrdocs-danger", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mrdocs-danger", + "version": "0.0.0", + "license": "BSL-1.0", + "devDependencies": { + "@types/node": "^20.14.2", + "danger": "^12.3.1", + "ts-node": "^10.9.2", + "typescript": "^5.4.5", + "vitest": "^1.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@gitbeaker/core": { + "version": "38.12.1", + "resolved": "https://registry.npmjs.org/@gitbeaker/core/-/core-38.12.1.tgz", + "integrity": "sha512-8XMVcBIdVAAoxn7JtqmZ2Ee8f+AZLcCPmqEmPFOXY2jPS84y/DERISg/+sbhhb18iRy+ZsZhpWgQ/r3CkYNJOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@gitbeaker/requester-utils": "^38.12.1", + "qs": "^6.11.1", + "xcase": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@gitbeaker/requester-utils": { + "version": "38.12.1", + "resolved": "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-38.12.1.tgz", + "integrity": "sha512-Rc/DgngS0YPN+AY1s9UnexKSy4Lh0bkQVAq9p7PRbRpXb33SlTeCg8eg/8+A/mrMcHgYmP0XhH8lkizyA5tBUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "qs": "^6.11.1", + "xcase": "^2.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@gitbeaker/rest": { + "version": "38.12.1", + "resolved": "https://registry.npmjs.org/@gitbeaker/rest/-/rest-38.12.1.tgz", + "integrity": "sha512-9KMSDtJ/sIov+5pcH+CAfiJXSiuYgN0KLKQFg0HHWR2DwcjGYkcbmhoZcWsaOWOqq4kihN1l7wX91UoRxxKKTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@gitbeaker/core": "^38.12.1", + "@gitbeaker/requester-utils": "^38.12.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "node_modules/@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", + "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^6.40.0" + }, + "peerDependencies": { + "@octokit/core": ">=2" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", + "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^6.39.0", + "deprecation": "^2.3.1" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/rest": { + "version": "18.12.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", + "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + } + }, + "node_modules/@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^12.11.0" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.19.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz", + "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@vitest/expect": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.1.tgz", + "integrity": "sha512-jXL+9+ZNIJKruofqXuuTClf44eSpcHlgj3CiuNihUF3Ioujtmc0zIa3UJOW5RjDK1YLBJZnWBlPuqhYycLioog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "1.6.1", + "@vitest/utils": "1.6.1", + "chai": "^4.3.10" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.1.tgz", + "integrity": "sha512-3nSnYXkVkf3mXFfE7vVyPmi3Sazhb/2cfZGGs0JRzFsPFvAMBEcrweV1V1GsrstdXeKCTXlJbvnQwGWgEIHmOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "1.6.1", + "p-limit": "^5.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-5.0.0.tgz", + "integrity": "sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/snapshot": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.1.tgz", + "integrity": "sha512-WvidQuWAzU2p95u8GAKlRMqMyN1yOJkGHnx3M1PL9Raf7AQ1kwLKg04ADlCa3+OXUZE7BceOhVZiuWAbzCKcUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.1.tgz", + "integrity": "sha512-MGcMmpGkZebsMZhbQKkAf9CX5zGvjkBTqf8Zx3ApYWXr3wG+QvEu2eXWfnIIWYSJExIp4V9FCKDEeygzkYrXMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^2.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.1.tgz", + "integrity": "sha512-jOrrUvXM4Av9ZWiG1EajNto0u96kWAhJ1LmPmJhXXQx/32MecEKd10pOLYgS2BQx1TgkGhloPU1ArDW2vvaY6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "diff-sequences": "^29.6.3", + "estree-walker": "^3.0.3", + "loupe": "^2.3.7", + "pretty-format": "^29.7.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/async-retry": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.2.3.tgz", + "integrity": "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "retry": "0.12.0" + } + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/chai": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", + "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", + "pathval": "^1.1.1", + "type-detect": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-js": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.47.0.tgz", + "integrity": "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/danger": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/danger/-/danger-12.3.4.tgz", + "integrity": "sha512-esr6iowAryWjWkMzOKyOmMRkamPkDRhC6OAj2tO48i0oobObdP0d8I/YE+qSj9m+/RRcrhaKnysvPL51eW1m3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@gitbeaker/rest": "^38.0.0", + "@octokit/rest": "^18.12.0", + "async-retry": "1.2.3", + "chalk": "^2.3.0", + "commander": "^2.18.0", + "core-js": "^3.8.2", + "debug": "^4.1.1", + "fast-json-patch": "^3.0.0-1", + "get-stdin": "^6.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "hyperlinker": "^1.0.0", + "json5": "^2.2.3", + "jsonpointer": "^5.0.0", + "jsonwebtoken": "^9.0.0", + "lodash.find": "^4.6.0", + "lodash.includes": "^4.3.0", + "lodash.isobject": "^3.0.2", + "lodash.keys": "^4.0.8", + "lodash.mapvalues": "^4.6.0", + "lodash.memoize": "^4.1.2", + "memfs-or-file-map-to-github-branch": "^1.2.1", + "micromatch": "^4.0.4", + "node-cleanup": "^2.1.2", + "node-fetch": "^2.6.7", + "override-require": "^1.1.1", + "p-limit": "^2.1.0", + "parse-diff": "^0.7.0", + "parse-git-config": "^2.0.3", + "parse-github-url": "^1.0.2", + "parse-link-header": "^2.0.0", + "pinpoint": "^1.1.0", + "prettyjson": "^1.2.1", + "readline-sync": "^1.4.9", + "regenerator-runtime": "^0.13.9", + "require-from-string": "^2.0.2", + "supports-hyperlinks": "^1.0.1" + }, + "bin": { + "danger": "distribution/commands/danger.js", + "danger-ci": "distribution/commands/danger-ci.js", + "danger-init": "distribution/commands/danger-init.js", + "danger-js": "distribution/commands/danger.js", + "danger-local": "distribution/commands/danger-local.js", + "danger-pr": "distribution/commands/danger-pr.js", + "danger-process": "distribution/commands/danger-process.js", + "danger-reset-status": "distribution/commands/danger-reset-status.js", + "danger-runner": "distribution/commands/danger-runner.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-json-patch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stdin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", + "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-config-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-1.0.1.tgz", + "integrity": "sha512-KcJ2dlrrP5DbBnYIZ2nlikALfRhKzNSX0stvv3ImJ+fvC4hXKoV+U+74SV0upg+jlQZbrtQzc0bu6/Zh+7aQbg==", + "dev": true, + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "fs-exists-sync": "^0.1.0", + "homedir-polyfill": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=16.17.0" + } + }, + "node_modules/hyperlinker": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hyperlinker/-/hyperlinker-1.0.0.tgz", + "integrity": "sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/local-pkg": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.1.tgz", + "integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mlly": "^1.7.3", + "pkg-types": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/lodash.find": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", + "integrity": "sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isobject": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", + "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-4.2.0.tgz", + "integrity": "sha512-J79MkJcp7Df5mizHiVNpjoHXLi4HLjh9VLS/M7lQSGoQ+0oQ+lWEigREkqKyizPB1IawvQLLKY8mzEcm1tkyxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "dev": true, + "license": "MIT" + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memfs-or-file-map-to-github-branch": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/memfs-or-file-map-to-github-branch/-/memfs-or-file-map-to-github-branch-1.3.0.tgz", + "integrity": "sha512-AzgIEodmt51dgwB3TmihTf1Fh2SmszdZskC6trFHy4v71R5shLmdjJSYI7ocVfFa7C/TE6ncb0OZ9eBg2rmkBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/rest": "*" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mlly": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz", + "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.1" + } + }, + "node_modules/mlly/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-cleanup": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", + "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/override-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/override-require/-/override-require-1.1.1.tgz", + "integrity": "sha512-eoJ9YWxFcXbrn2U8FKT6RV+/Kj7fiGAB1VvHzbYKt8xM5ZuKZgCGvnHzDxmreEjcBH28ejg5MiOH4iyY1mQnkg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-diff": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.7.1.tgz", + "integrity": "sha512-1j3l8IKcy4yRK2W4o9EYvJLSzpAVwz4DXqCewYyx2vEwk2gcf3DBPqc8Fj4XV3K33OYJ08A8fWwyu/ykD/HUSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/parse-git-config": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-2.0.3.tgz", + "integrity": "sha512-Js7ueMZOVSZ3tP8C7E3KZiHv6QQl7lnJ+OkbxoaFazzSa2KyEHqApfGbU3XboUgUnq4ZuUmskUpYKTNx01fm5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "expand-tilde": "^2.0.2", + "git-config-path": "^1.0.1", + "ini": "^1.3.5" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-github-url": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.3.tgz", + "integrity": "sha512-tfalY5/4SqGaV/GIGzWyHnFjlpTPTNpENR9Ea2lLldSJ8EWXMsvacWucqY3m3I4YPtas15IxTLQVQ5NSYXPrww==", + "dev": true, + "license": "MIT", + "bin": { + "parse-github-url": "cli.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse-link-header": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-link-header/-/parse-link-header-2.0.0.tgz", + "integrity": "sha512-xjU87V0VyHZybn2RrCX5TIFGxTVZE6zqqZWMPlIKiSKuWh/X5WZdt+w1Ki1nXB+8L/KtL+nZ4iq+sfI6MrhhMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "xtend": "~4.0.1" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinpoint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pinpoint/-/pinpoint-1.1.0.tgz", + "integrity": "sha512-+04FTD9x7Cls2rihLlo57QDCcHoLBGn5Dk51SwtFBWkUWLxZaBXyNVpCw1S+atvE7GmnFjeaRZ0WLq3UYuqAdg==", + "dev": true, + "license": "MIT" + }, + "node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/pkg-types/node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/prettyjson": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-1.2.5.tgz", + "integrity": "sha512-rksPWtoZb2ZpT5OVgtmy0KHVM+Dca3iVwWY9ifwhcexfjebtgjg3wmrUt9PvJ59XIYBcknQeYHD8IAnVlh9lAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "colors": "1.4.0", + "minimist": "^1.2.0" + }, + "bin": { + "prettyjson": "bin/prettyjson" + } + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/readline-sync": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", + "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true, + "license": "MIT" + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/rollup": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-2.1.1.tgz", + "integrity": "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz", + "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^2.0.0", + "supports-color": "^5.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.8.4.tgz", + "integrity": "sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.1.tgz", + "integrity": "sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.1.tgz", + "integrity": "sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.1.tgz", + "integrity": "sha512-Ljb1cnSJSivGN0LqXd/zmDbWEM0RNNg2t1QW/XUhYl/qPqyu7CsqeWtqQXHVaJsecLPuDoak2oJcZN2QoRIOag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "1.6.1", + "@vitest/runner": "1.6.1", + "@vitest/snapshot": "1.6.1", + "@vitest/spy": "1.6.1", + "@vitest/utils": "1.6.1", + "acorn-walk": "^8.3.2", + "chai": "^4.3.10", + "debug": "^4.3.4", + "execa": "^8.0.1", + "local-pkg": "^0.5.0", + "magic-string": "^0.30.5", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.5.0", + "strip-literal": "^2.0.0", + "tinybench": "^2.5.1", + "tinypool": "^0.8.3", + "vite": "^5.0.0", + "vite-node": "1.6.1", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "1.6.1", + "@vitest/ui": "1.6.1", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xcase": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/xcase/-/xcase-2.0.1.tgz", + "integrity": "sha512-UmFXIPU+9Eg3E9m/728Bii0lAIuoc+6nbrNUKaRPJOFp91ih44qqGlWtxMB6kXFrRD6po+86ksHM5XHCfk6iPw==", + "dev": true, + "license": "MIT" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/util/danger/package.json b/util/danger/package.json new file mode 100644 index 0000000000..16105f50f8 --- /dev/null +++ b/util/danger/package.json @@ -0,0 +1,21 @@ +{ + "name": "mrdocs-danger", + "version": "0.0.0", + "private": true, + "license": "BSL-1.0", + "engines": { + "node": ">=18" + }, + "scripts": { + "test": "vitest run", + "danger:ci": "danger ci --dangerfile dangerfile.ts", + "danger:local": "ts-node --project tsconfig.json run-local.ts" + }, + "devDependencies": { + "@types/node": "^20.14.2", + "danger": "^12.3.1", + "ts-node": "^10.9.2", + "typescript": "^5.4.5", + "vitest": "^1.6.0" + } +} diff --git a/util/danger/run-local.ts b/util/danger/run-local.ts new file mode 100644 index 0000000000..63264c2709 --- /dev/null +++ b/util/danger/run-local.ts @@ -0,0 +1,60 @@ +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com) +// +// Official repository: https://github.com/cppalliance/mrdocs +// +import { readFileSync } from "fs"; +import path from "path"; +import { evaluateDanger, type DangerInputs } from "./logic"; + +/** + * Load a JSON fixture from disk and parse into DangerInputs. + * + * @param fixturePath path to the fixture file (absolute or relative). + * @returns parsed DangerInputs used to simulate a PR. + */ +function loadFixture(fixturePath: string): DangerInputs { + const resolved = path.isAbsolute(fixturePath) ? fixturePath : path.join(process.cwd(), fixturePath); + const raw = readFileSync(resolved, "utf8"); + return JSON.parse(raw) as DangerInputs; +} + +/** + * Print a human-readable report for local runs. + * + * @param result evaluated Danger outputs to render. + */ +function printResult(result: ReturnType): void { + console.log(result.summary.markdown); + if (result.summary.highlights.length > 0) { + console.log("\nHighlights:"); + for (const note of result.summary.highlights) { + console.log(`- ${note}`); + } + } + if (result.warnings.length > 0) { + console.log("\nWarnings:"); + for (const message of result.warnings) { + console.log(`- ${message}`); + } + } +} + +/** + * CLI entry: load a fixture (default sample) and print the evaluation summary. + * + * @remarks + * This avoids GitHub calls so rule changes can be iterated locally. + */ +function main(): void { + const fixtureArg = process.argv[2] || path.join(__dirname, "fixtures/sample-pr.json"); + const inputs = loadFixture(fixtureArg); + const result = evaluateDanger(inputs); + printResult(result); +} + +main(); diff --git a/util/danger/runner.ts b/util/danger/runner.ts new file mode 100644 index 0000000000..4e7bbcb918 --- /dev/null +++ b/util/danger/runner.ts @@ -0,0 +1,133 @@ +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com) +// +// Official repository: https://github.com/cppalliance/mrdocs +// +import type { DangerDSLType } from "danger"; +import { evaluateDanger, type CommitInfo, type FileChange } from "./logic"; + +// Danger provides these as globals at runtime; we declare them for editors/typecheckers. +declare const danger: DangerDSLType; +declare function warn(message: string, file?: string, line?: number): void; +declare function markdown(message: string, file?: string, line?: number): void; + +/** + * Retrieve the list of changed files with basic stats for scope summaries. + * + * @returns files touched in the PR including add/delete counts. + */ +async function fetchChangedFiles(): Promise { + const api = danger.github.api; + const pr = danger.github.pr; + const files: FileChange[] = []; + let page = 1; + + while (true) { + const response = await api.pulls.listFiles({ + owner: pr.base.repo.owner.login, + repo: pr.base.repo.name, + pull_number: pr.number, + per_page: 100, + page, + }); + + for (const file of response.data) { + files.push({ + filename: file.filename, + additions: file.additions ?? 0, + deletions: file.deletions ?? 0, + status: file.status, + }); + } + + if (response.data.length < 100) { + break; + } + page += 1; + } + + return files; +} + +/** + * Pull commit messages and per-commit file stats so size checks can ignore test churn. + * + * @returns commits enriched with file-level additions/deletions. + */ +async function fetchCommitDetails(): Promise { + const api = danger.github.api; + const commits = danger.github.commits; + const pr = danger.github.pr; + const owner = pr.base.repo.owner.login; + const repo = pr.base.repo.name; + + const enriched: CommitInfo[] = []; + for (const commit of commits) { + let files: FileChange[] | undefined; + try { + const response = await api.repos.getCommit({ + owner, + repo, + ref: commit.sha, + }); + files = (response.data.files || []).map((file) => ({ + filename: file.filename, + additions: file.additions ?? 0, + deletions: file.deletions ?? 0, + status: file.status, + })); + } catch (error) { + warn(`Unable to load file stats for commit ${commit.sha}: ${String(error)}`); + } + + enriched.push({ + sha: commit.sha, + message: commit.commit.message, + files, + }); + } + return enriched; +} + +/** + * Main runner: gathers PR context and feeds it into rule evaluation. + */ +export async function runDanger(): Promise { + if (!danger.github || !danger.github.pr) { + markdown("Danger checks are only available on pull requests."); + return; + } + + const [files, commits] = await Promise.all([fetchChangedFiles(), fetchCommitDetails()]); + const pr = danger.github.pr; + const labels = (danger.github.issue?.labels || []).map((label) => label.name); + + const result = evaluateDanger({ + files, + commits, + prBody: pr.body || "", + prTitle: pr.title || "", + labels, + }); + + const experimentalNote = + "\n_Note: Danger.js checks for MrDocs are experimental; some warnings may still be noisy or false positives._"; + + markdown( + [ + result.summary.markdown, + result.summary.highlights.length > 0 ? "\n**Highlights:**\n- " + result.summary.highlights.join("\n- ") : "", + experimentalNote, + ] + .filter(Boolean) + .join("\n"), + ); + + for (const message of result.warnings) { + warn(message); + } +} diff --git a/util/danger/tsconfig.json b/util/danger/tsconfig.json new file mode 100644 index 0000000000..01c3191cbc --- /dev/null +++ b/util/danger/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "CommonJS", + "moduleResolution": "Node", + "esModuleInterop": true, + "resolveJsonModule": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "types": ["node", "danger"], + "outDir": "dist" + }, + "include": [ + "dangerfile.ts", + "**/*.ts" + ] +} From cb11fc4ded0748f8bb1cb63ed4082a98cbf75e04 Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Tue, 2 Dec 2025 18:39:44 -0500 Subject: [PATCH 02/11] build: remove CMakeUserPresets.json.example The example file is no longer necessary because the real file can be generated with bootstrap.py. Additionally, bootstrap.py generates user presets without extra noise and unused presets. --- CMakeUserPresets.json.example | 438 ---------------------------------- 1 file changed, 438 deletions(-) delete mode 100644 CMakeUserPresets.json.example diff --git a/CMakeUserPresets.json.example b/CMakeUserPresets.json.example deleted file mode 100644 index e04454a031..0000000000 --- a/CMakeUserPresets.json.example +++ /dev/null @@ -1,438 +0,0 @@ -{ - "version": 3, - "cmakeMinimumRequired": { - "major": 3, - "minor": 10, - "patch": 0 - }, - "configurePresets": [ - { - "name": "debug-msvc", - "displayName": "Debug MSVC", - "description": "Build on Windows + MSVC natively (Debug)", - "inherits": "debug", - "generator": "Ninja", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "LLVM_ROOT": "C:\\Users\\$env{USERNAME}\\Libraries\\llvm\\install\\MSVC\\Debug", - "Clang_ROOT": "C:\\Users\\$env{USERNAME}\\Libraries\\llvm\\install\\MSVC\\Debug", - "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", - "CMAKE_CXX_FLAGS": "/W4", - "CMAKE_C_FLAGS": "/W4" - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - } - }, - { - "name": "release-msvc", - "displayName": "Release MSVC", - "description": "Build on Windows + MSVC natively (Release)", - "inherits": "debug-msvc", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "LLVM_ROOT": "C:\\Users\\$env{USERNAME}\\Libraries\\llvm\\Release", - "Clang_ROOT": "C:\\Users\\$env{USERNAME}\\Libraries\\llvm\\Release" - } - }, - { - "name": "debug-wsl-gcc", - "displayName": "Debug WSL GCC", - "description": "Build on WSL + GCC (Debug). Windows developers can use this preset to catch GCC-specific issues with WSL. WSL tends to be very slow, so this is not recommended for interactive development.", - "inherits": "debug", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_CXX_COMPILER": "/usr/bin/g++", - "CMAKE_C_COMPILER": "/usr/bin/gcc", - "LLVM_ROOT": "${sourceDir}/build/third-party/llvm", - "Clang_ROOT": "${sourceDir}/build/third-party/llvm", - "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", - "CMAKE_CXX_FLAGS": "-Wall -Wextra -Werror", - "CMAKE_C_FLAGS": "-Wall -Wextra -Werror" - }, - "vendor": { - "microsoft.com/VisualStudioSettings/CMake/1.0": { - "hostOS": [ - "Linux" - ], - "intelliSenseMode": "windows-msvc-x64" - }, - "jetbrains.com/clion": { - "toolchain": "WSL GCC" - } - } - }, - { - "name": "debug-wsl-gcc-asan", - "displayName": "Debug WSL GCC AddressSanitizer", - "description": "Build on WSL + GCC with AddressSanitizer (Debug). This is useful for catching memory issues.", - "inherits": "debug-wsl-gcc", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_CXX_FLAGS": "-fsanitize=address -fno-omit-frame-pointer -g -O0 -fno-inline-functions" - } - }, - { - "name": "release-wsl-gcc", - "displayName": "Release WSL GCC", - "description": "Build on WSL + GCC (Release). Windows developers can use this preset to catch GCC-specific issues with WSL. WSL tends to be very slow, so this is not recommended for interactive development.", - "inherits": "debug-wsl-gcc", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "LLVM_ROOT": "${sourceDir}/build/third-party/llvm-project/llvm/install/Linux/Release", - "Clang_ROOT": "${sourceDir}/build/third-party/llvm-project/llvm/install/Linux/Release" - } - }, - { - "name": "relwithdebinfo-wsl-gcc", - "displayName": "RelWithDebInfo WSL GCC", - "description": "Build on WSL + GCC (RelWithDebInfo). Windows developers can use this preset to catch GCC-specific issues with WSL. WSL tends to be very slow, so this is not recommended for interactive development.", - "inherits": "debug-wsl-gcc", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithDebInfo", - "LLVM_ROOT": "${sourceDir}/build/third-party/llvm-project/llvm/install/Linux/Release", - "Clang_ROOT": "${sourceDir}/build/third-party/llvm-project/llvm/install/Linux/Release" - } - }, - { - "name": "debug-wsl-clang", - "displayName": "Debug WSL Clang", - "description": "Build on WSL + Clang (Debug). Windows developers can use this preset to catch Clang-specific issues with WSL. WSL tends to be very slow, so this is not recommended for interactive development.", - "inherits": "debug-wsl-gcc", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_CXX_COMPILER": "/usr/bin/clang++-16", - "CMAKE_C_COMPILER": "/usr/bin/clang-16" - }, - "vendor": { - "jetbrains.com/clion": { - "toolchain": "WSL Clang" - } - } - }, - { - "name": "debug-macos", - "displayName": "Debug (macOS)", - "description": "Preset for building MrDocs in Debug mode with the default compiler in macOS.", - "inherits": "debug", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "LLVM_ROOT": "${sourceDir}/build/third-party/llvm-project/install/debug", - "Clang_ROOT": "${sourceDir}/build/third-party/llvm-project/install/debug", - "duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/debug", - "Duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/debug", - "libxml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release", - "LibXml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release", - "MRDOCS_BUILD_TESTS": true, - "MRDOCS_BUILD_DOCS": false, - "MRDOCS_GENERATE_REFERENCE": false, - "MRDOCS_GENERATE_ANTORA_REFERENCE": false, - "CMAKE_MAKE_PROGRAM": "${sourceDir}/build/third-party/ninja/ninja", - "CMAKE_CXX_FLAGS": "-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE" - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Darwin" - }, - "warnings": { - "unusedCli": false - }, - "generator": "Ninja" - }, - { - "name": "debug-macos-fast", - "displayName": "Debug with Optimized Dependencies (macOS)", - "description": "Preset for building MrDocs in Debug mode with the default compiler in macOS.", - "inherits": "debug", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "LLVM_ROOT": "${sourceDir}/build/third-party/llvm-project/install/release", - "Clang_ROOT": "${sourceDir}/build/third-party/llvm-project/install/release", - "duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/release", - "Duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/release", - "libxml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release", - "LibXml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release", - "MRDOCS_BUILD_TESTS": true, - "MRDOCS_BUILD_DOCS": false, - "MRDOCS_GENERATE_REFERENCE": false, - "MRDOCS_GENERATE_ANTORA_REFERENCE": false, - "CMAKE_MAKE_PROGRAM": "${sourceDir}/build/third-party/ninja/ninja", - "CMAKE_CXX_FLAGS": "-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE" - }, - "warnings": { - "unusedCli": false - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Darwin" - }, - "generator": "Ninja" - }, - { - "name": "release-macos", - "displayName": "Release (macOS)", - "description": "Preset for building MrDocs in Release mode with the default compiler in macOS.", - "inherits": "release", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "LLVM_ROOT": "${sourceDir}/build/third-party/llvm-project/install/release", - "Clang_ROOT": "${sourceDir}/build/third-party/llvm-project/install/release", - "duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/release", - "Duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/release", - "libxml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release", - "LibXml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release", - "MRDOCS_BUILD_TESTS": true, - "MRDOCS_BUILD_DOCS": false, - "MRDOCS_GENERATE_REFERENCE": false, - "MRDOCS_GENERATE_ANTORA_REFERENCE": false, - "CMAKE_MAKE_PROGRAM": "${sourceDir}/build/third-party/ninja/ninja" - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Darwin" - }, - "warnings": { - "unusedCli": false - }, - "generator": "Ninja" - }, - { - "name": "release-macos-gcc", - "displayName": "Release (macOS: gcc)", - "description": "Preset for building MrDocs in Release mode with the gcc compiler in macOS.", - "inherits": "release", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "LLVM_ROOT": "${sourceDir}/build/third-party/llvm-project/install/release-gcc", - "Clang_ROOT": "${sourceDir}/build/third-party/llvm-project/install/release-gcc", - "duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/release-gcc", - "Duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/release-gcc", - "libxml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release-gcc", - "LibXml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release-gcc", - "MRDOCS_BUILD_TESTS": true, - "MRDOCS_BUILD_DOCS": false, - "MRDOCS_GENERATE_REFERENCE": false, - "MRDOCS_GENERATE_ANTORA_REFERENCE": false, - "CMAKE_C_COMPILER": "/usr/bin/gcc", - "CMAKE_CXX_COMPILER": "/usr/bin/g++", - "CMAKE_MAKE_PROGRAM": "${sourceDir}/build/third-party/ninja/ninja" - }, - "warnings": { - "unusedCli": false - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Darwin" - }, - "generator": "Ninja" - }, - { - "name": "debug-macos-gcc-asan", - "displayName": "Debug (macOS: gcc) with ASan", - "description": "Preset for building MrDocs in Debug mode with the gcc compiler in macOS.", - "inherits": "debug", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "LLVM_ROOT": "${sourceDir}/build/third-party/llvm-project/install/debug-gcc-asan", - "Clang_ROOT": "${sourceDir}/build/third-party/llvm-project/install/debug-gcc-asan", - "duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/debug-gcc-asan", - "Duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/debug-gcc-asan", - "libxml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release-gcc", - "LibXml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release-gcc", - "MRDOCS_BUILD_TESTS": true, - "MRDOCS_BUILD_DOCS": false, - "MRDOCS_GENERATE_REFERENCE": false, - "MRDOCS_GENERATE_ANTORA_REFERENCE": false, - "CMAKE_C_COMPILER": "/usr/bin/gcc", - "CMAKE_CXX_COMPILER": "/usr/bin/g++", - "CMAKE_MAKE_PROGRAM": "${sourceDir}/build/third-party/ninja/ninja", - "CMAKE_C_FLAGS": "-fsanitize=address -fno-sanitize-recover=address -fno-omit-frame-pointer", - "CMAKE_CXX_FLAGS": "-fsanitize=address -fno-sanitize-recover=address -fno-omit-frame-pointer" - }, - "warnings": { - "unusedCli": false - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Darwin" - }, - "generator": "Ninja" - }, - { - "name": "debug-macos-gcc-ubsan", - "displayName": "Debug (macOS: gcc) with UBSan", - "description": "Preset for building MrDocs in Debug mode with the gcc compiler in macOS.", - "inherits": "debug", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "LLVM_ROOT": "${sourceDir}/build/third-party/llvm-project/install/debug-gcc-ubsan", - "Clang_ROOT": "${sourceDir}/build/third-party/llvm-project/install/debug-gcc-ubsan", - "duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/debug-gcc-ubsan", - "Duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/debug-gcc-ubsan", - "libxml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release-gcc", - "LibXml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release-gcc", - "MRDOCS_BUILD_TESTS": true, - "MRDOCS_BUILD_DOCS": false, - "MRDOCS_GENERATE_REFERENCE": false, - "MRDOCS_GENERATE_ANTORA_REFERENCE": false, - "CMAKE_C_COMPILER": "/usr/bin/gcc", - "CMAKE_CXX_COMPILER": "/usr/bin/g++", - "CMAKE_MAKE_PROGRAM": "${sourceDir}/build/third-party/ninja/ninja", - "CMAKE_C_FLAGS": "-fsanitize=undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer", - "CMAKE_CXX_FLAGS": "-fsanitize=undefined -fno-sanitize-recover=undefined -fno-omit-frame-pointer" - }, - "warnings": { - "unusedCli": false - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Darwin" - }, - "generator": "Ninja" - }, - { - "name": "debug-macos-clang", - "displayName": "Debug (macOS: clang)", - "description": "Preset for building MrDocs in Debug mode with the clang compiler in macOS.", - "inherits": "debug", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "LLVM_ROOT": "${sourceDir}/build/third-party/llvm-project/install/debug-clang", - "Clang_ROOT": "${sourceDir}/build/third-party/llvm-project/install/debug-clang", - "duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/debug-clang", - "Duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/debug-clang", - "libxml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release-clang", - "LibXml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release-clang", - "MRDOCS_BUILD_TESTS": true, - "MRDOCS_BUILD_DOCS": false, - "MRDOCS_GENERATE_REFERENCE": false, - "MRDOCS_GENERATE_ANTORA_REFERENCE": false, - "CMAKE_C_COMPILER": "/opt/homebrew/opt/llvm/bin/clang", - "CMAKE_CXX_COMPILER": "/opt/homebrew/opt/llvm/bin/clang++", - "CMAKE_MAKE_PROGRAM": "${sourceDir}/build/third-party/ninja/ninja", - "CMAKE_AR": "/opt/homebrew/opt/llvm/bin/llvm-ar", - "CMAKE_CXX_COMPILER_AR": "/opt/homebrew/opt/llvm/bin/llvm-ar", - "CMAKE_C_COMPILER_AR": "/opt/homebrew/opt/llvm/bin/llvm-ar", - "CMAKE_RANLIB": "/opt/homebrew/opt/llvm/bin/llvm-ranlib", - "CMAKE_C_COMPILER_LINKER": "/opt/homebrew/bin/ld.lld", - "CMAKE_CXX_COMPILER_LINKER": "/opt/homebrew/bin/ld.lld", - "CMAKE_EXE_LINKER_FLAGS": "-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind", - "CMAKE_SHARED_LINKER_FLAGS": "-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind", - "CMAKE_MODULE_LINKER_FLAGS": "-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind", - "CMAKE_CXX_FLAGS": "-stdlib=libc++ -I/opt/homebrew/opt/llvm/include/c++/v1" - }, - "warnings": { - "unusedCli": false - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Darwin" - }, - "generator": "Ninja" - }, - { - "name": "debug-macos-clang-asan", - "generator": "Ninja", - "displayName": "Debug (macOS: clang) with ASan", - "description": "Preset for building MrDocs in Debug mode with the clang compiler in macOS.", - "inherits": "debug", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug", - "LLVM_ROOT": "${sourceDir}/build/third-party/llvm-project/install/debug-clang-asan", - "Clang_ROOT": "${sourceDir}/build/third-party/llvm-project/install/debug-clang-asan", - "duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/debug-clang-asan", - "Duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/debug-clang-asan", - "libxml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release-clang", - "LibXml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release-clang", - "MRDOCS_BUILD_TESTS": true, - "MRDOCS_BUILD_DOCS": false, - "MRDOCS_GENERATE_REFERENCE": false, - "MRDOCS_GENERATE_ANTORA_REFERENCE": false, - "CMAKE_C_COMPILER": "/opt/homebrew/opt/llvm/bin/clang", - "CMAKE_CXX_COMPILER": "/opt/homebrew/opt/llvm/bin/clang++", - "CMAKE_MAKE_PROGRAM": "${sourceDir}/build/third-party/ninja/ninja", - "CMAKE_AR": "/opt/homebrew/opt/llvm/bin/llvm-ar", - "CMAKE_CXX_COMPILER_AR": "/opt/homebrew/opt/llvm/bin/llvm-ar", - "CMAKE_C_COMPILER_AR": "/opt/homebrew/opt/llvm/bin/llvm-ar", - "CMAKE_RANLIB": "/opt/homebrew/opt/llvm/bin/llvm-ranlib", - "CMAKE_C_COMPILER_LINKER": "/opt/homebrew/bin/ld.lld", - "CMAKE_CXX_COMPILER_LINKER": "/opt/homebrew/bin/ld.lld", - "CMAKE_EXE_LINKER_FLAGS": "-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind -fsanitize=address", - "CMAKE_SHARED_LINKER_FLAGS": "-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind -fsanitize=address", - "CMAKE_MODULE_LINKER_FLAGS": "-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind -fsanitize=address", - "CMAKE_C_FLAGS": "-fsanitize=address -fno-sanitize-recover=address -fno-omit-frame-pointer", - "CMAKE_CXX_FLAGS": "-fsanitize=address -fno-sanitize-recover=address -fno-omit-frame-pointer -stdlib=libc++ -I/opt/homebrew/opt/llvm/include/c++/v1" - }, - "warnings": { - "unusedCli": false - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Darwin" - } - }, - { - "name": "release-macos-clang", - "generator": "Ninja", - "displayName": "Release (macOS: clang)", - "description": "Preset for building MrDocs in Release mode with the clang compiler in macOS.", - "inherits": "release", - "binaryDir": "${sourceDir}/build/${presetName}", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release", - "LLVM_ROOT": "${sourceDir}/build/third-party/llvm-project/install/release-clang", - "Clang_ROOT": "${sourceDir}/build/third-party/llvm-project/install/release-clang", - "duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/release-clang", - "Duktape_ROOT": "${sourceDir}/build/third-party/duktape/install/release-clang", - "libxml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release-clang", - "LibXml2_ROOT": "${sourceDir}/build/third-party/libxml2/install/release-clang", - "MRDOCS_BUILD_TESTS": true, - "MRDOCS_BUILD_DOCS": false, - "MRDOCS_GENERATE_REFERENCE": false, - "MRDOCS_GENERATE_ANTORA_REFERENCE": false, - "CMAKE_C_COMPILER": "/opt/homebrew/opt/llvm/bin/clang", - "CMAKE_CXX_COMPILER": "/opt/homebrew/opt/llvm/bin/clang++", - "CMAKE_MAKE_PROGRAM": "${sourceDir}/build/third-party/ninja/ninja", - "CMAKE_AR": "/opt/homebrew/opt/llvm/bin/llvm-ar", - "CMAKE_CXX_COMPILER_AR": "/opt/homebrew/opt/llvm/bin/llvm-ar", - "CMAKE_C_COMPILER_AR": "/opt/homebrew/opt/llvm/bin/llvm-ar", - "CMAKE_RANLIB": "/opt/homebrew/opt/llvm/bin/llvm-ranlib", - "CMAKE_C_COMPILER_LINKER": "/opt/homebrew/bin/ld.lld", - "CMAKE_CXX_COMPILER_LINKER": "/opt/homebrew/bin/ld.lld", - "CMAKE_EXE_LINKER_FLAGS": "-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind", - "CMAKE_SHARED_LINKER_FLAGS": "-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind", - "CMAKE_MODULE_LINKER_FLAGS": "-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib/unwind -lunwind", - "CMAKE_CXX_FLAGS": "-stdlib=libc++ -I/opt/homebrew/opt/llvm/include/c++/v1" - }, - "warnings": { - "unusedCli": false - }, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Darwin" - } - } - ] -} \ No newline at end of file From e2bdd62335a6aab8e3bf1b7b692ecedf11b22499 Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Tue, 2 Dec 2025 16:03:39 -0500 Subject: [PATCH 03/11] test: check int tests results in ctest --- src/test/TestMain.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/TestMain.cpp b/src/test/TestMain.cpp index 85fb91df31..0abc77115f 100644 --- a/src/test/TestMain.cpp +++ b/src/test/TestMain.cpp @@ -111,7 +111,11 @@ int test_main(int argc, char const** argv) if (testArgs.unitOption.getValue()) { - test_suite::unit_test_main(argc, argv); + int unitResult = test_suite::unit_test_main(argc, argv); + if (unitResult != EXIT_SUCCESS) + { + return unitResult; + } } if (report::results.errorCount > 0 || From 9e8e4db6a11a7feccdb1dd92a3c7a590aa3e4c5f Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Tue, 2 Dec 2025 16:04:20 -0500 Subject: [PATCH 04/11] test: --bad is disabled by default --- src/test/TestArgs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/TestArgs.cpp b/src/test/TestArgs.cpp index 44e33bf59f..fe2ecf38df 100644 --- a/src/test/TestArgs.cpp +++ b/src/test/TestArgs.cpp @@ -44,8 +44,8 @@ R"( , badOption( "bad", - llvm::cl::desc("Write a .bad.xml file for each test failure."), - llvm::cl::init(true)) + llvm::cl::desc("Write a .bad. file for each test failure."), + llvm::cl::init(false)) , unitOption( "unit", From eab30c139980458d6d9aa23cad4e82a0e99cb6ae Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Tue, 2 Dec 2025 16:04:43 -0500 Subject: [PATCH 05/11] test: output normalization --- src/test/Support/TextNormalization.cpp | 262 +++++++++++++++++++++++++ src/test/Support/TextNormalization.hpp | 43 ++++ src/test/TestRunner.cpp | 23 +-- 3 files changed, 313 insertions(+), 15 deletions(-) create mode 100644 src/test/Support/TextNormalization.cpp create mode 100644 src/test/Support/TextNormalization.hpp diff --git a/src/test/Support/TextNormalization.cpp b/src/test/Support/TextNormalization.cpp new file mode 100644 index 0000000000..456d3cd80a --- /dev/null +++ b/src/test/Support/TextNormalization.cpp @@ -0,0 +1,262 @@ +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com) +// +// Official repository: https://github.com/cppalliance/mrdocs +// + +#include "TextNormalization.hpp" +#include +#include +#include +#include +#include +#include +#include + +namespace mrdocs::test_support { +namespace { + +bool +isHorizontalSpace(char c) +{ + return c == ' ' || c == '\t'; +} + +void +normalizeNewlines(std::string& text) +{ + std::string normalized; + normalized.reserve(text.size()); + for (std::size_t i = 0; i < text.size(); ++i) + { + if (text[i] == '\r') + { + if (i + 1 < text.size() && text[i + 1] == '\n') + { + ++i; + } + normalized.push_back('\n'); + } + else + { + normalized.push_back(text[i]); + } + } + text.swap(normalized); +} + +void +rstripEachLine(std::string& text) +{ + std::string trimmed; + trimmed.reserve(text.size()); + std::size_t lineStart = 0; + for (std::size_t i = 0; i <= text.size(); ++i) + { + if (i == text.size() || text[i] == '\n') + { + std::size_t lineEnd = i; + while (lineEnd > lineStart && + (text[lineEnd - 1] == ' ' || + text[lineEnd - 1] == '\t' || + text[lineEnd - 1] == '\r')) + { + --lineEnd; + } + trimmed.append(text.data() + lineStart, lineEnd - lineStart); + if (i != text.size()) + { + trimmed.push_back('\n'); + } + lineStart = i + 1; + } + } + text.swap(trimmed); +} + +void +collapseBlankLines(std::string& text, std::size_t maxBlankLines) +{ + if (text.empty()) + return; + + std::string collapsed; + collapsed.reserve(text.size()); + std::size_t blankCount = 0; + std::size_t pos = 0; + while (pos < text.size()) + { + auto nextNewline = text.find('\n', pos); + bool hasNewline = nextNewline != std::string::npos; + std::size_t lineLength = + (hasNewline ? nextNewline : text.size()) - pos; + std::string_view line(text.data() + pos, lineLength); + bool isBlank = line.empty(); + + if (!isBlank || blankCount < maxBlankLines) + { + collapsed.append(line); + if (hasNewline) + { + collapsed.push_back('\n'); + } + } + + blankCount = isBlank ? blankCount + 1 : 0; + if (!hasNewline) + break; + pos = nextNewline + 1; + } + + text.swap(collapsed); +} + +std::string +collapseSpacesOutsideVerbatim( + std::string_view text, + std::initializer_list verbatimTags) +{ + std::vector verbatim; + verbatim.reserve(verbatimTags.size()); + for (auto const tag : verbatimTags) + { + verbatim.emplace_back(tag.lower()); + } + + std::vector verbatimStack; + std::string out; + out.reserve(text.size()); + + bool previousSpace = false; + std::size_t i = 0; + while (i < text.size()) + { + if (text[i] == '<') + { + auto close = text.find('>', i); + if (close == std::string::npos) + { + out.append(text.substr(i)); + break; + } + + llvm::StringRef tag(text.data() + i + 1, close - i - 1); + tag = tag.ltrim(); + bool isClosing = tag.consume_front("/"); + tag = tag.ltrim(); + llvm::StringRef tagBody = tag.rtrim(); + bool selfClosing = tagBody.ends_with("/"); + llvm::StringRef name = tag.take_while([](char c) { + return std::isalnum(static_cast(c)) || + c == '-' || c == ':'; + }); + std::string lowerName = name.lower(); + + if (isClosing) + { + if (!verbatimStack.empty() && + verbatimStack.back() == lowerName) + { + verbatimStack.pop_back(); + } + } + else + { + bool isVerbatim = std::find( + verbatim.begin(), verbatim.end(), lowerName) != verbatim.end(); + if (isVerbatim && !selfClosing) + { + verbatimStack.push_back(lowerName); + } + } + + out.append(text.substr(i, close - i + 1)); + previousSpace = false; + i = close + 1; + continue; + } + + char c = text[i]; + if (verbatimStack.empty() && isHorizontalSpace(c)) + { + if (!previousSpace) + { + out.push_back(' '); + } + previousSpace = true; + ++i; + continue; + } + + previousSpace = false; + out.push_back(c); + ++i; + } + + return out; +} + +} // namespace + +OutputFormat +guessOutputFormat(llvm::StringRef pathOrExtension) +{ + llvm::StringRef ext = llvm::sys::path::extension(pathOrExtension); + if (ext.empty()) + ext = pathOrExtension; + ext = ext.ltrim("."); + auto lower = ext.lower(); + llvm::StringRef extLower(lower); + + if (extLower == "html" || extLower == "htm") + return OutputFormat::html; + if (extLower == "adoc" || extLower == "asciidoc") + return OutputFormat::adoc; + if (extLower == "xml") + return OutputFormat::xml; + return OutputFormat::other; +} + +std::string +normalizeForComparison(std::string_view text, OutputFormat format) +{ + std::string normalized(text); + normalizeNewlines(normalized); + + switch (format) + { + case OutputFormat::html: + normalized = collapseSpacesOutsideVerbatim( + normalized, { "pre", "code", "textarea" }); + rstripEachLine(normalized); + break; + + case OutputFormat::xml: + rstripEachLine(normalized); + collapseBlankLines(normalized, 1); + break; + + case OutputFormat::adoc: + rstripEachLine(normalized); + collapseBlankLines(normalized, 1); + break; + + case OutputFormat::other: + rstripEachLine(normalized); + break; + } + + return normalized; +} + +std::string +normalizeForComparison(std::string_view text, llvm::StringRef pathOrExtension) +{ + return normalizeForComparison(text, guessOutputFormat(pathOrExtension)); +} + +} // namespace mrdocs::test_support diff --git a/src/test/Support/TextNormalization.hpp b/src/test/Support/TextNormalization.hpp new file mode 100644 index 0000000000..7b85fb407b --- /dev/null +++ b/src/test/Support/TextNormalization.hpp @@ -0,0 +1,43 @@ +// +// Licensed under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// Copyright (c) 2024 Alan de Freitas (alandefreitas@gmail.com) +// +// Official repository: https://github.com/cppalliance/mrdocs +// + +#ifndef MRDOCS_TEST_SUPPORT_TEXTNORMALIZATION_HPP +#define MRDOCS_TEST_SUPPORT_TEXTNORMALIZATION_HPP + +#include +#include +#include + +namespace mrdocs::test_support { + +/** File format classification used by test normalizers. */ +enum class OutputFormat +{ + html, + adoc, + xml, + other, +}; + +/** Deduce the output format from a path or extension. */ +OutputFormat +guessOutputFormat(llvm::StringRef pathOrExtension); + +/** Normalize text for comparison in tests based on the output format. */ +std::string +normalizeForComparison(std::string_view text, OutputFormat format); + +/** Convenience overload that accepts a path or extension directly. */ +std::string +normalizeForComparison(std::string_view text, llvm::StringRef pathOrExtension); + +} // namespace mrdocs::test_support + +#endif diff --git a/src/test/TestRunner.cpp b/src/test/TestRunner.cpp index 847e5825d6..a32e04ded2 100644 --- a/src/test/TestRunner.cpp +++ b/src/test/TestRunner.cpp @@ -11,6 +11,7 @@ #include #include "TestArgs.hpp" #include "TestRunner.hpp" +#include "Support/TextNormalization.hpp" #include #include #include @@ -56,16 +57,6 @@ writeFile( } namespace { -void -replaceCRLFWithLF(std::string &str) -{ - std::string::size_type pos = 0; - while ((pos = str.find("\r\n", pos)) != std::string::npos) { - str.replace(pos, 2, "\n"); - pos += 1; // Move past the '\n' character - } -} - SingleFileDB makeSingleFileDB(llvm::StringRef pathName, std::vector cmds) { @@ -181,7 +172,9 @@ TestRunner::handleCompilationDatabase( { return report::error("{}: \"{}\"", exp.error(), filePath); } - replaceCRLFWithLF(generatedDocs); + auto const format = test_support::guessOutputFormat(expectedPath.str()); + std::string normalizedGenerated = test_support::normalizeForComparison( + generatedDocs, format); // Generate tagfile if (auto hbsGen = dynamic_cast(gen_)) @@ -234,9 +227,9 @@ TestRunner::handleCompilationDatabase( } // Analyse results - std::string expectedDocs = expectedDocsBuf->getBuffer().str(); - replaceCRLFWithLF(expectedDocs); - if (generatedDocs == expectedDocs) + std::string const expectedDocs = test_support::normalizeForComparison( + expectedDocsBuf->getBuffer(), format); + if (normalizedGenerated == expectedDocs) { report::info("\"{}\" passed", filePath); ++results.expectedDocsMatching; @@ -259,7 +252,7 @@ TestRunner::handleCompilationDatabase( } report::error("{}: \"{}\"", Error("Incorrect results"), filePathSv); - auto res = test_suite::diffStrings(expectedDocs, generatedDocs); + auto res = test_suite::diffStrings(expectedDocs, normalizedGenerated); report::error("{} lines added", res.added); report::error("{} lines removed", res.removed); From 6bfc28f581edd31df77ef801e4143eb80004d046 Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Tue, 2 Dec 2025 16:05:20 -0500 Subject: [PATCH 06/11] test: testClang_stdCxx default is C++26 --- src/test/lib/MrDocsCompilationDatabase.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/lib/MrDocsCompilationDatabase.cpp b/src/test/lib/MrDocsCompilationDatabase.cpp index 12670208ec..444ec9de69 100644 --- a/src/test/lib/MrDocsCompilationDatabase.cpp +++ b/src/test/lib/MrDocsCompilationDatabase.cpp @@ -93,7 +93,7 @@ struct MrDocsCompilationDatabase_test { { auto adjusted = adjustCompileCommand({ programName }); - BOOST_TEST(has(adjusted, "-std=c++23")); + BOOST_TEST(has(adjusted, "-std=c++26")); } { auto adjusted = adjustCompileCommand({ programName, "-std=c++11" }); @@ -217,7 +217,7 @@ struct MrDocsCompilationDatabase_test { { auto adjusted = adjustCompileCommand({ programName }); - BOOST_TEST(has(adjusted, "-std:c++23preview")); + BOOST_TEST(has(adjusted, "-std:c++latest")); } { auto adjusted = adjustCompileCommand({ programName, "-std:c++11" }); @@ -238,7 +238,7 @@ struct MrDocsCompilationDatabase_test { { auto adjusted = adjustCompileCommand({ programName, "-x", "c" }); - BOOST_TEST(has(adjusted, "-std:c17")); + BOOST_TEST(has(adjusted, "-std:clatest")); } { auto adjusted = adjustCompileCommand( From 737c369fcd3b4a6c71343b68801ba95b9e83fd46 Mon Sep 17 00:00:00 2001 From: Alan de Freitas Date: Tue, 2 Dec 2025 17:16:51 -0500 Subject: [PATCH 07/11] test: run_ci_with_act.py script --- util/README.adoc | 7 + util/run_ci_with_act.py | 1045 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 1052 insertions(+) create mode 100644 util/run_ci_with_act.py diff --git a/util/README.adoc b/util/README.adoc index da4afcfe85..22ce855d21 100644 --- a/util/README.adoc +++ b/util/README.adoc @@ -13,3 +13,10 @@ This directory holds additional scripts and files for building and testing. - Docs build runs by default; pass `--skip-docs` to omit the documentation step. Docs are built after install with `MRDOCS_ROOT` pointed at the freshly installed prefix so the generated reference uses that version. - Strict tests (self-doc, format check, warn-as-error) are enabled by default; pass `--no-strict` to disable `MRDOCS_BUILD_STRICT_TESTS`. - `util/reformat.py` supports `--check` to validate formatting/include guards without modifying files (used by the strict test suite). + +== CI tests with act + +- Run `python util/run_ci_with_act.py` to install https://github.com/nektos/act (if needed) under `local/act/`, pull lightweight Ubuntu runner images, and execute every job defined in `.github/workflows/ci.yml` using the `pull_request` event payload. +- Script state (act binary, caches, artifacts, secrets stub) lives in `local/act/`, which is already git-ignored. Secrets default to placeholders so side-effecting publishing steps stay skipped. +- Pass `--list-jobs` to see the discovered job IDs, `--jobs build llvm-releases` to target a subset, `--image ubuntu-24.04=` to override the minimal runner image, or `--dry-run` to inspect the generated act commands. +- The script maps the host architecture to `linux/amd64` or `linux/arm64` automatically and pre-pulls runner images before starting jobs. Use `--reuse` to let `act` keep containers alive between job batches if Docker resources allow. diff --git a/util/run_ci_with_act.py b/util/run_ci_with_act.py new file mode 100644 index 0000000000..fcc0eb3132 --- /dev/null +++ b/util/run_ci_with_act.py @@ -0,0 +1,1045 @@ +#!/usr/bin/env python3 +# +# Licensed under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# Copyright (c) 2025 Alan de Freitas (alandefreitas@gmail.com) +# +# Official repository: https://github.com/cppalliance/mrdocs +# + +"""Run the CI workflow locally with act using lightweight defaults.""" + +from __future__ import annotations + +import argparse +import json +import os +import platform +import re +import math +import shlex +import shutil +import stat +import subprocess +import sys +import tarfile +import textwrap +from collections import deque, OrderedDict +from datetime import datetime +import urllib.error +import urllib.request +from pathlib import Path +from typing import Dict, List, Optional, TextIO + + +class TextUI: + COLOR = { + "reset": "\033[0m", + "info": "\033[36m", + "warn": "\033[33m", + "error": "\033[31m", + "ok": "\033[32m", + "section": "\033[35m", + "command": "\033[34m", + } + EMOJI = { + "info": "💬 ", + "warn": "⚠️ ", + "error": "⛔ ", + "ok": "✅ ", + "section": "", + "command": "▶️ ", + } + + def __init__(self, enable_color: bool = True, enable_emoji: bool = True): + force_color = os.environ.get("BOOTSTRAP_FORCE_COLOR") or os.environ.get("CLICOLOR_FORCE") + force_emoji = os.environ.get("BOOTSTRAP_FORCE_EMOJI") + self.color_enabled = bool(enable_color and (force_color or self._supports_color())) + self.emoji_enabled = bool(enable_emoji and (force_emoji or self._supports_emoji())) + + @staticmethod + def _supports_color() -> bool: + if os.environ.get("NO_COLOR") or os.environ.get("BOOTSTRAP_PLAIN"): + return False + return True + + @staticmethod + def _supports_emoji() -> bool: + if os.environ.get("BOOTSTRAP_PLAIN"): + return False + return True + + def _fmt(self, text: str, kind: str, icon: Optional[str] = None) -> str: + prefix = "" + if self.emoji_enabled: + prefix = icon if icon is not None else self.EMOJI.get(kind, "") + if not self.color_enabled: + return f"{prefix}{text}" + color = self.COLOR.get(kind, "") + reset = self.COLOR["reset"] + return f"{color}{prefix}{text}{reset}" + + def info(self, msg: str, icon: Optional[str] = None) -> None: + print(self._fmt(msg, "info", icon)) + + def warn(self, msg: str, icon: Optional[str] = None) -> None: + print(self._fmt(msg, "warn", icon)) + + def error(self, msg: str, icon: Optional[str] = None) -> None: + print(self._fmt(msg, "error", icon)) + + def ok(self, msg: str, icon: Optional[str] = None) -> None: + print(self._fmt(msg, "ok", icon)) + + def section_big(self, title: str, icon: Optional[str] = None) -> None: + prefix = (icon + " ") if (self.emoji_enabled and icon) else "" + text = f"{prefix}{title}" + line = "=" * max(8, len(text) + 8) + banner = f"{line}\n|| {text}\n{line}" + print(self._fmt(banner, "section", "")) + + def section_small(self, title: str, icon: Optional[str] = None) -> None: + prefix = (icon + " ") if (self.emoji_enabled and icon) else "" + banner = f"-- {prefix}{title} --" + print(self._fmt(banner, "section", "")) + + def command(self, cmd: str, icon: Optional[str] = None) -> None: + print(self._fmt(cmd, "command", icon)) + + def kv(self, key: str, value: str, icon: Optional[str] = None) -> None: + print(self._fmt(f"{key}: {value}", "info", icon)) + + +ui = TextUI() + +# Resolve to the repository root (this file lives in /util/) +# parents[1] = repo root for paths like /util/run_ci_with_act2.py +ROOT = Path(__file__).resolve().parent.parent +WORKFLOW_FILE = ROOT / ".github" / "workflows" / "ci.yml" +STATE_ROOT = ROOT / "local" / "act" +BIN_DIR = STATE_ROOT / "bin" +DOWNLOAD_DIR = STATE_ROOT / "downloads" +CACHE_DIR = STATE_ROOT / "cache" +ARTIFACT_DIR = STATE_ROOT / "artifacts" +TMP_DIR = STATE_ROOT / "tmp" +LOG_DIR = STATE_ROOT / "logs" +DEFAULT_SECRETS_FILE = STATE_ROOT / "secrets.env" +DEFAULT_ACT_VERSION = "v0.2.68" +DEFAULT_TOKEN = "local-test-token" +DEFAULT_PLATFORM_IMAGES = { + # Use smaller images by default to reduce pull size; override with --image for full if needed. + "ubuntu-latest": "ghcr.io/catthehacker/ubuntu:act-24.04", + "ubuntu-24.04": "ghcr.io/catthehacker/ubuntu:act-24.04", + "ubuntu-22.04": "ghcr.io/catthehacker/ubuntu:act-22.04", + "ubuntu-20.04": "ghcr.io/catthehacker/ubuntu:act-20.04", +} +ARM_FRIENDLY_PLATFORM_IMAGES = DEFAULT_PLATFORM_IMAGES +FALLBACK_PLATFORM_IMAGES = { + "ubuntu-latest": "ghcr.io/catthehacker/ubuntu:act-24.04", + "ubuntu-24.04": "ghcr.io/catthehacker/ubuntu:act-24.04", + "ubuntu-22.04": "ghcr.io/catthehacker/ubuntu:act-22.04", + "ubuntu-20.04": "ghcr.io/catthehacker/ubuntu:act-20.04", +} + + +class ActError(RuntimeError): + """Raised when act could not be prepared or run.""" + + +def _prefix(message: str) -> str: + timestamp = datetime.now().strftime("%H:%M:%S") + return f"[{timestamp}] [run-ci-act] {message}" + + +def is_placeholder_token(token: str) -> bool: + if not token: + return True + lower = token.lower() + return token == DEFAULT_TOKEN or lower.startswith("local-") or lower == "ghp_placeholder" + + +def log(message: str, *, emoji: str = "ℹ️", color: str | None = None, bold: bool = False) -> None: + text = _prefix(message) + icon = f"{emoji} " + if color == "yellow": + ui.warn(text, icon=icon) + elif color == "green": + ui.ok(text, icon=icon) + elif color == "red": + ui.error(text, icon=icon) + else: + ui.info(text, icon=icon) + + +def warn(message: str) -> None: + log(f"warning: {message}", emoji="⚠️", color="yellow") + + +def success(message: str) -> None: + log(message, emoji="✅", color="green") + + +def error(message: str) -> None: + log(message, emoji="⛔", color="red") + + +def ensure_directories() -> None: + for path in (STATE_ROOT, BIN_DIR, DOWNLOAD_DIR, CACHE_DIR, ARTIFACT_DIR, TMP_DIR, LOG_DIR): + path.mkdir(parents=True, exist_ok=True) + + +def check_docker() -> str: + path = shutil.which("docker") + if path: + log(f"docker CLI found at {path}", emoji="🐳", color="blue") + return path + + system = platform.system() + if system == "Darwin": + hint = "Install Docker Desktop for Mac (https://docs.docker.com/desktop/install/mac/) and start it once." + elif system == "Linux": + hint = "Install Docker Engine (e.g., via your package manager or https://docs.docker.com/engine/install/) and ensure your user can run docker commands." + else: + hint = "Install Docker Desktop/Engine for your OS and ensure the docker CLI is on PATH." + + raise ActError(f"docker is required by act but was not found. {hint} After installing, verify with `docker ps`.") + + +def detect_platform() -> tuple[str, str]: + system = platform.system() + machine = platform.machine().lower() + if system not in {"Linux", "Darwin"}: + raise ActError(f"Unsupported OS '{system}'. This script only supports Linux and macOS hosts.") + if machine in {"x86_64", "amd64"}: + arch = "x86_64" + elif machine in {"arm64", "aarch64"}: + arch = "arm64" + else: + raise ActError(f"Unsupported CPU architecture '{platform.machine()}'.") + return system, arch + + +def resolve_container_arch(machine: str) -> str: + # Prefer amd64 containers even on arm hosts to mirror GitHub’s runners and avoid + # actions that download x86-only tooling (e.g., setup-ninja v5). + return "linux/amd64" if machine in {"x86_64", "arm64"} else "linux/arm64" + + +def fetch_latest_act_tag(timeout: int = 20) -> str: + url = "https://api.github.com/repos/nektos/act/releases/latest" + req = urllib.request.Request(url, headers={"Accept": "application/vnd.github+json"}) + try: + with urllib.request.urlopen(req, timeout=timeout) as response: + data = json.loads(response.read().decode("utf-8")) + tag = data.get("tag_name") + if isinstance(tag, str) and tag: + return tag + warn("latest release response missing tag_name; falling back to default version") + except Exception as exc: # noqa: BLE001 - best effort fetch + warn(f"could not query GitHub releases: {exc}; falling back to {DEFAULT_ACT_VERSION}") + return DEFAULT_ACT_VERSION + + +def download_act_archive(tag: str, system: str, arch: str) -> Path: + suffix = "tar.gz" if system in {"Linux", "Darwin"} else "zip" + asset_name = f"act_{system}_{arch}.{suffix}" + url = f"https://github.com/nektos/act/releases/download/{tag}/{asset_name}" + dest = DOWNLOAD_DIR / asset_name + log(f"downloading {asset_name} ({tag})") + try: + with urllib.request.urlopen(url) as response: + dest.write_bytes(response.read()) + except urllib.error.HTTPError as exc: + raise ActError(f"failed to download {asset_name}: {exc}") from exc + return dest + + +def install_act(tag: Optional[str]) -> Path: + system, arch = detect_platform() + version = tag or fetch_latest_act_tag() + archive = download_act_archive(version, system, arch) + with tarfile.open(archive) as tar: + members = [m for m in tar.getmembers() if m.isfile() and m.name.endswith("act")] + if not members: + raise ActError(f"could not find act binary inside {archive.name}") + member = members[0] + binary_path = BIN_DIR / "act" + with tar.extractfile(member) as src, open(binary_path, "wb") as dst: + assert src is not None + shutil.copyfileobj(src, dst) + binary_path.chmod(binary_path.stat().st_mode | stat.S_IEXEC) + log(f"installed act {version} to {binary_path}") + return binary_path + + +def find_act(existing_path: Optional[str], preferred_version: Optional[str], *, allow_install: bool = True) -> Path: + if existing_path: + resolved = Path(existing_path) + if resolved.is_file(): + log(f"using provided act binary at {resolved}", emoji="🧭", color="blue") + return resolved + raise ActError(f"Specified act path {existing_path} does not exist") + + path_from_env = shutil.which("act") + if path_from_env: + log(f"using act from PATH: {path_from_env}", emoji="🧭", color="blue") + return Path(path_from_env) + + local_binary = BIN_DIR / "act" + if local_binary.exists(): + log(f"using cached act at {local_binary}", emoji="🧭", color="blue") + return local_binary + + if not allow_install: + warn("act not found locally; using placeholder path because installation is disabled (likely due to --dry-run).") + return Path("act") + + log("act not found; downloading...", emoji="⬇️", color="blue") + return install_act(preferred_version) + + +def ensure_secrets_file(path: Path) -> Path: + if not path.exists(): + log(f"creating default secrets file at {path}") + content = textwrap.dedent( + f""" + GITHUB_TOKEN={DEFAULT_TOKEN} + DEV_WEBSITES_SSH_KEY= + GH_TOKEN={DEFAULT_TOKEN} + """.strip() + ) + path.write_text(content + "\n", encoding="utf-8") + warn( + "Edit local/act/secrets.env to add a real GitHub token (read-only is fine) " + "so actions and registry pulls can authenticate." + ) + return path + + +def parse_job_ids(workflow: Path) -> List[str]: + if not workflow.exists(): + raise ActError(f"Workflow file {workflow} not found.") + text = workflow.read_text(encoding="utf-8") + try: + import yaml # type: ignore + + data = yaml.safe_load(text) + jobs = list((data or {}).get("jobs", {}).keys()) + if jobs: + return jobs + except Exception: + # Fall back to a simple regex-based scan if PyYAML is unavailable. + pass + + jobs: List[str] = [] + in_jobs = False + for line in text.splitlines(): + stripped = line.rstrip("\n") + if not in_jobs: + if stripped.strip().startswith("jobs:"): + in_jobs = True + continue + m = re.match(r"^\s{2}([A-Za-z0-9_-]+):\s*$", stripped) + if m: + jobs.append(m.group(1)) + if not jobs: + raise ActError(f"No jobs found under 'jobs:' in {workflow}") + return jobs + + +def select_default_images(container_arch: str) -> Dict[str, str]: + if container_arch == "linux/arm64": + log("Detected arm64; using arm-friendly runner images by default.", emoji="🧠", color="green") + return ARM_FRIENDLY_PLATFORM_IMAGES.copy() + return DEFAULT_PLATFORM_IMAGES.copy() + + +def build_platform_overrides(overrides: List[str], base: Dict[str, str]) -> Dict[str, str]: + images = base.copy() + for item in overrides: + if "=" not in item: + raise ActError(f"Invalid --image override '{item}'. Expected label=image") + label, image = item.split("=", 1) + images[label.strip()] = image.strip() + return images + + +def parse_runs_on_labels(workflow: Path) -> List[str]: + """Best-effort extraction of static runs-on labels from the workflow YAML.""" + if not workflow.exists(): + return [] + labels: List[str] = [] + for raw_line in workflow.read_text(encoding="utf-8").splitlines(): + line = raw_line.strip() + if not line.startswith("runs-on:"): + continue + _, rhs = line.split(":", 1) + rhs = rhs.strip() + if not rhs or "${{" in rhs: + continue + # Handle single value or simple list form (runs-on: [ubuntu-latest]) + rhs = rhs.strip("[] ") + for part in rhs.split(","): + val = part.strip().strip("'\"") + if val: + labels.append(val) + return labels + + +def docker_pull( + image: str, + dry_run: bool, + label: str, + token_source: Optional[str], + gh_user: Optional[str], + gh_scopes: Optional[List[str]], + container_arch: str, +) -> str: + cmd = ["docker", "pull", image] + try: + run_command(cmd, dry_run=dry_run, capture_output=True) + success(f"image ready: {label} -> {image}") + return image + except ActError as exc: + reason = str(exc) + reason_note = f" (reason: {reason})" if reason else "" + reason_lower = reason.lower() + manifest_missing = "manifest unknown" in reason_lower or "manifest list entries" in reason_lower + if "no space left on device" in reason_lower: + warn( + f"could not pull {image}{reason_note}. The Docker cache may be too large. " + f"Try `docker system prune -af` (removes all unused images/containers) or `docker image prune -af`, then rerun. " + "You can also pass a smaller image via --image ubuntu-24.04=." + ) + raise + ghcr_image = "ghcr.io/nektos/act-environments-ubuntu" + if image.startswith(ghcr_image) and not dry_run: + fallback = FALLBACK_PLATFORM_IMAGES.get(label) + scope_note = "" + missing_read_packages = False + if gh_scopes is not None: + joined = ", ".join(gh_scopes) if gh_scopes else "none" + if not any(scope.lower() == "read:packages" for scope in gh_scopes): + missing_read_packages = True + scope_note = f" Scopes detected: {joined}. GHCR requires read:packages." + else: + scope_note = f" Scopes detected: {joined}." + if missing_read_packages: + warn( + f"could not pull {image}{reason_note} (GHCR may require login). Trying a broader compatibility image instead.{scope_note}" + ) + warn( + "Your current token source lacks read:packages. Create a PAT with read:packages (and repo for private repos) at " + "https://github.com/settings/tokens?type=classic, then login with it " + f"using: {login_hint(None, gh_user)}. " + "To avoid using the GitHub CLI token for pulls, set GH_TOKEN/GITHUB_TOKEN to that PAT (or add it to local/act/secrets.env) and rerun." + ) + else: + if manifest_missing: + warn( + f"could not pull {image}{reason_note}. The tag may not be published for {container_arch}. " + "Trying a broader compatibility image instead. " + "Override with --image