diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml
index 476c2c1..b91ecc5 100644
--- a/.github/workflows/main.yaml
+++ b/.github/workflows/main.yaml
@@ -7,90 +7,90 @@ on:
jobs:
test:
runs-on: ubuntu-latest
-
+
strategy:
matrix:
node-version: [20.19.0, 21.x]
-
+
steps:
- - name: Checkout code
- uses: actions/checkout@v4
-
- - name: Setup Node.js ${{ matrix.node-version }}
- uses: actions/setup-node@v4
- with:
- node-version: ${{ matrix.node-version }}
- cache: 'npm'
-
- - name: Install dependencies
- run: npm ci
-
- - name: Build project
- run: npm run build
-
- - name: Run tests
- run: npm test
-
- - name: Run tests with coverage
- run: npm run test:coverage
-
- - name: Publish Test Report
- uses: ctrf-io/github-test-reporter@v1
- with:
- report-path: './ctrf/*.json'
- summary-report: true
- github-report: true
- failed-report: true
- flaky-report: true
- insights-report: true
- fail-rate-report: true
- flaky-rate-report: true
- slowest-report: true
- previous-results-report: true
- upload-artifact: true
- artifact-name: ctrf-test-report-${{ matrix.node-version }}
-
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- if: always()
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ matrix.node-version }}
+ cache: "npm"
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Build project
+ run: npm run build
+
+ - name: Run tests
+ run: npm test
+
+ - name: Run tests with coverage
+ run: npm run test:coverage
+
+ - name: Publish Test Report
+ uses: ctrf-io/github-test-reporter@v1
+ with:
+ report-path: "./ctrf/*.json"
+ summary-report: true
+ github-report: true
+ failed-report: true
+ flaky-report: true
+ insights-report: true
+ fail-rate-report: true
+ flaky-rate-report: true
+ slowest-report: true
+ previous-results-report: true
+ upload-artifact: true
+ artifact-name: ctrf-test-report-${{ matrix.node-version }}
+
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ if: always()
lint:
runs-on: ubuntu-latest
-
+
steps:
- - name: Checkout code
- uses: actions/checkout@v4
-
- - name: Setup Node.js
- uses: actions/setup-node@v4
- with:
- node-version: '20.19.0'
- cache: 'npm'
-
- - name: Install dependencies
- run: npm ci
-
- - name: Type check
- run: npx tsc --noEmit
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: "20.19.0"
+ cache: "npm"
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Type check
+ run: npx tsc --noEmit
security:
runs-on: ubuntu-latest
-
+
steps:
- - name: Checkout code
- uses: actions/checkout@v4
-
- - name: Setup Node.js
- uses: actions/setup-node@v4
- with:
- node-version: '20.19.0'
- cache: 'npm'
-
- - name: Install dependencies
- run: npm ci
-
- - name: Run security audit
- run: npm audit --audit-level=moderate
-
- - name: Check for known vulnerabilities
- run: npx audit-ci --moderate
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: "20.19.0"
+ cache: "npm"
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run security audit
+ run: npm audit --audit-level=moderate
+
+ - name: Check for known vulnerabilities
+ run: npx audit-ci --moderate
diff --git a/.gitignore b/.gitignore
index c4374df..61b0646 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,5 +3,5 @@ final
scripts
coverage
dist
-docs
-node_modules
\ No newline at end of file
+node_modules
+ctrf
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
new file mode 100644
index 0000000..7003896
--- /dev/null
+++ b/.prettierignore
@@ -0,0 +1,10 @@
+dist/
+node_modules/
+coverage/
+templates/
+reports/
+community-reports/
+.github/
+.exlintrc.js
+README.md
+docs/
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..e505faf
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,10 @@
+{
+ "semi": false,
+ "singleQuote": true,
+ "trailingComma": "es5",
+ "tabWidth": 2,
+ "useTabs": false,
+ "printWidth": 80,
+ "bracketSpacing": true,
+ "arrowParens": "avoid"
+}
diff --git a/README.md b/README.md
index fb1a204..ac37028 100644
--- a/README.md
+++ b/README.md
@@ -27,188 +27,28 @@ Explore more integrations
## Installation
```sh
-npm install ctrf@0.0.13-next.0
+npm install ctrf
```
+## API reference
+
+See [API reference](./docs) for more details.
+
## TypeScript Types
The library exports comprehensive TypeScript types for working with CTRF reports:
```typescript
-import type { Report, Test, Insights } from 'ctrf';
+import type { Report, Test, Insights } from "ctrf";
function analyzeReport(report: Report): void {
const flakyTests = report.results.tests.filter((test: Test) => test.flaky);
const insights = report.insights as Insights;
-
+
console.log(`Flaky rate: ${insights?.flakyRate.current}`);
}
```
-## API Reference
-
-### Reading Reports
-
-#### `readSingleReport(filePath: string): Report`
-
-Reads and parses a single CTRF report file from a specified file path.
-
-**Parameters:**
-- `filePath` - Path to the JSON file containing the CTRF report
-
-**Returns:** The parsed `Report` object
-
-**Throws:** Error if the file does not exist, is not valid JSON, or does not conform to the CTRF report structure
-
-**Example:**
-```typescript
-import { readSingleReport } from 'ctrf';
-
-const report = readSingleReport('./test-results.json');
-console.log(`Found ${report.results.summary.tests} tests`);
-```
-
-#### `readReportsFromDirectory(directoryPath: string): Report[]`
-
-Reads all CTRF report files from a given directory.
-
-**Parameters:**
-- `directoryPath` - Path to the directory containing JSON files
-
-**Returns:** Array of parsed `Report` objects
-
-**Throws:** Error if the directory does not exist or no valid CTRF reports are found
-
-**Example:**
-```typescript
-import { readReportsFromDirectory } from 'ctrf';
-
-const reports = readReportsFromDirectory('./test-reports/');
-console.log(`Loaded ${reports.length} reports`);
-```
-
-#### `readReportsFromGlobPattern(pattern: string): Report[]`
-
-Reads all CTRF report files matching a glob pattern.
-
-**Parameters:**
-- `pattern` - The glob pattern to match files (e.g., `ctrf/*.json`)
-
-**Returns:** Array of parsed `Report` objects
-
-**Throws:** Error if no valid CTRF reports are found
-
-**Example:**
-```typescript
-import { readReportsFromGlobPattern } from 'ctrf';
-
-const reports = readReportsFromGlobPattern('reports/**/*.json');
-console.log(`Found ${reports.length} reports matching pattern`);
-```
-
-### Merging Reports
-
-#### `mergeReports(reports: Report[]): Report`
-
-Merges multiple CTRF reports into a single report. Combines test results, summaries, and metadata from all input reports.
-
-**Parameters:**
-- `reports` - Array of CTRF report objects to be merged
-
-**Returns:** The merged CTRF report object
-
-**Throws:** Error if no reports are provided for merging
-
-**Example:**
-```typescript
-import { mergeReports, readReportsFromDirectory } from 'ctrf';
-
-const reports = readReportsFromDirectory('./test-reports/');
-const mergedReport = mergeReports(reports);
-console.log(`Merged ${reports.length} reports into one`);
-```
-
-### Report Enrichment & Insights
-
-#### `enrichReportWithInsights(currentReport: Report, previousReports?: Report[], baseline?: number | string): Report`
-
-Enriches a CTRF report with comprehensive insights by analyzing current and historical test data. Calculates metrics like flaky rates, failure rates, and performance trends.
-
-**Parameters:**
-- `currentReport` - The current CTRF report to enrich
-- `previousReports` - Array of historical CTRF reports (ordered newest to oldest, optional)
-- `baseline` - Optional baseline specification:
- - `undefined`: Use most recent previous report (default)
- - `number`: Use report at this index in previousReports array (0 = most recent)
- - `string`: Use report with specific timestamp ID
-
-**Returns:** The current report enriched with insights
-
-**Example:**
-```typescript
-import { enrichReportWithInsights, readSingleReport } from 'ctrf';
-
-const currentReport = readSingleReport('./current-report.json');
-const previousReports = readReportsFromDirectory('./historical-reports/');
-
-const enrichedReport = enrichReportWithInsights(currentReport, previousReports);
-console.log(`Flaky rate: ${enrichedReport.insights?.flakyRate.current}`);
-```
-
-### Storing Previous Results
-
-#### `storePreviousResults(currentReport: Report, previousReports: Report[]): Report`
-
-Stores previous test run results in the current report's metadata. Extracts key metrics from historical reports for trend analysis.
-
-**Parameters:**
-- `currentReport` - The current CTRF report to enrich with previous results
-- `previousReports` - Array of previous CTRF reports to extract metrics from
-
-**Returns:** The current report with previousResults populated in the `extra` field
-
-**Example:**
-```typescript
-import { storePreviousResults, readSingleReport } from 'ctrf';
-
-const currentReport = readSingleReport('./current-report.json');
-const previousReports = readReportsFromDirectory('./historical-reports/');
-
-const reportWithHistory = storePreviousResults(currentReport, previousReports);
-console.log(`Stored ${reportWithHistory.extra?.previousResults?.length} previous results`);
-```
-
-### Utility Functions
-
-#### `isTestFlaky(test: Test): boolean`
-
-Determines if a test is flaky based on its retries and status.
-
-**Parameters:**
-- `test` - The CTRF test to evaluate
-
-**Returns:** `true` if the test is considered flaky, otherwise `false`
-
-#### `formatAsPercentage(ratio: number, decimals?: number): string`
-
-Formats a ratio (0-1) as a percentage string for display.
-
-**Parameters:**
-- `ratio` - The ratio to format (0-1)
-- `decimals` - Number of decimal places (default: 2)
-
-**Returns:** Formatted percentage string (e.g., "25.50%")
-
-#### `formatInsightsMetricAsPercentage(metric: InsightsMetric, decimals?: number): object`
-
-Formats an InsightsMetric as percentage strings for display.
-
-**Parameters:**
-- `metric` - The insights metric to format
-- `decimals` - Number of decimal places (default: 2)
-
-**Returns:** Object with formatted percentage strings for current, previous, and change values
-
## What is CTRF?
CTRF is a universal JSON test report schema that addresses the lack of a standardized format for JSON test reports.
diff --git a/ctrf/ctrf-report.json b/ctrf/ctrf-report.json
deleted file mode 100644
index ddf8251..0000000
--- a/ctrf/ctrf-report.json
+++ /dev/null
@@ -1,393 +0,0 @@
-{
- "results": {
- "tool": {
- "name": "jest"
- },
- "summary": {
- "tests": 34,
- "passed": 34,
- "failed": 0,
- "pending": 0,
- "skipped": 0,
- "other": 0,
- "start": 1753734090944,
- "stop": 1753734092321
- },
- "tests": [
- {
- "name": "read-reports readSingleReport should read and parse a valid CTRF report file",
- "duration": 3,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/read-reports.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "read-reports.test.ts > read-reports > readSingleReport"
- },
- {
- "name": "read-reports readSingleReport should throw error when file does not exist",
- "duration": 12,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/read-reports.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "read-reports.test.ts > read-reports > readSingleReport"
- },
- {
- "name": "read-reports readSingleReport should throw error when file is not valid JSON",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/read-reports.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "read-reports.test.ts > read-reports > readSingleReport"
- },
- {
- "name": "read-reports readSingleReport should throw error when file is not a valid CTRF report",
- "duration": 1,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/read-reports.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "read-reports.test.ts > read-reports > readSingleReport"
- },
- {
- "name": "read-reports readReportsFromDirectory should read valid CTRF reports from directory",
- "duration": 1,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/read-reports.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "read-reports.test.ts > read-reports > readReportsFromDirectory"
- },
- {
- "name": "read-reports readReportsFromDirectory should throw error when directory does not exist",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/read-reports.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "read-reports.test.ts > read-reports > readReportsFromDirectory"
- },
- {
- "name": "read-reports readReportsFromDirectory should throw error when no valid CTRF reports are found",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/read-reports.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "read-reports.test.ts > read-reports > readReportsFromDirectory"
- },
- {
- "name": "read-reports readReportsFromDirectory should skip invalid files and warn about them",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/read-reports.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "read-reports.test.ts > read-reports > readReportsFromDirectory"
- },
- {
- "name": "read-reports readReportsFromGlobPattern should read valid CTRF reports from glob pattern",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/read-reports.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "read-reports.test.ts > read-reports > readReportsFromGlobPattern"
- },
- {
- "name": "read-reports readReportsFromGlobPattern should throw error when no files match the pattern",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/read-reports.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "read-reports.test.ts > read-reports > readReportsFromGlobPattern"
- },
- {
- "name": "read-reports readReportsFromGlobPattern should throw error when no valid CTRF reports are found",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/read-reports.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "read-reports.test.ts > read-reports > readReportsFromGlobPattern"
- },
- {
- "name": "run-insights utility functions isTestFlaky should return true for explicitly flaky tests",
- "duration": 2,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > run-insights utility functions > isTestFlaky"
- },
- {
- "name": "run-insights utility functions isTestFlaky should return true for passed tests with retries",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > run-insights utility functions > isTestFlaky"
- },
- {
- "name": "run-insights utility functions isTestFlaky should return false for failed tests with retries",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > run-insights utility functions > isTestFlaky"
- },
- {
- "name": "run-insights utility functions isTestFlaky should return false for passed tests without retries",
- "duration": 1,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > run-insights utility functions > isTestFlaky"
- },
- {
- "name": "run-insights utility functions isTestFlaky should return false for passed tests without retries property",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > run-insights utility functions > isTestFlaky"
- },
- {
- "name": "run-insights utility functions formatAsPercentage should format ratio as percentage with default 2 decimals",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > run-insights utility functions > formatAsPercentage"
- },
- {
- "name": "run-insights utility functions formatAsPercentage should format ratio as percentage with custom decimals",
- "duration": 1,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > run-insights utility functions > formatAsPercentage"
- },
- {
- "name": "run-insights utility functions formatAsPercentage should handle edge cases",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > run-insights utility functions > formatAsPercentage"
- },
- {
- "name": "run-insights utility functions formatInsightsMetricAsPercentage should format all metric values as percentages",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > run-insights utility functions > formatInsightsMetricAsPercentage"
- },
- {
- "name": "run-insights utility functions formatInsightsMetricAsPercentage should handle negative change values",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > run-insights utility functions > formatInsightsMetricAsPercentage"
- },
- {
- "name": "run-insights utility functions formatInsightsMetricAsPercentage should handle zero change values",
- "duration": 1,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > run-insights utility functions > formatInsightsMetricAsPercentage"
- },
- {
- "name": "enrichReportWithInsights - Main API basic functionality should enrich a report with run-level insights when no previous reports",
- "duration": 1,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > enrichReportWithInsights - Main API > basic functionality"
- },
- {
- "name": "enrichReportWithInsights - Main API basic functionality should add test-level insights to each test",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > enrichReportWithInsights - Main API > basic functionality"
- },
- {
- "name": "enrichReportWithInsights - Main API baseline comparison functionality should compare against previous report by default",
- "duration": 1,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > enrichReportWithInsights - Main API > baseline comparison functionality"
- },
- {
- "name": "enrichReportWithInsights - Main API baseline comparison functionality should handle baseline by index",
- "duration": 1,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > enrichReportWithInsights - Main API > baseline comparison functionality"
- },
- {
- "name": "enrichReportWithInsights - Main API baseline comparison functionality should handle baseline by report ID",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > enrichReportWithInsights - Main API > baseline comparison functionality"
- },
- {
- "name": "enrichReportWithInsights - Main API baseline comparison functionality should handle invalid baseline gracefully",
- "duration": 24,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > enrichReportWithInsights - Main API > baseline comparison functionality"
- },
- {
- "name": "enrichReportWithInsights - Main API added/removed tests tracking should track tests added since baseline",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > enrichReportWithInsights - Main API > added/removed tests tracking"
- },
- {
- "name": "enrichReportWithInsights - Main API added/removed tests tracking should track tests removed since baseline",
- "duration": 1,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > enrichReportWithInsights - Main API > added/removed tests tracking"
- },
- {
- "name": "enrichReportWithInsights - Main API added/removed tests tracking should handle single report no added/removed tests",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > enrichReportWithInsights - Main API > added/removed tests tracking"
- },
- {
- "name": "enrichReportWithInsights - Main API edge cases should handle empty current report",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > enrichReportWithInsights - Main API > edge cases"
- },
- {
- "name": "enrichReportWithInsights - Main API edge cases should handle invalid current report",
- "duration": 0,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > enrichReportWithInsights - Main API > edge cases"
- },
- {
- "name": "enrichReportWithInsights - Main API edge cases should handle multiple previous reports",
- "duration": 1,
- "status": "passed",
- "rawStatus": "passed",
- "type": "unit",
- "filePath": "/Users/matthew/projects/personal/ctrf/ctrf-js-common/src/__tests__/run-insights.test.ts",
- "retries": 0,
- "flaky": false,
- "suite": "run-insights.test.ts > enrichReportWithInsights - Main API > edge cases"
- }
- ]
- }
-}
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..5587594
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,38 @@
+**CTRF v0.0.13**
+
+***
+
+# CTRF v0.0.13
+
+## Enumerations
+
+- [SortOrder](enumerations/SortOrder.md)
+
+## Interfaces
+
+- [Attachment](interfaces/Attachment.md)
+- [Environment](interfaces/Environment.md)
+- [Insights](interfaces/Insights.md)
+- [InsightsMetric](interfaces/InsightsMetric.md)
+- [Report](interfaces/Report.md)
+- [Results](interfaces/Results.md)
+- [RetryAttempt](interfaces/RetryAttempt.md)
+- [Step](interfaces/Step.md)
+- [Summary](interfaces/Summary.md)
+- [Test](interfaces/Test.md)
+- [TestInsights](interfaces/TestInsights.md)
+- [Tool](interfaces/Tool.md)
+
+## Type Aliases
+
+- [TestStatus](type-aliases/TestStatus.md)
+
+## Functions
+
+- [enrichReportWithInsights](functions/enrichReportWithInsights.md)
+- [mergeReports](functions/mergeReports.md)
+- [readReportFromFile](functions/readReportFromFile.md)
+- [readReportsFromDirectory](functions/readReportsFromDirectory.md)
+- [readReportsFromGlobPattern](functions/readReportsFromGlobPattern.md)
+- [sortReportsByTimestamp](functions/sortReportsByTimestamp.md)
+- [storePreviousResults](functions/storePreviousResults.md)
diff --git a/docs/enumerations/SortOrder.md b/docs/enumerations/SortOrder.md
new file mode 100644
index 0000000..d4b8148
--- /dev/null
+++ b/docs/enumerations/SortOrder.md
@@ -0,0 +1,27 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / SortOrder
+
+# Enumeration: SortOrder
+
+Defined in: [src/methods/utilities/sort-reports.ts:6](https://github.com/ctrf-io/ctrf-core-js/blob/main/src/methods/utilities/sort-reports.ts#L6)
+
+Sort order options for timestamp-based sorting.
+
+## Enumeration Members
+
+### ASC
+
+> **ASC**: `"asc"`
+
+Defined in: [src/methods/utilities/sort-reports.ts:7](https://github.com/ctrf-io/ctrf-core-js/blob/main/src/methods/utilities/sort-reports.ts#L7)
+
+***
+
+### DESC
+
+> **DESC**: `"desc"`
+
+Defined in: [src/methods/utilities/sort-reports.ts:8](https://github.com/ctrf-io/ctrf-core-js/blob/main/src/methods/utilities/sort-reports.ts#L8)
diff --git a/docs/functions/enrichReportWithInsights.md b/docs/functions/enrichReportWithInsights.md
new file mode 100644
index 0000000..1d9082c
--- /dev/null
+++ b/docs/functions/enrichReportWithInsights.md
@@ -0,0 +1,37 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / enrichReportWithInsights
+
+# Function: enrichReportWithInsights()
+
+> **enrichReportWithInsights**(`currentReport`, `previousReports`, `baseline?`): [`Report`](../interfaces/Report.md)
+
+Defined in: [src/methods/run-insights.ts:818](https://github.com/ctrf-io/ctrf-core-js/blob/main/src/methods/run-insights.ts#L818)
+
+## Parameters
+
+### currentReport
+
+[`Report`](../interfaces/Report.md)
+
+The current CTRF report to enrich
+
+### previousReports
+
+[`Report`](../interfaces/Report.md)[] = `[]`
+
+Array of historical CTRF reports
+
+### baseline?
+
+[`Report`](../interfaces/Report.md)
+
+Optional baseline report to compare against. If not provided, no baseline comparisons are made.
+
+## Returns
+
+[`Report`](../interfaces/Report.md)
+
+The current report fully enriched with run-level insights, test-level insights, and baseline comparisons (if baseline provided)
diff --git a/docs/functions/mergeReports.md b/docs/functions/mergeReports.md
new file mode 100644
index 0000000..d0e3f0c
--- /dev/null
+++ b/docs/functions/mergeReports.md
@@ -0,0 +1,27 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / mergeReports
+
+# Function: mergeReports()
+
+> **mergeReports**(`reports`): [`Report`](../interfaces/Report.md)
+
+Defined in: [src/methods/merge-reports.ts:10](https://github.com/ctrf-io/ctrf-core-js/blob/main/src/methods/merge-reports.ts#L10)
+
+Merges multiple CTRF reports into a single report.
+
+## Parameters
+
+### reports
+
+[`Report`](../interfaces/Report.md)[]
+
+Array of CTRF report objects to be merged.
+
+## Returns
+
+[`Report`](../interfaces/Report.md)
+
+The merged CTRF report object.
diff --git a/docs/functions/readReportFromFile.md b/docs/functions/readReportFromFile.md
new file mode 100644
index 0000000..1553831
--- /dev/null
+++ b/docs/functions/readReportFromFile.md
@@ -0,0 +1,31 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / readReportFromFile
+
+# Function: readReportFromFile()
+
+> **readReportFromFile**(`filePath`): [`Report`](../interfaces/Report.md)
+
+Defined in: [src/methods/read-reports.ts:13](https://github.com/ctrf-io/ctrf-core-js/blob/main/src/methods/read-reports.ts#L13)
+
+Reads a single CTRF report file from a specified path.
+
+## Parameters
+
+### filePath
+
+`string`
+
+Path to the JSON file containing the CTRF report.
+
+## Returns
+
+[`Report`](../interfaces/Report.md)
+
+The parsed `CtrfReport` object.
+
+## Throws
+
+If the file does not exist, is not a valid JSON, or does not conform to the `CtrfReport` structure.
diff --git a/docs/functions/readReportsFromDirectory.md b/docs/functions/readReportsFromDirectory.md
new file mode 100644
index 0000000..73fdc24
--- /dev/null
+++ b/docs/functions/readReportsFromDirectory.md
@@ -0,0 +1,31 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / readReportsFromDirectory
+
+# Function: readReportsFromDirectory()
+
+> **readReportsFromDirectory**(`directoryPath`): [`Report`](../interfaces/Report.md)[]
+
+Defined in: [src/methods/read-reports.ts:48](https://github.com/ctrf-io/ctrf-core-js/blob/main/src/methods/read-reports.ts#L48)
+
+Reads all CTRF report files from a given directory.
+
+## Parameters
+
+### directoryPath
+
+`string`
+
+Path to the directory containing JSON files.
+
+## Returns
+
+[`Report`](../interfaces/Report.md)[]
+
+An array of parsed `CtrfReport` objects.
+
+## Throws
+
+If the directory does not exist or no valid CTRF reports are found.
diff --git a/docs/functions/readReportsFromGlobPattern.md b/docs/functions/readReportsFromGlobPattern.md
new file mode 100644
index 0000000..f31cf0f
--- /dev/null
+++ b/docs/functions/readReportsFromGlobPattern.md
@@ -0,0 +1,31 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / readReportsFromGlobPattern
+
+# Function: readReportsFromGlobPattern()
+
+> **readReportsFromGlobPattern**(`pattern`): [`Report`](../interfaces/Report.md)[]
+
+Defined in: [src/methods/read-reports.ts:95](https://github.com/ctrf-io/ctrf-core-js/blob/main/src/methods/read-reports.ts#L95)
+
+Reads all CTRF report files matching a glob pattern.
+
+## Parameters
+
+### pattern
+
+`string`
+
+The glob pattern to match files (e.g., ctrf/*.json).
+
+## Returns
+
+[`Report`](../interfaces/Report.md)[]
+
+An array of parsed `CtrfReport` objects.
+
+## Throws
+
+If no valid CTRF reports are found.
diff --git a/docs/functions/sortReportsByTimestamp.md b/docs/functions/sortReportsByTimestamp.md
new file mode 100644
index 0000000..87a14a4
--- /dev/null
+++ b/docs/functions/sortReportsByTimestamp.md
@@ -0,0 +1,52 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / sortReportsByTimestamp
+
+# Function: sortReportsByTimestamp()
+
+> **sortReportsByTimestamp**(`reports`, `order`): [`Report`](../interfaces/Report.md)[]
+
+Defined in: [src/methods/utilities/sort-reports.ts:38](https://github.com/ctrf-io/ctrf-core-js/blob/main/src/methods/utilities/sort-reports.ts#L38)
+
+Sorts CTRF reports by their timestamp.
+
+This function uses a fallback strategy for timestamp selection:
+1. First tries to use `report.timestamp` if available
+2. Falls back to `report.results.summary.stop` if `timestamp` is not available
+3. Reports without any timestamp are sorted to the end of the array
+
+## Parameters
+
+### reports
+
+[`Report`](../interfaces/Report.md)[]
+
+Array of CTRF reports to sort
+
+### order
+
+[`SortOrder`](../enumerations/SortOrder.md) = `SortOrder.DESC`
+
+Sort order: SortOrder.DESC for newest first (default), SortOrder.ASC for oldest first
+
+## Returns
+
+[`Report`](../interfaces/Report.md)[]
+
+A new array with reports sorted by timestamp
+
+## Example
+
+```typescript
+const unsortedReports = [report1, report2, report3];
+
+const newestFirst = sortReportsByTimestamp(unsortedReports);
+// newestFirst[0] will be the most recent report
+
+const oldestFirst = sortReportsByTimestamp(unsortedReports, SortOrder.ASC);
+// oldestFirst[0] will be the oldest report
+
+const newestFirst = sortReportsByTimestamp(unsortedReports, SortOrder.DESC);
+```
diff --git a/docs/functions/storePreviousResults.md b/docs/functions/storePreviousResults.md
new file mode 100644
index 0000000..4c3e765
--- /dev/null
+++ b/docs/functions/storePreviousResults.md
@@ -0,0 +1,34 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / storePreviousResults
+
+# Function: storePreviousResults()
+
+> **storePreviousResults**(`currentReport`, `previousReports`): [`Report`](../interfaces/Report.md)
+
+Defined in: [src/methods/store-previous-results.ts:34](https://github.com/ctrf-io/ctrf-core-js/blob/main/src/methods/store-previous-results.ts#L34)
+
+Stores previous results in the current report's previousResults array.
+Extracts key metrics from each previous report and adds them to the current report.
+
+## Parameters
+
+### currentReport
+
+[`Report`](../interfaces/Report.md)
+
+The current CTRF report to enrich with previous results
+
+### previousReports
+
+[`Report`](../interfaces/Report.md)[]
+
+Array of previous CTRF reports to extract metrics from
+
+## Returns
+
+[`Report`](../interfaces/Report.md)
+
+The current report with previousResults populated
diff --git a/docs/interfaces/Attachment.md b/docs/interfaces/Attachment.md
new file mode 100644
index 0000000..89aa66e
--- /dev/null
+++ b/docs/interfaces/Attachment.md
@@ -0,0 +1,41 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / Attachment
+
+# Interface: Attachment
+
+Defined in: [types/ctrf.d.ts:100](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L100)
+
+## Properties
+
+### contentType
+
+> **contentType**: `string`
+
+Defined in: [types/ctrf.d.ts:102](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L102)
+
+***
+
+### extra?
+
+> `optional` **extra**: `Record`\<`string`, `unknown`\>
+
+Defined in: [types/ctrf.d.ts:104](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L104)
+
+***
+
+### name
+
+> **name**: `string`
+
+Defined in: [types/ctrf.d.ts:101](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L101)
+
+***
+
+### path
+
+> **path**: `string`
+
+Defined in: [types/ctrf.d.ts:103](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L103)
diff --git a/docs/interfaces/Environment.md b/docs/interfaces/Environment.md
new file mode 100644
index 0000000..01af5ed
--- /dev/null
+++ b/docs/interfaces/Environment.md
@@ -0,0 +1,137 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / Environment
+
+# Interface: Environment
+
+Defined in: [types/ctrf.d.ts:69](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L69)
+
+## Properties
+
+### appName?
+
+> `optional` **appName**: `string`
+
+Defined in: [types/ctrf.d.ts:71](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L71)
+
+***
+
+### appVersion?
+
+> `optional` **appVersion**: `string`
+
+Defined in: [types/ctrf.d.ts:72](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L72)
+
+***
+
+### branchName?
+
+> `optional` **branchName**: `string`
+
+Defined in: [types/ctrf.d.ts:80](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L80)
+
+***
+
+### buildId?
+
+> `optional` **buildId**: `string`
+
+Defined in: [types/ctrf.d.ts:73](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L73)
+
+***
+
+### buildName?
+
+> `optional` **buildName**: `string`
+
+Defined in: [types/ctrf.d.ts:74](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L74)
+
+***
+
+### buildNumber?
+
+> `optional` **buildNumber**: `number`
+
+Defined in: [types/ctrf.d.ts:75](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L75)
+
+***
+
+### buildUrl?
+
+> `optional` **buildUrl**: `string`
+
+Defined in: [types/ctrf.d.ts:76](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L76)
+
+***
+
+### commit?
+
+> `optional` **commit**: `string`
+
+Defined in: [types/ctrf.d.ts:79](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L79)
+
+***
+
+### extra?
+
+> `optional` **extra**: `Record`\<`string`, `unknown`\>
+
+Defined in: [types/ctrf.d.ts:85](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L85)
+
+***
+
+### osPlatform?
+
+> `optional` **osPlatform**: `string`
+
+Defined in: [types/ctrf.d.ts:81](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L81)
+
+***
+
+### osRelease?
+
+> `optional` **osRelease**: `string`
+
+Defined in: [types/ctrf.d.ts:82](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L82)
+
+***
+
+### osVersion?
+
+> `optional` **osVersion**: `string`
+
+Defined in: [types/ctrf.d.ts:83](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L83)
+
+***
+
+### reportName?
+
+> `optional` **reportName**: `string`
+
+Defined in: [types/ctrf.d.ts:70](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L70)
+
+***
+
+### repositoryName?
+
+> `optional` **repositoryName**: `string`
+
+Defined in: [types/ctrf.d.ts:77](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L77)
+
+***
+
+### repositoryUrl?
+
+> `optional` **repositoryUrl**: `string`
+
+Defined in: [types/ctrf.d.ts:78](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L78)
+
+***
+
+### testEnvironment?
+
+> `optional` **testEnvironment**: `string`
+
+Defined in: [types/ctrf.d.ts:84](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L84)
diff --git a/docs/interfaces/Insights.md b/docs/interfaces/Insights.md
new file mode 100644
index 0000000..b474e7f
--- /dev/null
+++ b/docs/interfaces/Insights.md
@@ -0,0 +1,73 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / Insights
+
+# Interface: Insights
+
+Defined in: [types/ctrf.d.ts:123](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L123)
+
+## Properties
+
+### averageRunDuration?
+
+> `optional` **averageRunDuration**: [`InsightsMetric`](InsightsMetric.md)
+
+Defined in: [types/ctrf.d.ts:128](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L128)
+
+***
+
+### averageTestDuration?
+
+> `optional` **averageTestDuration**: [`InsightsMetric`](InsightsMetric.md)
+
+Defined in: [types/ctrf.d.ts:130](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L130)
+
+***
+
+### extra?
+
+> `optional` **extra**: `Record`\<`string`, `unknown`\>
+
+Defined in: [types/ctrf.d.ts:131](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L131)
+
+***
+
+### failRate?
+
+> `optional` **failRate**: [`InsightsMetric`](InsightsMetric.md)
+
+Defined in: [types/ctrf.d.ts:126](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L126)
+
+***
+
+### flakyRate?
+
+> `optional` **flakyRate**: [`InsightsMetric`](InsightsMetric.md)
+
+Defined in: [types/ctrf.d.ts:127](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L127)
+
+***
+
+### p95RunDuration?
+
+> `optional` **p95RunDuration**: [`InsightsMetric`](InsightsMetric.md)
+
+Defined in: [types/ctrf.d.ts:129](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L129)
+
+***
+
+### passRate?
+
+> `optional` **passRate**: [`InsightsMetric`](InsightsMetric.md)
+
+Defined in: [types/ctrf.d.ts:125](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L125)
+
+***
+
+### runsAnalyzed?
+
+> `optional` **runsAnalyzed**: `number`
+
+Defined in: [types/ctrf.d.ts:124](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L124)
diff --git a/docs/interfaces/InsightsMetric.md b/docs/interfaces/InsightsMetric.md
new file mode 100644
index 0000000..911497f
--- /dev/null
+++ b/docs/interfaces/InsightsMetric.md
@@ -0,0 +1,33 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / InsightsMetric
+
+# Interface: InsightsMetric
+
+Defined in: [types/ctrf.d.ts:144](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L144)
+
+## Properties
+
+### baseline
+
+> **baseline**: `number`
+
+Defined in: [types/ctrf.d.ts:146](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L146)
+
+***
+
+### change
+
+> **change**: `number`
+
+Defined in: [types/ctrf.d.ts:147](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L147)
+
+***
+
+### current
+
+> **current**: `number`
+
+Defined in: [types/ctrf.d.ts:145](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L145)
diff --git a/docs/interfaces/Report.md b/docs/interfaces/Report.md
new file mode 100644
index 0000000..b01829f
--- /dev/null
+++ b/docs/interfaces/Report.md
@@ -0,0 +1,81 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / Report
+
+# Interface: Report
+
+Defined in: [types/ctrf.d.ts:1](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L1)
+
+## Properties
+
+### baseline?
+
+> `optional` **baseline**: `Baseline`
+
+Defined in: [types/ctrf.d.ts:9](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L9)
+
+***
+
+### extra?
+
+> `optional` **extra**: `Record`\<`string`, `unknown`\>
+
+Defined in: [types/ctrf.d.ts:10](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L10)
+
+***
+
+### generatedBy?
+
+> `optional` **generatedBy**: `string`
+
+Defined in: [types/ctrf.d.ts:6](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L6)
+
+***
+
+### insights?
+
+> `optional` **insights**: [`Insights`](Insights.md)
+
+Defined in: [types/ctrf.d.ts:8](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L8)
+
+***
+
+### reportFormat
+
+> **reportFormat**: `"CTRF"`
+
+Defined in: [types/ctrf.d.ts:2](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L2)
+
+***
+
+### reportId?
+
+> `optional` **reportId**: `string`
+
+Defined in: [types/ctrf.d.ts:4](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L4)
+
+***
+
+### results
+
+> **results**: [`Results`](Results.md)
+
+Defined in: [types/ctrf.d.ts:7](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L7)
+
+***
+
+### specVersion
+
+> **specVersion**: `` `${number}.${number}.${number}` ``
+
+Defined in: [types/ctrf.d.ts:3](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L3)
+
+***
+
+### timestamp?
+
+> `optional` **timestamp**: `string`
+
+Defined in: [types/ctrf.d.ts:5](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L5)
diff --git a/docs/interfaces/Results.md b/docs/interfaces/Results.md
new file mode 100644
index 0000000..b87bc82
--- /dev/null
+++ b/docs/interfaces/Results.md
@@ -0,0 +1,49 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / Results
+
+# Interface: Results
+
+Defined in: [types/ctrf.d.ts:13](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L13)
+
+## Properties
+
+### environment?
+
+> `optional` **environment**: [`Environment`](Environment.md)
+
+Defined in: [types/ctrf.d.ts:17](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L17)
+
+***
+
+### extra?
+
+> `optional` **extra**: `Record`\<`string`, `unknown`\>
+
+Defined in: [types/ctrf.d.ts:18](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L18)
+
+***
+
+### summary
+
+> **summary**: [`Summary`](Summary.md)
+
+Defined in: [types/ctrf.d.ts:15](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L15)
+
+***
+
+### tests
+
+> **tests**: [`Test`](Test.md)[]
+
+Defined in: [types/ctrf.d.ts:16](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L16)
+
+***
+
+### tool
+
+> **tool**: [`Tool`](Tool.md)
+
+Defined in: [types/ctrf.d.ts:14](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L14)
diff --git a/docs/interfaces/RetryAttempt.md b/docs/interfaces/RetryAttempt.md
new file mode 100644
index 0000000..fd4d236
--- /dev/null
+++ b/docs/interfaces/RetryAttempt.md
@@ -0,0 +1,113 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / RetryAttempt
+
+# Interface: RetryAttempt
+
+Defined in: [types/ctrf.d.ts:107](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L107)
+
+## Properties
+
+### attachments?
+
+> `optional` **attachments**: [`Attachment`](Attachment.md)[]
+
+Defined in: [types/ctrf.d.ts:119](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L119)
+
+***
+
+### attempt
+
+> **attempt**: `number`
+
+Defined in: [types/ctrf.d.ts:108](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L108)
+
+***
+
+### duration?
+
+> `optional` **duration**: `number`
+
+Defined in: [types/ctrf.d.ts:110](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L110)
+
+***
+
+### extra?
+
+> `optional` **extra**: `Record`\<`string`, `unknown`\>
+
+Defined in: [types/ctrf.d.ts:120](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L120)
+
+***
+
+### line?
+
+> `optional` **line**: `number`
+
+Defined in: [types/ctrf.d.ts:113](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L113)
+
+***
+
+### message?
+
+> `optional` **message**: `string`
+
+Defined in: [types/ctrf.d.ts:111](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L111)
+
+***
+
+### snippet?
+
+> `optional` **snippet**: `string`
+
+Defined in: [types/ctrf.d.ts:114](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L114)
+
+***
+
+### start?
+
+> `optional` **start**: `number`
+
+Defined in: [types/ctrf.d.ts:117](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L117)
+
+***
+
+### status
+
+> **status**: [`TestStatus`](../type-aliases/TestStatus.md)
+
+Defined in: [types/ctrf.d.ts:109](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L109)
+
+***
+
+### stderr?
+
+> `optional` **stderr**: `string`[]
+
+Defined in: [types/ctrf.d.ts:116](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L116)
+
+***
+
+### stdout?
+
+> `optional` **stdout**: `string`[]
+
+Defined in: [types/ctrf.d.ts:115](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L115)
+
+***
+
+### stop?
+
+> `optional` **stop**: `number`
+
+Defined in: [types/ctrf.d.ts:118](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L118)
+
+***
+
+### trace?
+
+> `optional` **trace**: `string`
+
+Defined in: [types/ctrf.d.ts:112](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L112)
diff --git a/docs/interfaces/Step.md b/docs/interfaces/Step.md
new file mode 100644
index 0000000..637c65a
--- /dev/null
+++ b/docs/interfaces/Step.md
@@ -0,0 +1,33 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / Step
+
+# Interface: Step
+
+Defined in: [types/ctrf.d.ts:94](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L94)
+
+## Properties
+
+### extra?
+
+> `optional` **extra**: `Record`\<`string`, `unknown`\>
+
+Defined in: [types/ctrf.d.ts:97](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L97)
+
+***
+
+### name
+
+> **name**: `string`
+
+Defined in: [types/ctrf.d.ts:95](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L95)
+
+***
+
+### status
+
+> **status**: [`TestStatus`](../type-aliases/TestStatus.md)
+
+Defined in: [types/ctrf.d.ts:96](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L96)
diff --git a/docs/interfaces/Summary.md b/docs/interfaces/Summary.md
new file mode 100644
index 0000000..847ce34
--- /dev/null
+++ b/docs/interfaces/Summary.md
@@ -0,0 +1,105 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / Summary
+
+# Interface: Summary
+
+Defined in: [types/ctrf.d.ts:21](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L21)
+
+## Properties
+
+### duration
+
+> **duration**: `number`
+
+Defined in: [types/ctrf.d.ts:32](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L32)
+
+***
+
+### extra?
+
+> `optional` **extra**: `Record`\<`string`, `unknown`\>
+
+Defined in: [types/ctrf.d.ts:33](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L33)
+
+***
+
+### failed
+
+> **failed**: `number`
+
+Defined in: [types/ctrf.d.ts:24](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L24)
+
+***
+
+### flaky
+
+> **flaky**: `number`
+
+Defined in: [types/ctrf.d.ts:28](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L28)
+
+***
+
+### other
+
+> **other**: `number`
+
+Defined in: [types/ctrf.d.ts:27](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L27)
+
+***
+
+### passed
+
+> **passed**: `number`
+
+Defined in: [types/ctrf.d.ts:23](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L23)
+
+***
+
+### pending
+
+> **pending**: `number`
+
+Defined in: [types/ctrf.d.ts:26](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L26)
+
+***
+
+### skipped
+
+> **skipped**: `number`
+
+Defined in: [types/ctrf.d.ts:25](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L25)
+
+***
+
+### start
+
+> **start**: `number`
+
+Defined in: [types/ctrf.d.ts:30](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L30)
+
+***
+
+### stop
+
+> **stop**: `number`
+
+Defined in: [types/ctrf.d.ts:31](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L31)
+
+***
+
+### suites?
+
+> `optional` **suites**: `number`
+
+Defined in: [types/ctrf.d.ts:29](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L29)
+
+***
+
+### tests
+
+> **tests**: `number`
+
+Defined in: [types/ctrf.d.ts:22](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L22)
diff --git a/docs/interfaces/Test.md b/docs/interfaces/Test.md
new file mode 100644
index 0000000..f3dad27
--- /dev/null
+++ b/docs/interfaces/Test.md
@@ -0,0 +1,249 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / Test
+
+# Interface: Test
+
+Defined in: [types/ctrf.d.ts:36](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L36)
+
+## Properties
+
+### ai?
+
+> `optional` **ai**: `string`
+
+Defined in: [types/ctrf.d.ts:48](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L48)
+
+***
+
+### attachments?
+
+> `optional` **attachments**: [`Attachment`](Attachment.md)[]
+
+Defined in: [types/ctrf.d.ts:59](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L59)
+
+***
+
+### browser?
+
+> `optional` **browser**: `string`
+
+Defined in: [types/ctrf.d.ts:60](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L60)
+
+***
+
+### device?
+
+> `optional` **device**: `string`
+
+Defined in: [types/ctrf.d.ts:61](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L61)
+
+***
+
+### duration
+
+> **duration**: `number`
+
+Defined in: [types/ctrf.d.ts:40](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L40)
+
+***
+
+### extra?
+
+> `optional` **extra**: `Record`\<`string`, `unknown`\>
+
+Defined in: [types/ctrf.d.ts:66](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L66)
+
+***
+
+### filePath?
+
+> `optional` **filePath**: `string`
+
+Defined in: [types/ctrf.d.ts:52](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L52)
+
+***
+
+### flaky?
+
+> `optional` **flaky**: `boolean`
+
+Defined in: [types/ctrf.d.ts:55](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L55)
+
+***
+
+### id?
+
+> `optional` **id**: `string`
+
+Defined in: [types/ctrf.d.ts:37](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L37)
+
+***
+
+### insights?
+
+> `optional` **insights**: [`TestInsights`](TestInsights.md)
+
+Defined in: [types/ctrf.d.ts:65](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L65)
+
+***
+
+### line?
+
+> `optional` **line**: `number`
+
+Defined in: [types/ctrf.d.ts:47](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L47)
+
+***
+
+### message?
+
+> `optional` **message**: `string`
+
+Defined in: [types/ctrf.d.ts:44](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L44)
+
+***
+
+### name
+
+> **name**: `string`
+
+Defined in: [types/ctrf.d.ts:38](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L38)
+
+***
+
+### parameters?
+
+> `optional` **parameters**: `Record`\<`string`, `unknown`\>
+
+Defined in: [types/ctrf.d.ts:63](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L63)
+
+***
+
+### rawStatus?
+
+> `optional` **rawStatus**: `string`
+
+Defined in: [types/ctrf.d.ts:49](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L49)
+
+***
+
+### retries?
+
+> `optional` **retries**: `number`
+
+Defined in: [types/ctrf.d.ts:53](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L53)
+
+***
+
+### retryAttempts?
+
+> `optional` **retryAttempts**: [`RetryAttempt`](RetryAttempt.md)[]
+
+Defined in: [types/ctrf.d.ts:54](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L54)
+
+***
+
+### screenshot?
+
+> `optional` **screenshot**: `string`
+
+Defined in: [types/ctrf.d.ts:62](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L62)
+
+***
+
+### snippet?
+
+> `optional` **snippet**: `string`
+
+Defined in: [types/ctrf.d.ts:46](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L46)
+
+***
+
+### start?
+
+> `optional` **start**: `number`
+
+Defined in: [types/ctrf.d.ts:41](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L41)
+
+***
+
+### status
+
+> **status**: [`TestStatus`](../type-aliases/TestStatus.md)
+
+Defined in: [types/ctrf.d.ts:39](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L39)
+
+***
+
+### stderr?
+
+> `optional` **stderr**: `string`[]
+
+Defined in: [types/ctrf.d.ts:57](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L57)
+
+***
+
+### stdout?
+
+> `optional` **stdout**: `string`[]
+
+Defined in: [types/ctrf.d.ts:56](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L56)
+
+***
+
+### steps?
+
+> `optional` **steps**: [`Step`](Step.md)[]
+
+Defined in: [types/ctrf.d.ts:64](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L64)
+
+***
+
+### stop?
+
+> `optional` **stop**: `number`
+
+Defined in: [types/ctrf.d.ts:42](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L42)
+
+***
+
+### suite?
+
+> `optional` **suite**: `string`
+
+Defined in: [types/ctrf.d.ts:43](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L43)
+
+***
+
+### tags?
+
+> `optional` **tags**: `string`[]
+
+Defined in: [types/ctrf.d.ts:50](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L50)
+
+***
+
+### threadId?
+
+> `optional` **threadId**: `string`
+
+Defined in: [types/ctrf.d.ts:58](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L58)
+
+***
+
+### trace?
+
+> `optional` **trace**: `string`
+
+Defined in: [types/ctrf.d.ts:45](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L45)
+
+***
+
+### type?
+
+> `optional` **type**: `string`
+
+Defined in: [types/ctrf.d.ts:51](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L51)
diff --git a/docs/interfaces/TestInsights.md b/docs/interfaces/TestInsights.md
new file mode 100644
index 0000000..f803806
--- /dev/null
+++ b/docs/interfaces/TestInsights.md
@@ -0,0 +1,65 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / TestInsights
+
+# Interface: TestInsights
+
+Defined in: [types/ctrf.d.ts:134](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L134)
+
+## Properties
+
+### averageTestDuration?
+
+> `optional` **averageTestDuration**: [`InsightsMetric`](InsightsMetric.md)
+
+Defined in: [types/ctrf.d.ts:138](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L138)
+
+***
+
+### executedInRuns?
+
+> `optional` **executedInRuns**: `number`
+
+Defined in: [types/ctrf.d.ts:140](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L140)
+
+***
+
+### extra?
+
+> `optional` **extra**: `Record`\<`string`, `unknown`\>
+
+Defined in: [types/ctrf.d.ts:141](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L141)
+
+***
+
+### failRate?
+
+> `optional` **failRate**: [`InsightsMetric`](InsightsMetric.md)
+
+Defined in: [types/ctrf.d.ts:136](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L136)
+
+***
+
+### flakyRate?
+
+> `optional` **flakyRate**: [`InsightsMetric`](InsightsMetric.md)
+
+Defined in: [types/ctrf.d.ts:137](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L137)
+
+***
+
+### p95TestDuration?
+
+> `optional` **p95TestDuration**: [`InsightsMetric`](InsightsMetric.md)
+
+Defined in: [types/ctrf.d.ts:139](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L139)
+
+***
+
+### passRate?
+
+> `optional` **passRate**: [`InsightsMetric`](InsightsMetric.md)
+
+Defined in: [types/ctrf.d.ts:135](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L135)
diff --git a/docs/interfaces/Tool.md b/docs/interfaces/Tool.md
new file mode 100644
index 0000000..2599a01
--- /dev/null
+++ b/docs/interfaces/Tool.md
@@ -0,0 +1,33 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / Tool
+
+# Interface: Tool
+
+Defined in: [types/ctrf.d.ts:88](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L88)
+
+## Properties
+
+### extra?
+
+> `optional` **extra**: `Record`\<`string`, `unknown`\>
+
+Defined in: [types/ctrf.d.ts:91](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L91)
+
+***
+
+### name
+
+> **name**: `string`
+
+Defined in: [types/ctrf.d.ts:89](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L89)
+
+***
+
+### version?
+
+> `optional` **version**: `string`
+
+Defined in: [types/ctrf.d.ts:90](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L90)
diff --git a/docs/type-aliases/TestStatus.md b/docs/type-aliases/TestStatus.md
new file mode 100644
index 0000000..a7e6fa4
--- /dev/null
+++ b/docs/type-aliases/TestStatus.md
@@ -0,0 +1,11 @@
+[**CTRF v0.0.13**](../README.md)
+
+***
+
+[CTRF](../README.md) / TestStatus
+
+# Type Alias: TestStatus
+
+> **TestStatus** = `"passed"` \| `"failed"` \| `"skipped"` \| `"pending"` \| `"other"`
+
+Defined in: [types/ctrf.d.ts:160](https://github.com/ctrf-io/ctrf-core-js/blob/main/types/ctrf.d.ts#L160)
diff --git a/eslint.config.mjs b/eslint.config.mjs
new file mode 100644
index 0000000..2ebe1b2
--- /dev/null
+++ b/eslint.config.mjs
@@ -0,0 +1,35 @@
+// @ts-check
+import js from '@eslint/js'
+import typescript from 'typescript-eslint'
+
+export default [
+ {
+ ignores: [
+ 'node_modules/**',
+ 'dist/**',
+ 'coverage/**',
+ 'docs/**',
+ 'ctrf/**',
+ '*.js',
+ '*.mjs',
+ 'src/test-utils/**',
+ 'scripts/**',
+ 'examples/**',
+ 'final/**',
+ 'src/__tests__/**',
+ 'src/test-utils/**',
+ 'src/test-utils/**',
+ '**/*.test.ts',
+ 'src/cli.ts',
+ ],
+ },
+ js.configs.recommended,
+ ...typescript.configs.recommended,
+ {
+ files: ['**/*.ts'],
+ rules: {
+ '@typescript-eslint/no-explicit-any': 'warn',
+ '@typescript-eslint/no-unused-vars': 'error',
+ },
+ },
+]
diff --git a/jest.config.js b/jest.config.js
deleted file mode 100644
index 8f6d0a7..0000000
--- a/jest.config.js
+++ /dev/null
@@ -1,24 +0,0 @@
-export default {
- preset: 'ts-jest/presets/default-esm',
- extensionsToTreatAsEsm: ['.ts'],
- testEnvironment: 'node',
- testMatch: [
- '**/__tests__/**/*.test.ts',
- '**/?(*.)+(spec|test).ts'
- ],
- collectCoverageFrom: [
- 'src/**/*.ts',
- '!src/**/*.d.ts'
- ],
- coverageDirectory: 'coverage',
- coverageReporters: ['text', 'lcov', 'html'],
- transform: {
- '^.+\\.ts$': ['ts-jest', {
- useESM: true
- }]
- },
- reporters: [
- 'default',
- ['jest-ctrf-json-reporter', {}],
- ],
-};
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 6dbd3f2..0185cf3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "ctrf",
- "version": "0.0.13-next.0",
+ "version": "0.0.13",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "ctrf",
- "version": "0.0.13-next.0",
+ "version": "0.0.13",
"license": "MIT",
"dependencies": {
"glob": "^11.0.3",
@@ -17,16 +17,18 @@
"ctrf": "dist/cli.js"
},
"devDependencies": {
- "@types/jest": "^30.0.0",
+ "@d2t/vitest-ctrf-json-reporter": "^1.2.0",
+ "@eslint/js": "^9.32.0",
"@types/node": "^20.12.7",
"@types/yargs": "^17.0.32",
- "jest": "^30.0.4",
- "jest-ctrf-json-reporter": "^0.0.9",
- "jest-environment-node": "^30.0.4",
- "ts-jest": "^29.4.0",
- "tsx": "^4.19.2",
- "typedoc": "^0.28.8",
- "typescript": "^5.8.3"
+ "@vitest/coverage-v8": "^3.2.4",
+ "eslint": "^9.32.0",
+ "prettier": "^3.5.3",
+ "typedoc": "^0.28.9",
+ "typedoc-plugin-markdown": "^4.8.0",
+ "typescript": "^5.8.3",
+ "typescript-eslint": "^8.38.0",
+ "vitest": "^3.2.4"
},
"engines": {
"node": ">=20.19.0"
@@ -37,6 +39,7 @@
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
@@ -45,153 +48,12 @@
"node": ">=6.0.0"
}
},
- "node_modules/@babel/code-frame": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
- "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.27.1",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.1.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/compat-data": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz",
- "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/core": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz",
- "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==",
- "dev": true,
- "dependencies": {
- "@ampproject/remapping": "^2.2.0",
- "@babel/code-frame": "^7.27.1",
- "@babel/generator": "^7.28.0",
- "@babel/helper-compilation-targets": "^7.27.2",
- "@babel/helper-module-transforms": "^7.27.3",
- "@babel/helpers": "^7.27.6",
- "@babel/parser": "^7.28.0",
- "@babel/template": "^7.27.2",
- "@babel/traverse": "^7.28.0",
- "@babel/types": "^7.28.0",
- "convert-source-map": "^2.0.0",
- "debug": "^4.1.0",
- "gensync": "^1.0.0-beta.2",
- "json5": "^2.2.3",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/babel"
- }
- },
- "node_modules/@babel/generator": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz",
- "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.28.0",
- "@babel/types": "^7.28.0",
- "@jridgewell/gen-mapping": "^0.3.12",
- "@jridgewell/trace-mapping": "^0.3.28",
- "jsesc": "^3.0.2"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets": {
- "version": "7.27.2",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
- "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
- "dev": true,
- "dependencies": {
- "@babel/compat-data": "^7.27.2",
- "@babel/helper-validator-option": "^7.27.1",
- "browserslist": "^4.24.0",
- "lru-cache": "^5.1.1",
- "semver": "^6.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
- "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
- "dev": true,
- "dependencies": {
- "yallist": "^3.0.2"
- }
- },
- "node_modules/@babel/helper-globals": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
- "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-imports": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
- "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
- "dev": true,
- "dependencies": {
- "@babel/traverse": "^7.27.1",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-module-transforms": {
- "version": "7.27.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz",
- "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-module-imports": "^7.27.1",
- "@babel/helper-validator-identifier": "^7.27.1",
- "@babel/traverse": "^7.27.3"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/@babel/helper-plugin-utils": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz",
- "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/helper-string-parser": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
@@ -201,28 +63,7 @@
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-validator-option": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
- "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helpers": {
- "version": "7.27.6",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz",
- "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==",
- "dev": true,
- "dependencies": {
- "@babel/template": "^7.27.2",
- "@babel/types": "^7.27.6"
- },
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
@@ -232,6 +73,7 @@
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz",
"integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@babel/types": "^7.28.0"
},
@@ -242,265 +84,12 @@
"node": ">=6.0.0"
}
},
- "node_modules/@babel/plugin-syntax-async-generators": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
- "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-bigint": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
- "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-class-properties": {
- "version": "7.12.13",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
- "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.12.13"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-class-static-block": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
- "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-attributes": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz",
- "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-meta": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
- "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-json-strings": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
- "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz",
- "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
- "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
- "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-numeric-separator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
- "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-object-rest-spread": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
- "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-catch-binding": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
- "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-chaining": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
- "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-private-property-in-object": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
- "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-top-level-await": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
- "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-typescript": {
- "version": "7.27.1",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz",
- "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/template": {
- "version": "7.27.2",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
- "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.27.1",
- "@babel/parser": "^7.27.2",
- "@babel/types": "^7.27.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/traverse": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz",
- "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.27.1",
- "@babel/generator": "^7.28.0",
- "@babel/helper-globals": "^7.28.0",
- "@babel/parser": "^7.28.0",
- "@babel/template": "^7.27.2",
- "@babel/types": "^7.28.0",
- "debug": "^4.3.1"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/types": {
- "version": "7.28.0",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.0.tgz",
- "integrity": "sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==",
+ "version": "7.28.2",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
+ "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.27.1"
@@ -510,41 +99,21 @@
}
},
"node_modules/@bcoe/v8-coverage": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
- "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
- "dev": true
- },
- "node_modules/@emnapi/core": {
- "version": "1.4.4",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.4.tgz",
- "integrity": "sha512-A9CnAbC6ARNMKcIcrQwq6HeHCjpcBZ5wSx4U01WXCqEKlrzB9F9315WDNHkrs2xbx7YjjSxbUYxuN6EQzpcY2g==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "@emnapi/wasi-threads": "1.0.3",
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@emnapi/runtime": {
- "version": "1.4.4",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.4.tgz",
- "integrity": "sha512-hHyapA4A3gPaDCNfiqyZUStTMqIkKRshqPIuDOXv1hcBnD4U3l8cP0T1HMCfGRxQ6V64TGCcoswChANyOAwbQg==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz",
+ "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==",
"dev": true,
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
}
},
- "node_modules/@emnapi/wasi-threads": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.3.tgz",
- "integrity": "sha512-8K5IFFsQqF9wQNJptGbS6FNKgUTsSRYnTqNCG1vPP8jFdjSv18n2mQfJpkt2Oibo9iBEzcDnDxNwKTzC7svlJw==",
+ "node_modules/@d2t/vitest-ctrf-json-reporter": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@d2t/vitest-ctrf-json-reporter/-/vitest-ctrf-json-reporter-1.2.0.tgz",
+ "integrity": "sha512-CL+vAIdavJ3rr1IBE0lv5NvUtxigNTnNDo99hLMlgMkbOpzMvhV3EksQQt3CjweVVnPuTbiSqXXyqAKA7JINjg==",
"dev": true,
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
+ "license": "MIT"
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.6",
@@ -962,473 +531,338 @@
"node": ">=18"
}
},
- "node_modules/@gerrit0/mini-shiki": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.8.1.tgz",
- "integrity": "sha512-HVZW+8pxoOExr5ZMPK15U79jQAZTO/S6i5byQyyZGjtNj+qaYd82cizTncwFzTQgiLo8uUBym6vh+/1tfJklTw==",
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
+ "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@shikijs/engine-oniguruma": "^3.8.1",
- "@shikijs/langs": "^3.8.1",
- "@shikijs/themes": "^3.8.1",
- "@shikijs/types": "^3.8.1",
- "@shikijs/vscode-textmate": "^10.0.2"
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
}
},
- "node_modules/@isaacs/balanced-match": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
- "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": "20 || >=22"
- }
- },
- "node_modules/@isaacs/brace-expansion": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
- "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
- "dependencies": {
- "@isaacs/balanced-match": "^4.0.1"
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
- "engines": {
- "node": "20 || >=22"
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/@isaacs/cliui": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
- "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
- "dependencies": {
- "string-width": "^5.1.2",
- "string-width-cjs": "npm:string-width@^4.2.0",
- "strip-ansi": "^7.0.1",
- "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
- "wrap-ansi": "^8.1.0",
- "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
- },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=12"
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
- "node_modules/@istanbuljs/load-nyc-config": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
- "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
+ "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "camelcase": "^5.3.1",
- "find-up": "^4.1.0",
- "get-package-type": "^0.1.0",
- "js-yaml": "^3.13.1",
- "resolve-from": "^5.0.0"
+ "@eslint/object-schema": "^2.1.6",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
},
"engines": {
- "node": ">=8"
- }
- },
- "node_modules/@istanbuljs/schema": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
- "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@jest/console": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.0.4.tgz",
- "integrity": "sha512-tMLCDvBJBwPqMm4OAiuKm2uF5y5Qe26KgcMn+nrDSWpEW+eeFmqA0iO4zJfL16GP7gE3bUUQ3hIuUJ22AqVRnw==",
- "dev": true,
- "dependencies": {
- "@jest/types": "30.0.1",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "jest-message-util": "30.0.2",
- "jest-util": "30.0.2",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
- },
- "node_modules/@jest/core": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.0.4.tgz",
- "integrity": "sha512-MWScSO9GuU5/HoWjpXAOBs6F/iobvK1XlioelgOM9St7S0Z5WTI9kjCQLPeo4eQRRYusyLW25/J7J5lbFkrYXw==",
- "dev": true,
- "dependencies": {
- "@jest/console": "30.0.4",
- "@jest/pattern": "30.0.1",
- "@jest/reporters": "30.0.4",
- "@jest/test-result": "30.0.4",
- "@jest/transform": "30.0.4",
- "@jest/types": "30.0.1",
- "@types/node": "*",
- "ansi-escapes": "^4.3.2",
- "chalk": "^4.1.2",
- "ci-info": "^4.2.0",
- "exit-x": "^0.2.2",
- "graceful-fs": "^4.2.11",
- "jest-changed-files": "30.0.2",
- "jest-config": "30.0.4",
- "jest-haste-map": "30.0.2",
- "jest-message-util": "30.0.2",
- "jest-regex-util": "30.0.1",
- "jest-resolve": "30.0.2",
- "jest-resolve-dependencies": "30.0.4",
- "jest-runner": "30.0.4",
- "jest-runtime": "30.0.4",
- "jest-snapshot": "30.0.4",
- "jest-util": "30.0.2",
- "jest-validate": "30.0.2",
- "jest-watcher": "30.0.4",
- "micromatch": "^4.0.8",
- "pretty-format": "30.0.2",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@jest/diff-sequences": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz",
- "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==",
+ "node_modules/@eslint/config-array/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
- "node_modules/@jest/environment": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.4.tgz",
- "integrity": "sha512-5NT+sr7ZOb8wW7C4r7wOKnRQ8zmRWQT2gW4j73IXAKp5/PX1Z8MCStBLQDYfIG3n1Sw0NRfYGdp0iIPVooBAFQ==",
+ "node_modules/@eslint/config-array/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
+ "license": "ISC",
"dependencies": {
- "@jest/fake-timers": "30.0.4",
- "@jest/types": "30.0.1",
- "@types/node": "*",
- "jest-mock": "30.0.2"
+ "brace-expansion": "^1.1.7"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "*"
}
},
- "node_modules/@jest/expect": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.0.4.tgz",
- "integrity": "sha512-Z/DL7t67LBHSX4UzDyeYKqOxE/n7lbrrgEwWM3dGiH5Dgn35nk+YtgzKudmfIrBI8DRRrKYY5BCo3317HZV1Fw==",
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz",
+ "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==",
"dev": true,
- "dependencies": {
- "expect": "30.0.4",
- "jest-snapshot": "30.0.4"
- },
+ "license": "Apache-2.0",
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@jest/expect-utils": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.4.tgz",
- "integrity": "sha512-EgXecHDNfANeqOkcak0DxsoVI4qkDUsR7n/Lr2vtmTBjwLPBnnPOF71S11Q8IObWzxm2QgQoY6f9hzrRD3gHRA==",
+ "node_modules/@eslint/core": {
+ "version": "0.15.1",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz",
+ "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@jest/get-type": "30.0.1"
+ "@types/json-schema": "^7.0.15"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@jest/fake-timers": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.4.tgz",
- "integrity": "sha512-qZ7nxOcL5+gwBO6LErvwVy5k06VsX/deqo2XnVUSTV0TNC9lrg8FC3dARbi+5lmrr5VyX5drragK+xLcOjvjYw==",
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
+ "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/types": "30.0.1",
- "@sinonjs/fake-timers": "^13.0.0",
- "@types/node": "*",
- "jest-message-util": "30.0.2",
- "jest-mock": "30.0.2",
- "jest-util": "30.0.2"
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/@jest/get-type": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.0.1.tgz",
- "integrity": "sha512-AyYdemXCptSRFirI5EPazNxyPwAL0jXt3zceFjaj8NFiKP9pOi0bfXonf6qkf82z2t3QWPeLCWWw4stPBzctLw==",
+ "node_modules/@eslint/eslintrc/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- }
+ "license": "Python-2.0"
},
- "node_modules/@jest/globals": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.0.4.tgz",
- "integrity": "sha512-avyZuxEHF2EUhFF6NEWVdxkRRV6iXXcIES66DLhuLlU7lXhtFG/ySq/a8SRZmEJSsLkNAFX6z6mm8KWyXe9OEA==",
+ "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/environment": "30.0.4",
- "@jest/expect": "30.0.4",
- "@jest/types": "30.0.1",
- "jest-mock": "30.0.2"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
- "node_modules/@jest/pattern": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz",
- "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==",
+ "node_modules/@eslint/eslintrc/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@types/node": "*",
- "jest-regex-util": "30.0.1"
+ "argparse": "^2.0.1"
},
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/@jest/reporters": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.0.4.tgz",
- "integrity": "sha512-6ycNmP0JSJEEys1FbIzHtjl9BP0tOZ/KN6iMeAKrdvGmUsa1qfRdlQRUDKJ4P84hJ3xHw1yTqJt4fvPNHhyE+g==",
+ "node_modules/@eslint/eslintrc/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
+ "license": "ISC",
"dependencies": {
- "@bcoe/v8-coverage": "^0.2.3",
- "@jest/console": "30.0.4",
- "@jest/test-result": "30.0.4",
- "@jest/transform": "30.0.4",
- "@jest/types": "30.0.1",
- "@jridgewell/trace-mapping": "^0.3.25",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "collect-v8-coverage": "^1.0.2",
- "exit-x": "^0.2.2",
- "glob": "^10.3.10",
- "graceful-fs": "^4.2.11",
- "istanbul-lib-coverage": "^3.0.0",
- "istanbul-lib-instrument": "^6.0.0",
- "istanbul-lib-report": "^3.0.0",
- "istanbul-lib-source-maps": "^5.0.0",
- "istanbul-reports": "^3.1.3",
- "jest-message-util": "30.0.2",
- "jest-util": "30.0.2",
- "jest-worker": "30.0.2",
- "slash": "^3.0.0",
- "string-length": "^4.0.2",
- "v8-to-istanbul": "^9.0.1"
+ "brace-expansion": "^1.1.7"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
+ "node": "*"
}
},
- "node_modules/@jest/reporters/node_modules/glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "node_modules/@eslint/js": {
+ "version": "9.32.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz",
+ "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==",
"dev": true,
- "dependencies": {
- "foreground-child": "^3.1.0",
- "jackspeak": "^3.1.2",
- "minimatch": "^9.0.4",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^1.11.1"
- },
- "bin": {
- "glob": "dist/esm/bin.mjs"
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://eslint.org/donate"
}
},
- "node_modules/@jest/reporters/node_modules/jackspeak": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
- "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+ "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
"dev": true,
- "dependencies": {
- "@isaacs/cliui": "^8.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- },
- "optionalDependencies": {
- "@pkgjs/parseargs": "^0.11.0"
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@jest/reporters/node_modules/lru-cache": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "dev": true
- },
- "node_modules/@jest/reporters/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz",
+ "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "brace-expansion": "^2.0.1"
+ "@eslint/core": "^0.15.1",
+ "levn": "^0.4.1"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@jest/reporters/node_modules/path-scurry": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
- "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "node_modules/@gerrit0/mini-shiki": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.9.2.tgz",
+ "integrity": "sha512-Tvsj+AOO4Z8xLRJK900WkyfxHsZQu+Zm1//oT1w443PO6RiYMoq/4NGOhaNuZoUMYsjKIAPVQ6eOFMddj6yphQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "lru-cache": "^10.2.0",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
- },
- "engines": {
- "node": ">=16 || 14 >=14.18"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "@shikijs/engine-oniguruma": "^3.9.2",
+ "@shikijs/langs": "^3.9.2",
+ "@shikijs/themes": "^3.9.2",
+ "@shikijs/types": "^3.9.2",
+ "@shikijs/vscode-textmate": "^10.0.2"
}
},
- "node_modules/@jest/schemas": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.1.tgz",
- "integrity": "sha512-+g/1TKjFuGrf1Hh0QPCv0gISwBxJ+MQSNXmG9zjHy7BmFhtoJ9fdNhWJp3qUKRi93AOZHXtdxZgJ1vAtz6z65w==",
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
"dev": true,
- "dependencies": {
- "@sinclair/typebox": "^0.34.0"
- },
+ "license": "Apache-2.0",
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=18.18.0"
}
},
- "node_modules/@jest/snapshot-utils": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.0.4.tgz",
- "integrity": "sha512-BEpX8M/Y5lG7MI3fmiO+xCnacOrVsnbqVrcDZIT8aSGkKV1w2WwvRQxSWw5SIS8ozg7+h8tSj5EO1Riqqxcdag==",
+ "node_modules/@humanfs/node": {
+ "version": "0.16.6",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
+ "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@jest/types": "30.0.1",
- "chalk": "^4.1.2",
- "graceful-fs": "^4.2.11",
- "natural-compare": "^1.4.0"
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.3.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=18.18.0"
}
},
- "node_modules/@jest/source-map": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz",
- "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==",
+ "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+ "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
"dev": true,
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.25",
- "callsites": "^3.1.0",
- "graceful-fs": "^4.2.11"
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
},
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
}
},
- "node_modules/@jest/test-result": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.0.4.tgz",
- "integrity": "sha512-Mfpv8kjyKTHqsuu9YugB6z1gcdB3TSSOaKlehtVaiNlClMkEHY+5ZqCY2CrEE3ntpBMlstX/ShDAf84HKWsyIw==",
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
"dev": true,
- "dependencies": {
- "@jest/console": "30.0.4",
- "@jest/types": "30.0.1",
- "@types/istanbul-lib-coverage": "^2.0.6",
- "collect-v8-coverage": "^1.0.2"
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
},
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@isaacs/balanced-match": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
+ "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "20 || >=22"
}
},
- "node_modules/@jest/test-sequencer": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.0.4.tgz",
- "integrity": "sha512-bj6ePmqi4uxAE8EHE0Slmk5uBYd9Vd/PcVt06CsBxzH4bbA8nGsI1YbXl/NH+eii4XRtyrRx+Cikub0x8H4vDg==",
- "dev": true,
+ "node_modules/@isaacs/brace-expansion": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
+ "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
"dependencies": {
- "@jest/test-result": "30.0.4",
- "graceful-fs": "^4.2.11",
- "jest-haste-map": "30.0.2",
- "slash": "^3.0.0"
+ "@isaacs/balanced-match": "^4.0.1"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "20 || >=22"
}
},
- "node_modules/@jest/transform": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.4.tgz",
- "integrity": "sha512-atvy4hRph/UxdCIBp+UB2jhEA/jJiUeGZ7QPgBi9jUUKNgi3WEoMXGNG7zbbELG2+88PMabUNCDchmqgJy3ELg==",
- "dev": true,
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"dependencies": {
- "@babel/core": "^7.27.4",
- "@jest/types": "30.0.1",
- "@jridgewell/trace-mapping": "^0.3.25",
- "babel-plugin-istanbul": "^7.0.0",
- "chalk": "^4.1.2",
- "convert-source-map": "^2.0.0",
- "fast-json-stable-stringify": "^2.1.0",
- "graceful-fs": "^4.2.11",
- "jest-haste-map": "30.0.2",
- "jest-regex-util": "30.0.1",
- "jest-util": "30.0.2",
- "micromatch": "^4.0.8",
- "pirates": "^4.0.7",
- "slash": "^3.0.0",
- "write-file-atomic": "^5.0.1"
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=12"
}
},
- "node_modules/@jest/types": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.1.tgz",
- "integrity": "sha512-HGwoYRVF0QSKJu1ZQX0o5ZrUrrhj0aOOFA8hXrumD7SIzjouevhawbTjmXdwOmURdGluU9DM/XvGm3NyFoiQjw==",
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
"dev": true,
- "dependencies": {
- "@jest/pattern": "30.0.1",
- "@jest/schemas": "30.0.1",
- "@types/istanbul-lib-coverage": "^2.0.6",
- "@types/istanbul-reports": "^3.0.4",
- "@types/node": "*",
- "@types/yargs": "^17.0.33",
- "chalk": "^4.1.2"
- },
+ "license": "MIT",
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=8"
}
},
"node_modules/@jridgewell/gen-mapping": {
@@ -1436,6 +870,7 @@
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
"integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
@@ -1446,6 +881,7 @@
"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"
}
@@ -1461,2528 +897,1955 @@
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
"integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
- "node_modules/@napi-rs/wasm-runtime": {
- "version": "0.2.12",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz",
- "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==",
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
"dev": true,
- "optional": true,
+ "license": "MIT",
"dependencies": {
- "@emnapi/core": "^1.4.3",
- "@emnapi/runtime": "^1.4.3",
- "@tybys/wasm-util": "^0.10.0"
- }
- },
- "node_modules/@pkgjs/parseargs": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
- "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
- "dev": true,
- "optional": true,
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
"engines": {
- "node": ">=14"
+ "node": ">= 8"
}
},
- "node_modules/@pkgr/core": {
- "version": "0.2.7",
- "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz",
- "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==",
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/pkgr"
+ "node": ">= 8"
}
},
- "node_modules/@shikijs/engine-oniguruma": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.8.1.tgz",
- "integrity": "sha512-KGQJZHlNY7c656qPFEQpIoqOuC4LrxjyNndRdzk5WKB/Ie87+NJCF1xo9KkOUxwxylk7rT6nhlZyTGTC4fCe1g==",
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@shikijs/types": "3.8.1",
- "@shikijs/vscode-textmate": "^10.0.2"
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
}
},
- "node_modules/@shikijs/langs": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.8.1.tgz",
- "integrity": "sha512-TjOFg2Wp1w07oKnXjs0AUMb4kJvujML+fJ1C5cmEj45lhjbUXtziT1x2bPQb9Db6kmPhkG5NI2tgYW1/DzhUuQ==",
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"dev": true,
- "dependencies": {
- "@shikijs/types": "3.8.1"
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
}
},
- "node_modules/@shikijs/themes": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.8.1.tgz",
- "integrity": "sha512-Vu3t3BBLifc0GB0UPg2Pox1naTemrrvyZv2lkiSw3QayVV60me1ujFQwPZGgUTmwXl1yhCPW8Lieesm0CYruLQ==",
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz",
+ "integrity": "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==",
+ "cpu": [
+ "arm"
+ ],
"dev": true,
- "dependencies": {
- "@shikijs/types": "3.8.1"
- }
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
},
- "node_modules/@shikijs/types": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.8.1.tgz",
- "integrity": "sha512-5C39Q8/8r1I26suLh+5TPk1DTrbY/kn3IdWA5HdizR0FhlhD05zx5nKCqhzSfDHH3p4S0ZefxWd77DLV+8FhGg==",
- "dev": true,
- "dependencies": {
- "@shikijs/vscode-textmate": "^10.0.2",
- "@types/hast": "^3.0.4"
- }
- },
- "node_modules/@shikijs/vscode-textmate": {
- "version": "10.0.2",
- "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
- "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
- "dev": true
- },
- "node_modules/@sinclair/typebox": {
- "version": "0.34.37",
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.37.tgz",
- "integrity": "sha512-2TRuQVgQYfy+EzHRTIvkhv2ADEouJ2xNS/Vq+W5EuuewBdOrvATvljZTxHWZSTYr2sTjTHpGvucaGAt67S2akw==",
- "dev": true
- },
- "node_modules/@sinonjs/commons": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
- "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
- "dev": true,
- "dependencies": {
- "type-detect": "4.0.8"
- }
- },
- "node_modules/@sinonjs/fake-timers": {
- "version": "13.0.5",
- "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz",
- "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==",
- "dev": true,
- "dependencies": {
- "@sinonjs/commons": "^3.0.1"
- }
- },
- "node_modules/@tybys/wasm-util": {
- "version": "0.10.0",
- "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz",
- "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "tslib": "^2.4.0"
- }
- },
- "node_modules/@types/babel__core": {
- "version": "7.20.5",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
- "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
- }
- },
- "node_modules/@types/babel__generator": {
- "version": "7.27.0",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
- "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__template": {
- "version": "7.4.4",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
- "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__traverse": {
- "version": "7.20.7",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz",
- "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.20.7"
- }
- },
- "node_modules/@types/hast": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
- "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
- "dev": true,
- "dependencies": {
- "@types/unist": "*"
- }
- },
- "node_modules/@types/istanbul-lib-coverage": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
- "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
- "dev": true
- },
- "node_modules/@types/istanbul-lib-report": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
- "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
- "dev": true,
- "dependencies": {
- "@types/istanbul-lib-coverage": "*"
- }
- },
- "node_modules/@types/istanbul-reports": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
- "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
- "dev": true,
- "dependencies": {
- "@types/istanbul-lib-report": "*"
- }
- },
- "node_modules/@types/jest": {
- "version": "30.0.0",
- "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz",
- "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==",
- "dev": true,
- "dependencies": {
- "expect": "^30.0.0",
- "pretty-format": "^30.0.0"
- }
- },
- "node_modules/@types/node": {
- "version": "20.19.7",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.7.tgz",
- "integrity": "sha512-1GM9z6BJOv86qkPvzh2i6VW5+VVrXxCLknfmTkWEqz+6DqosiY28XUWCTmBcJ0ACzKqx/iwdIREfo1fwExIlkA==",
- "dev": true,
- "dependencies": {
- "undici-types": "~6.21.0"
- }
- },
- "node_modules/@types/stack-utils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
- "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
- "dev": true
- },
- "node_modules/@types/unist": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
- "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
- "dev": true
- },
- "node_modules/@types/yargs": {
- "version": "17.0.33",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
- "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
- "dev": true,
- "dependencies": {
- "@types/yargs-parser": "*"
- }
- },
- "node_modules/@types/yargs-parser": {
- "version": "21.0.3",
- "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
- "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
- "dev": true
- },
- "node_modules/@ungap/structured-clone": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
- "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
- "dev": true
- },
- "node_modules/@unrs/resolver-binding-android-arm-eabi": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz",
- "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==",
- "cpu": [
- "arm"
- ],
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.2.tgz",
+ "integrity": "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==",
+ "cpu": [
+ "arm64"
+ ],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"android"
]
},
- "node_modules/@unrs/resolver-binding-android-arm64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz",
- "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==",
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.2.tgz",
+ "integrity": "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==",
"cpu": [
"arm64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
- "android"
+ "darwin"
]
},
- "node_modules/@unrs/resolver-binding-darwin-arm64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz",
- "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==",
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.2.tgz",
+ "integrity": "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==",
"cpu": [
- "arm64"
+ "x64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"darwin"
]
},
- "node_modules/@unrs/resolver-binding-darwin-x64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz",
- "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==",
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.2.tgz",
+ "integrity": "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==",
"cpu": [
- "x64"
+ "arm64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
- "darwin"
+ "freebsd"
]
},
- "node_modules/@unrs/resolver-binding-freebsd-x64": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz",
- "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==",
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.2.tgz",
+ "integrity": "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==",
"cpu": [
"x64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"freebsd"
]
},
- "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz",
- "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==",
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.2.tgz",
+ "integrity": "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==",
"cpu": [
"arm"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
- "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz",
- "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==",
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.2.tgz",
+ "integrity": "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==",
"cpu": [
"arm"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
- "node_modules/@unrs/resolver-binding-linux-arm64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz",
- "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==",
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.2.tgz",
+ "integrity": "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==",
"cpu": [
"arm64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
- "node_modules/@unrs/resolver-binding-linux-arm64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz",
- "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==",
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.2.tgz",
+ "integrity": "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==",
"cpu": [
"arm64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
- "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz",
- "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==",
+ "node_modules/@rollup/rollup-linux-loongarch64-gnu": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.2.tgz",
+ "integrity": "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==",
"cpu": [
- "ppc64"
+ "loong64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
- "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz",
- "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==",
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.2.tgz",
+ "integrity": "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==",
"cpu": [
- "riscv64"
+ "ppc64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
- "node_modules/@unrs/resolver-binding-linux-riscv64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz",
- "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==",
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.2.tgz",
+ "integrity": "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==",
"cpu": [
"riscv64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
- "node_modules/@unrs/resolver-binding-linux-s390x-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz",
- "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==",
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.2.tgz",
+ "integrity": "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==",
"cpu": [
- "s390x"
+ "riscv64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
- "node_modules/@unrs/resolver-binding-linux-x64-gnu": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz",
- "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==",
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.2.tgz",
+ "integrity": "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==",
"cpu": [
- "x64"
+ "s390x"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
- "node_modules/@unrs/resolver-binding-linux-x64-musl": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz",
- "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==",
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.2.tgz",
+ "integrity": "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==",
"cpu": [
"x64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
]
},
- "node_modules/@unrs/resolver-binding-wasm32-wasi": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz",
- "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==",
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.2.tgz",
+ "integrity": "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==",
"cpu": [
- "wasm32"
+ "x64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
- "dependencies": {
- "@napi-rs/wasm-runtime": "^0.2.11"
- },
- "engines": {
- "node": ">=14.0.0"
- }
+ "os": [
+ "linux"
+ ]
},
- "node_modules/@unrs/resolver-binding-win32-arm64-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz",
- "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==",
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.2.tgz",
+ "integrity": "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==",
"cpu": [
"arm64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"win32"
]
},
- "node_modules/@unrs/resolver-binding-win32-ia32-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz",
- "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==",
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.2.tgz",
+ "integrity": "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==",
"cpu": [
"ia32"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"win32"
]
},
- "node_modules/@unrs/resolver-binding-win32-x64-msvc": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz",
- "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==",
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.2.tgz",
+ "integrity": "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==",
"cpu": [
"x64"
],
"dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"win32"
]
},
- "node_modules/ansi-escapes": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
- "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "node_modules/@shikijs/engine-oniguruma": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.9.2.tgz",
+ "integrity": "sha512-Vn/w5oyQ6TUgTVDIC/BrpXwIlfK6V6kGWDVVz2eRkF2v13YoENUvaNwxMsQU/t6oCuZKzqp9vqtEtEzKl9VegA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "type-fest": "^0.21.3"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/ansi-regex": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
- "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ "@shikijs/types": "3.9.2",
+ "@shikijs/vscode-textmate": "^10.0.2"
}
},
- "node_modules/ansi-styles": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
- "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ "node_modules/@shikijs/langs": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.9.2.tgz",
+ "integrity": "sha512-X1Q6wRRQXY7HqAuX3I8WjMscjeGjqXCg/Sve7J2GWFORXkSrXud23UECqTBIdCSNKJioFtmUGJQNKtlMMZMn0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.9.2"
}
},
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "node_modules/@shikijs/themes": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.9.2.tgz",
+ "integrity": "sha512-6z5lBPBMRfLyyEsgf6uJDHPa6NAGVzFJqH4EAZ+03+7sedYir2yJBRu2uPZOKmj43GyhVHWHvyduLDAwJQfDjA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
+ "@shikijs/types": "3.9.2"
}
},
- "node_modules/argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "node_modules/@shikijs/types": {
+ "version": "3.9.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.9.2.tgz",
+ "integrity": "sha512-/M5L0Uc2ljyn2jKvj4Yiah7ow/W+DJSglVafvWAJ/b8AZDeeRAdMu3c2riDzB7N42VD+jSnWxeP9AKtd4TfYVw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "sprintf-js": "~1.0.2"
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
}
},
- "node_modules/async": {
- "version": "3.2.6",
- "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
- "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
- "dev": true
+ "node_modules/@shikijs/vscode-textmate": {
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
+ "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/babel-jest": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.0.4.tgz",
- "integrity": "sha512-UjG2j7sAOqsp2Xua1mS/e+ekddkSu3wpf4nZUSvXNHuVWdaOUXQ77+uyjJLDE9i0atm5x4kds8K9yb5lRsRtcA==",
+ "node_modules/@types/chai": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz",
+ "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/transform": "30.0.4",
- "@types/babel__core": "^7.20.5",
- "babel-plugin-istanbul": "^7.0.0",
- "babel-preset-jest": "30.0.1",
- "chalk": "^4.1.2",
- "graceful-fs": "^4.2.11",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.11.0"
+ "@types/deep-eql": "*"
}
},
- "node_modules/babel-plugin-istanbul": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz",
- "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==",
+ "node_modules/@types/deep-eql": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
+ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
"dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@istanbuljs/load-nyc-config": "^1.0.0",
- "@istanbuljs/schema": "^0.1.3",
- "istanbul-lib-instrument": "^6.0.2",
- "test-exclude": "^6.0.0"
- },
- "engines": {
- "node": ">=12"
- }
+ "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/babel-plugin-jest-hoist": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.0.1.tgz",
- "integrity": "sha512-zTPME3pI50NsFW8ZBaVIOeAxzEY7XHlmWeXXu9srI+9kNfzCUTy8MFan46xOGZY8NZThMqq+e3qZUKsvXbasnQ==",
+ "node_modules/@types/hast": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
+ "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/template": "^7.27.2",
- "@babel/types": "^7.27.3",
- "@types/babel__core": "^7.20.5"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "@types/unist": "*"
}
},
- "node_modules/babel-preset-current-node-syntax": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz",
- "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==",
- "dev": true,
- "dependencies": {
- "@babel/plugin-syntax-async-generators": "^7.8.4",
- "@babel/plugin-syntax-bigint": "^7.8.3",
- "@babel/plugin-syntax-class-properties": "^7.12.13",
- "@babel/plugin-syntax-class-static-block": "^7.14.5",
- "@babel/plugin-syntax-import-attributes": "^7.24.7",
- "@babel/plugin-syntax-import-meta": "^7.10.4",
- "@babel/plugin-syntax-json-strings": "^7.8.3",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
- "@babel/plugin-syntax-top-level-await": "^7.14.5"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/babel-preset-jest": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.0.1.tgz",
- "integrity": "sha512-+YHejD5iTWI46cZmcc/YtX4gaKBtdqCHCVfuVinizVpbmyjO3zYmeuyFdfA8duRqQZfgCAMlsfmkVbJ+e2MAJw==",
+ "node_modules/@types/node": {
+ "version": "20.19.7",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.7.tgz",
+ "integrity": "sha512-1GM9z6BJOv86qkPvzh2i6VW5+VVrXxCLknfmTkWEqz+6DqosiY28XUWCTmBcJ0ACzKqx/iwdIREfo1fwExIlkA==",
"dev": true,
"dependencies": {
- "babel-plugin-jest-hoist": "30.0.1",
- "babel-preset-current-node-syntax": "^1.1.0"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.11.0"
+ "undici-types": "~6.21.0"
}
},
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/brace-expansion": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
- "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
"dev": true,
"dependencies": {
- "balanced-match": "^1.0.0"
+ "@types/yargs-parser": "*"
}
},
- "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==",
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.39.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.0.tgz",
+ "integrity": "sha512-bhEz6OZeUR+O/6yx9Jk6ohX6H9JSFTaiY0v9/PuKT3oGK0rn0jNplLmyFUGV+a9gfYnVNwGDwS/UkLIuXNb2Rw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "fill-range": "^7.1.1"
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "8.39.0",
+ "@typescript-eslint/type-utils": "8.39.0",
+ "@typescript-eslint/utils": "8.39.0",
+ "@typescript-eslint/visitor-keys": "8.39.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^7.0.0",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.1.0"
},
"engines": {
- "node": ">=8"
- }
- },
- "node_modules/browserslist": {
- "version": "4.25.1",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz",
- "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "dependencies": {
- "caniuse-lite": "^1.0.30001726",
- "electron-to-chromium": "^1.5.173",
- "node-releases": "^2.0.19",
- "update-browserslist-db": "^1.1.3"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
- "bin": {
- "browserslist": "cli.js"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
},
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.39.0",
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
}
},
- "node_modules/bs-logger": {
- "version": "0.2.6",
- "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
- "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
"dev": true,
- "dependencies": {
- "fast-json-stable-stringify": "2.x"
- },
+ "license": "MIT",
"engines": {
- "node": ">= 6"
+ "node": ">= 4"
}
},
- "node_modules/bser": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
- "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.39.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.0.tgz",
+ "integrity": "sha512-g3WpVQHngx0aLXn6kfIYCZxM6rRJlWzEkVpqEFLT3SgEDsp9cpCbxxgwnE504q4H+ruSDh/VGS6nqZIDynP+vg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "node-int64": "^0.4.0"
- }
- },
- "node_modules/buffer-from": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
- "dev": true
- },
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true,
+ "@typescript-eslint/scope-manager": "8.39.0",
+ "@typescript-eslint/types": "8.39.0",
+ "@typescript-eslint/typescript-estree": "8.39.0",
+ "@typescript-eslint/visitor-keys": "8.39.0",
+ "debug": "^4.3.4"
+ },
"engines": {
- "node": ">=6"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
}
},
- "node_modules/caniuse-lite": {
- "version": "1.0.30001727",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz",
- "integrity": "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ]
- },
- "node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.39.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.0.tgz",
+ "integrity": "sha512-CTzJqaSq30V/Z2Og9jogzZt8lJRR5TKlAdXmWgdu4hgcC9Kww5flQ+xFvMxIBWVNdxJO7OifgdOK4PokMIWPew==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
+ "@typescript-eslint/tsconfig-utils": "^8.39.0",
+ "@typescript-eslint/types": "^8.39.0",
+ "debug": "^4.3.4"
},
"engines": {
- "node": ">=10"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
}
},
- "node_modules/chalk/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.39.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.0.tgz",
+ "integrity": "sha512-8QOzff9UKxOh6npZQ/4FQu4mjdOCGSdO3p44ww0hk8Vu+IGbg0tB/H1LcTARRDzGCC8pDGbh2rissBuuoPgH8A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "color-convert": "^2.0.1"
+ "@typescript-eslint/types": "8.39.0",
+ "@typescript-eslint/visitor-keys": "8.39.0"
},
"engines": {
- "node": ">=8"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
}
},
- "node_modules/char-regex": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
- "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.39.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.0.tgz",
+ "integrity": "sha512-Fd3/QjmFV2sKmvv3Mrj8r6N8CryYiCS8Wdb/6/rgOXAWGcFuc+VkQuG28uk/4kVNVZBQuuDHEDUpo/pQ32zsIQ==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=10"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
}
},
- "node_modules/ci-info": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz",
- "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==",
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.39.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.0.tgz",
+ "integrity": "sha512-6B3z0c1DXVT2vYA9+z9axjtc09rqKUPRmijD5m9iv8iQpHBRYRMBcgxSiKTZKm6FwWw1/cI4v6em35OsKCiN5Q==",
"dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cjs-module-lexer": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz",
- "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==",
- "dev": true
- },
- "node_modules/cliui": {
- "version": "9.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz",
- "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==",
+ "license": "MIT",
"dependencies": {
- "string-width": "^7.2.0",
- "strip-ansi": "^7.1.0",
- "wrap-ansi": "^9.0.0"
+ "@typescript-eslint/types": "8.39.0",
+ "@typescript-eslint/typescript-estree": "8.39.0",
+ "@typescript-eslint/utils": "8.39.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^2.1.0"
},
"engines": {
- "node": ">=20"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
}
},
- "node_modules/cliui/node_modules/emoji-regex": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
- "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="
- },
- "node_modules/cliui/node_modules/string-width": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
- "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
- "dependencies": {
- "emoji-regex": "^10.3.0",
- "get-east-asian-width": "^1.0.0",
- "strip-ansi": "^7.1.0"
- },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.39.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.0.tgz",
+ "integrity": "sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=18"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
}
},
- "node_modules/cliui/node_modules/wrap-ansi": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
- "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.39.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.0.tgz",
+ "integrity": "sha512-ndWdiflRMvfIgQRpckQQLiB5qAKQ7w++V4LlCHwp62eym1HLB/kw7D9f2e8ytONls/jt89TEasgvb+VwnRprsw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "ansi-styles": "^6.2.1",
- "string-width": "^7.0.0",
- "strip-ansi": "^7.1.0"
+ "@typescript-eslint/project-service": "8.39.0",
+ "@typescript-eslint/tsconfig-utils": "8.39.0",
+ "@typescript-eslint/types": "8.39.0",
+ "@typescript-eslint/visitor-keys": "8.39.0",
+ "debug": "^4.3.4",
+ "fast-glob": "^3.3.2",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^2.1.0"
},
"engines": {
- "node": ">=18"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
}
},
- "node_modules/co": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
- "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
- "engines": {
- "iojs": ">= 1.0.0",
- "node": ">= 0.12.0"
- }
- },
- "node_modules/collect-v8-coverage": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
- "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==",
- "dev": true
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "ISC",
"dependencies": {
- "color-name": "~1.1.4"
+ "brace-expansion": "^2.0.1"
},
"engines": {
- "node": ">=7.0.0"
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
- },
- "node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
- "dev": true
- },
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.39.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.0.tgz",
+ "integrity": "sha512-4GVSvNA0Vx1Ktwvf4sFE+exxJ3QGUorQG1/A5mRfRNZtkBT2xrA/BCO2H0eALx/PnvCS6/vmYwRdDA41EoffkQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
+ "@eslint-community/eslint-utils": "^4.7.0",
+ "@typescript-eslint/scope-manager": "8.39.0",
+ "@typescript-eslint/types": "8.39.0",
+ "@typescript-eslint/typescript-estree": "8.39.0"
},
"engines": {
- "node": ">= 8"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
}
},
- "node_modules/debug": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
- "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.39.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.0.tgz",
+ "integrity": "sha512-ldgiJ+VAhQCfIjeOgu8Kj5nSxds0ktPOSO9p4+0VDH2R2pLvQraaM5Oen2d7NxzMCm+Sn/vJT+mv2H5u6b/3fA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ms": "^2.1.3"
+ "@typescript-eslint/types": "8.39.0",
+ "eslint-visitor-keys": "^4.2.1"
},
"engines": {
- "node": ">=6.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
}
},
- "node_modules/dedent": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz",
- "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==",
+ "node_modules/@vitest/coverage-v8": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-3.2.4.tgz",
+ "integrity": "sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@ampproject/remapping": "^2.3.0",
+ "@bcoe/v8-coverage": "^1.0.2",
+ "ast-v8-to-istanbul": "^0.3.3",
+ "debug": "^4.4.1",
+ "istanbul-lib-coverage": "^3.2.2",
+ "istanbul-lib-report": "^3.0.1",
+ "istanbul-lib-source-maps": "^5.0.6",
+ "istanbul-reports": "^3.1.7",
+ "magic-string": "^0.30.17",
+ "magicast": "^0.3.5",
+ "std-env": "^3.9.0",
+ "test-exclude": "^7.0.1",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
"peerDependencies": {
- "babel-plugin-macros": "^3.1.0"
+ "@vitest/browser": "3.2.4",
+ "vitest": "3.2.4"
},
"peerDependenciesMeta": {
- "babel-plugin-macros": {
+ "@vitest/browser": {
"optional": true
}
}
},
- "node_modules/deepmerge": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
- "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "node_modules/@vitest/expect": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz",
+ "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==",
"dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/detect-newline": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
- "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
- "dev": true,
- "engines": {
- "node": ">=8"
+ "license": "MIT",
+ "dependencies": {
+ "@types/chai": "^5.2.2",
+ "@vitest/spy": "3.2.4",
+ "@vitest/utils": "3.2.4",
+ "chai": "^5.2.0",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
}
},
- "node_modules/eastasianwidth": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
- "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
- },
- "node_modules/ejs": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
- "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
+ "node_modules/@vitest/mocker": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz",
+ "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "jake": "^10.8.5"
+ "@vitest/spy": "3.2.4",
+ "estree-walker": "^3.0.3",
+ "magic-string": "^0.30.17"
},
- "bin": {
- "ejs": "bin/cli.js"
+ "funding": {
+ "url": "https://opencollective.com/vitest"
},
- "engines": {
- "node": ">=0.10.0"
+ "peerDependencies": {
+ "msw": "^2.4.9",
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "msw": {
+ "optional": true
+ },
+ "vite": {
+ "optional": true
+ }
}
},
- "node_modules/electron-to-chromium": {
- "version": "1.5.182",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.182.tgz",
- "integrity": "sha512-Lv65Btwv9W4J9pyODI6EWpdnhfvrve/us5h1WspW8B2Fb0366REPtY3hX7ounk1CkV/TBjWCEvCBBbYbmV0qCA==",
- "dev": true
- },
- "node_modules/emittery": {
- "version": "0.13.1",
- "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
- "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "node_modules/@vitest/pretty-format": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz",
+ "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==",
"dev": true,
- "engines": {
- "node": ">=12"
+ "license": "MIT",
+ "dependencies": {
+ "tinyrainbow": "^2.0.0"
},
"funding": {
- "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ "url": "https://opencollective.com/vitest"
}
},
- "node_modules/emoji-regex": {
- "version": "9.2.2",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
- "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
- },
- "node_modules/entities": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
- "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "node_modules/@vitest/runner": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz",
+ "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==",
"dev": true,
- "engines": {
- "node": ">=0.12"
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/utils": "3.2.4",
+ "pathe": "^2.0.3",
+ "strip-literal": "^3.0.0"
},
"funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
+ "url": "https://opencollective.com/vitest"
}
},
- "node_modules/error-ex": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
- "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "node_modules/@vitest/snapshot": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz",
+ "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-arrayish": "^0.2.1"
+ "@vitest/pretty-format": "3.2.4",
+ "magic-string": "^0.30.17",
+ "pathe": "^2.0.3"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
}
},
- "node_modules/esbuild": {
- "version": "0.25.6",
- "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.6.tgz",
- "integrity": "sha512-GVuzuUwtdsghE3ocJ9Bs8PNoF13HNQ5TXbEi2AhvVb8xU1Iwt9Fos9FEamfoee+u/TOsn7GUWc04lz46n2bbTg==",
+ "node_modules/@vitest/spy": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz",
+ "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==",
"dev": true,
- "hasInstallScript": true,
- "bin": {
- "esbuild": "bin/esbuild"
- },
- "engines": {
- "node": ">=18"
+ "license": "MIT",
+ "dependencies": {
+ "tinyspy": "^4.0.3"
},
- "optionalDependencies": {
- "@esbuild/aix-ppc64": "0.25.6",
- "@esbuild/android-arm": "0.25.6",
- "@esbuild/android-arm64": "0.25.6",
- "@esbuild/android-x64": "0.25.6",
- "@esbuild/darwin-arm64": "0.25.6",
- "@esbuild/darwin-x64": "0.25.6",
- "@esbuild/freebsd-arm64": "0.25.6",
- "@esbuild/freebsd-x64": "0.25.6",
- "@esbuild/linux-arm": "0.25.6",
- "@esbuild/linux-arm64": "0.25.6",
- "@esbuild/linux-ia32": "0.25.6",
- "@esbuild/linux-loong64": "0.25.6",
- "@esbuild/linux-mips64el": "0.25.6",
- "@esbuild/linux-ppc64": "0.25.6",
- "@esbuild/linux-riscv64": "0.25.6",
- "@esbuild/linux-s390x": "0.25.6",
- "@esbuild/linux-x64": "0.25.6",
- "@esbuild/netbsd-arm64": "0.25.6",
- "@esbuild/netbsd-x64": "0.25.6",
- "@esbuild/openbsd-arm64": "0.25.6",
- "@esbuild/openbsd-x64": "0.25.6",
- "@esbuild/openharmony-arm64": "0.25.6",
- "@esbuild/sunos-x64": "0.25.6",
- "@esbuild/win32-arm64": "0.25.6",
- "@esbuild/win32-ia32": "0.25.6",
- "@esbuild/win32-x64": "0.25.6"
- }
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "engines": {
- "node": ">=6"
+ "funding": {
+ "url": "https://opencollective.com/vitest"
}
},
- "node_modules/escape-string-regexp": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
- "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "node_modules/@vitest/utils": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz",
+ "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==",
"dev": true,
- "engines": {
- "node": ">=8"
+ "license": "MIT",
+ "dependencies": {
+ "@vitest/pretty-format": "3.2.4",
+ "loupe": "^3.1.4",
+ "tinyrainbow": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
}
},
- "node_modules/esprima": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
- "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "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": {
- "esparse": "bin/esparse.js",
- "esvalidate": "bin/esvalidate.js"
+ "acorn": "bin/acorn"
},
"engines": {
- "node": ">=4"
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
- "node_modules/execa": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
- "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cross-spawn": "^7.0.3",
- "get-stream": "^6.0.0",
- "human-signals": "^2.1.0",
- "is-stream": "^2.0.0",
- "merge-stream": "^2.0.0",
- "npm-run-path": "^4.0.1",
- "onetime": "^5.1.2",
- "signal-exit": "^3.0.3",
- "strip-final-newline": "^2.0.0"
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
},
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
"engines": {
- "node": ">=10"
+ "node": ">=12"
},
"funding": {
- "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
- "node_modules/execa/node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "dev": true
+ "node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
},
- "node_modules/exit-x": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz",
- "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==",
+ "node_modules/assertion-error": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">= 0.8.0"
+ "node": ">=12"
}
},
- "node_modules/expect": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.4.tgz",
- "integrity": "sha512-dDLGjnP2cKbEppxVICxI/Uf4YemmGMPNy0QytCbfafbpYk9AFQsxb8Uyrxii0RPK7FWgLGlSem+07WirwS3cFQ==",
+ "node_modules/ast-v8-to-istanbul": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.4.tgz",
+ "integrity": "sha512-cxrAnZNLBnQwBPByK4CeDaw5sWZtMilJE/Q3iDA0aamgaIVNDF9T6K2/8DfYDZEejZ2jNnDrG9m8MY72HFd0KA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/expect-utils": "30.0.4",
- "@jest/get-type": "30.0.1",
- "jest-matcher-utils": "30.0.4",
- "jest-message-util": "30.0.2",
- "jest-mock": "30.0.2",
- "jest-util": "30.0.2"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "@jridgewell/trace-mapping": "^0.3.29",
+ "estree-walker": "^3.0.3",
+ "js-tokens": "^9.0.1"
}
},
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
- "node_modules/fb-watchman": {
+ "node_modules/brace-expansion": {
"version": "2.0.2",
- "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
- "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"dependencies": {
- "bser": "2.1.1"
+ "balanced-match": "^1.0.0"
}
},
- "node_modules/filelist": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
- "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
+ "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,
"dependencies": {
- "minimatch": "^5.0.1"
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/filelist/node_modules/minimatch": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
- "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "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,
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
+ "license": "MIT",
"engines": {
- "node": ">=10"
+ "node": ">=8"
}
},
- "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==",
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true,
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
"engines": {
- "node": ">=8"
+ "node": ">=6"
}
},
- "node_modules/find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
- "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "node_modules/chai": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.1.tgz",
+ "integrity": "sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
+ "assertion-error": "^2.0.1",
+ "check-error": "^2.1.1",
+ "deep-eql": "^5.0.1",
+ "loupe": "^3.1.0",
+ "pathval": "^2.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=18"
}
},
- "node_modules/foreground-child": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
- "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
"dependencies": {
- "cross-spawn": "^7.0.6",
- "signal-exit": "^4.0.1"
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
},
"engines": {
- "node": ">=14"
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
- },
- "node_modules/fsevents": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
- "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "node_modules/chalk/node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
"engines": {
- "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/gensync": {
- "version": "1.0.0-beta.2",
- "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
- "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "node_modules/check-error": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz",
+ "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
+ "node": ">= 16"
}
},
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "node_modules/cliui": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz",
+ "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==",
+ "dependencies": {
+ "string-width": "^7.2.0",
+ "strip-ansi": "^7.1.0",
+ "wrap-ansi": "^9.0.0"
+ },
"engines": {
- "node": "6.* || 8.* || >= 10.*"
+ "node": ">=20"
}
},
- "node_modules/get-east-asian-width": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz",
- "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/get-package-type": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
- "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
- "dev": true,
- "engines": {
- "node": ">=8.0.0"
- }
+ "node_modules/cliui/node_modules/emoji-regex": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
+ "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="
},
- "node_modules/get-stream": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
- "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
- "dev": true,
+ "node_modules/cliui/node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
"engines": {
- "node": ">=10"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/get-tsconfig": {
- "version": "4.10.1",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz",
- "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==",
- "dev": true,
- "dependencies": {
- "resolve-pkg-maps": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
- }
- },
- "node_modules/glob": {
- "version": "11.0.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz",
- "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==",
+ "node_modules/cliui/node_modules/wrap-ansi": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
+ "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
"dependencies": {
- "foreground-child": "^3.3.1",
- "jackspeak": "^4.1.1",
- "minimatch": "^10.0.3",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^2.0.0"
- },
- "bin": {
- "glob": "dist/esm/bin.mjs"
+ "ansi-styles": "^6.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
},
"engines": {
- "node": "20 || >=22"
+ "node": ">=18"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/graceful-fs": {
- "version": "4.2.11",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
- "dev": true
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/html-escaper": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
- "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
- "dev": true
- },
- "node_modules/human-signals": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
- "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
- "dev": true,
- "engines": {
- "node": ">=10.17.0"
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
- "node_modules/import-local": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
- "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
- "dev": true,
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
- "pkg-dir": "^4.2.0",
- "resolve-cwd": "^3.0.0"
- },
- "bin": {
- "import-local-fixture": "fixtures/cli.js"
- },
- "engines": {
- "node": ">=8"
+ "color-name": "~1.1.4"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "dev": true,
"engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
- "dev": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
+ "node": ">=7.0.0"
}
},
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
- "node_modules/is-arrayish": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
- "node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-generator-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
- "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "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,
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-stream": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
- "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
- "dev": true,
- "engines": {
- "node": ">=8"
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
},
- "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=="
- },
- "node_modules/istanbul-lib-coverage": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
- "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
- "dev": true,
"engines": {
- "node": ">=8"
+ "node": ">= 8"
}
},
- "node_modules/istanbul-lib-instrument": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
- "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
+ "node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"dependencies": {
- "@babel/core": "^7.23.9",
- "@babel/parser": "^7.23.9",
- "@istanbuljs/schema": "^0.1.3",
- "istanbul-lib-coverage": "^3.2.0",
- "semver": "^7.5.4"
+ "ms": "^2.1.3"
},
"engines": {
- "node": ">=10"
- }
- },
- "node_modules/istanbul-lib-instrument/node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
+ "node": ">=6.0"
},
- "engines": {
- "node": ">=10"
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
}
},
- "node_modules/istanbul-lib-report": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
- "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "node_modules/deep-eql": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
+ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
"dev": true,
- "dependencies": {
- "istanbul-lib-coverage": "^3.0.0",
- "make-dir": "^4.0.0",
- "supports-color": "^7.1.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=10"
+ "node": ">=6"
}
},
- "node_modules/istanbul-lib-source-maps": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz",
- "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==",
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true,
- "dependencies": {
- "@jridgewell/trace-mapping": "^0.3.23",
- "debug": "^4.1.1",
- "istanbul-lib-coverage": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- }
+ "license": "MIT"
},
- "node_modules/istanbul-reports": {
- "version": "3.1.7",
- "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
- "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
- "dev": true,
- "dependencies": {
- "html-escaper": "^2.0.0",
- "istanbul-lib-report": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
},
- "node_modules/jackspeak": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz",
- "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==",
- "dependencies": {
- "@isaacs/cliui": "^8.0.2"
- },
- "engines": {
- "node": "20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
},
- "node_modules/jake": {
- "version": "10.9.2",
- "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz",
- "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==",
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"dev": true,
- "dependencies": {
- "async": "^3.2.3",
- "chalk": "^4.0.2",
- "filelist": "^1.0.4",
- "minimatch": "^3.1.2"
- },
- "bin": {
- "jake": "bin/cli.js"
- },
"engines": {
- "node": ">=10"
- }
- },
- "node_modules/jake/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "dev": true,
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
}
},
- "node_modules/jake/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "node_modules/es-module-lexer": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
+ "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
"dev": true,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
+ "license": "MIT"
},
- "node_modules/jest": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/jest/-/jest-30.0.4.tgz",
- "integrity": "sha512-9QE0RS4WwTj/TtTC4h/eFVmFAhGNVerSB9XpJh8sqaXlP73ILcPcZ7JWjjEtJJe2m8QyBLKKfPQuK+3F+Xij/g==",
+ "node_modules/esbuild": {
+ "version": "0.25.6",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.6.tgz",
+ "integrity": "sha512-GVuzuUwtdsghE3ocJ9Bs8PNoF13HNQ5TXbEi2AhvVb8xU1Iwt9Fos9FEamfoee+u/TOsn7GUWc04lz46n2bbTg==",
"dev": true,
- "dependencies": {
- "@jest/core": "30.0.4",
- "@jest/types": "30.0.1",
- "import-local": "^3.2.0",
- "jest-cli": "30.0.4"
- },
+ "hasInstallScript": true,
"bin": {
- "jest": "bin/jest.js"
+ "esbuild": "bin/esbuild"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
- },
- "peerDependenciesMeta": {
- "node-notifier": {
- "optional": true
- }
- }
- },
- "node_modules/jest-changed-files": {
- "version": "30.0.2",
- "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.0.2.tgz",
- "integrity": "sha512-Ius/iRST9FKfJI+I+kpiDh8JuUlAISnRszF9ixZDIqJF17FckH5sOzKC8a0wd0+D+8em5ADRHA5V5MnfeDk2WA==",
- "dev": true,
- "dependencies": {
- "execa": "^5.1.1",
- "jest-util": "30.0.2",
- "p-limit": "^3.1.0"
+ "node": ">=18"
},
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.25.6",
+ "@esbuild/android-arm": "0.25.6",
+ "@esbuild/android-arm64": "0.25.6",
+ "@esbuild/android-x64": "0.25.6",
+ "@esbuild/darwin-arm64": "0.25.6",
+ "@esbuild/darwin-x64": "0.25.6",
+ "@esbuild/freebsd-arm64": "0.25.6",
+ "@esbuild/freebsd-x64": "0.25.6",
+ "@esbuild/linux-arm": "0.25.6",
+ "@esbuild/linux-arm64": "0.25.6",
+ "@esbuild/linux-ia32": "0.25.6",
+ "@esbuild/linux-loong64": "0.25.6",
+ "@esbuild/linux-mips64el": "0.25.6",
+ "@esbuild/linux-ppc64": "0.25.6",
+ "@esbuild/linux-riscv64": "0.25.6",
+ "@esbuild/linux-s390x": "0.25.6",
+ "@esbuild/linux-x64": "0.25.6",
+ "@esbuild/netbsd-arm64": "0.25.6",
+ "@esbuild/netbsd-x64": "0.25.6",
+ "@esbuild/openbsd-arm64": "0.25.6",
+ "@esbuild/openbsd-x64": "0.25.6",
+ "@esbuild/openharmony-arm64": "0.25.6",
+ "@esbuild/sunos-x64": "0.25.6",
+ "@esbuild/win32-arm64": "0.25.6",
+ "@esbuild/win32-ia32": "0.25.6",
+ "@esbuild/win32-x64": "0.25.6"
}
},
- "node_modules/jest-circus": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.0.4.tgz",
- "integrity": "sha512-o6UNVfbXbmzjYgmVPtSQrr5xFZCtkDZGdTlptYvGFSN80RuOOlTe73djvMrs+QAuSERZWcHBNIOMH+OEqvjWuw==",
- "dev": true,
- "dependencies": {
- "@jest/environment": "30.0.4",
- "@jest/expect": "30.0.4",
- "@jest/test-result": "30.0.4",
- "@jest/types": "30.0.1",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "co": "^4.6.0",
- "dedent": "^1.6.0",
- "is-generator-fn": "^2.1.0",
- "jest-each": "30.0.2",
- "jest-matcher-utils": "30.0.4",
- "jest-message-util": "30.0.2",
- "jest-runtime": "30.0.4",
- "jest-snapshot": "30.0.4",
- "jest-util": "30.0.2",
- "p-limit": "^3.1.0",
- "pretty-format": "30.0.2",
- "pure-rand": "^7.0.0",
- "slash": "^3.0.0",
- "stack-utils": "^2.0.6"
- },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=6"
}
},
- "node_modules/jest-cli": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.0.4.tgz",
- "integrity": "sha512-3dOrP3zqCWBkjoVG1zjYJpD9143N9GUCbwaF2pFF5brnIgRLHmKcCIw+83BvF1LxggfMWBA0gxkn6RuQVuRhIQ==",
+ "node_modules/eslint": {
+ "version": "9.32.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz",
+ "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/core": "30.0.4",
- "@jest/test-result": "30.0.4",
- "@jest/types": "30.0.1",
- "chalk": "^4.1.2",
- "exit-x": "^0.2.2",
- "import-local": "^3.2.0",
- "jest-config": "30.0.4",
- "jest-util": "30.0.2",
- "jest-validate": "30.0.2",
- "yargs": "^17.7.2"
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.0",
+ "@eslint/config-helpers": "^0.3.0",
+ "@eslint/core": "^0.15.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.32.0",
+ "@eslint/plugin-kit": "^0.3.4",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "@types/json-schema": "^7.0.15",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
},
"bin": {
- "jest": "bin/jest.js"
+ "eslint": "bin/eslint.js"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
},
"peerDependencies": {
- "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ "jiti": "*"
},
"peerDependenciesMeta": {
- "node-notifier": {
+ "jiti": {
"optional": true
}
}
},
- "node_modules/jest-cli/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/jest-cli/node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "color-convert": "^2.0.1"
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
},
"engines": {
- "node": ">=8"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/jest-cli/node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "dev": true,
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/jest-cli/node_modules/emoji-regex": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
- "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
- "dev": true
- },
- "node_modules/jest-cli/node_modules/string-width": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
- "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
- "dependencies": {
- "emoji-regex": "^8.0.0",
- "is-fullwidth-code-point": "^3.0.0",
- "strip-ansi": "^6.0.1"
- },
+ "license": "Apache-2.0",
"engines": {
- "node": ">=8"
- }
- },
- "node_modules/jest-cli/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/jest-cli/node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/jest-cli/node_modules/yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "node_modules/eslint/node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "engines": {
- "node": ">=12"
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
}
},
- "node_modules/jest-cli/node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "node_modules/eslint/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=12"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/jest-config": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.0.4.tgz",
- "integrity": "sha512-3dzbO6sh34thAGEjJIW0fgT0GA0EVlkski6ZzMcbW6dzhenylXAE/Mj2MI4HonroWbkKc6wU6bLVQ8dvBSZ9lA==",
- "dev": true,
- "dependencies": {
- "@babel/core": "^7.27.4",
- "@jest/get-type": "30.0.1",
- "@jest/pattern": "30.0.1",
- "@jest/test-sequencer": "30.0.4",
- "@jest/types": "30.0.1",
- "babel-jest": "30.0.4",
- "chalk": "^4.1.2",
- "ci-info": "^4.2.0",
- "deepmerge": "^4.3.1",
- "glob": "^10.3.10",
- "graceful-fs": "^4.2.11",
- "jest-circus": "30.0.4",
- "jest-docblock": "30.0.1",
- "jest-environment-node": "30.0.4",
- "jest-regex-util": "30.0.1",
- "jest-resolve": "30.0.2",
- "jest-runner": "30.0.4",
- "jest-util": "30.0.2",
- "jest-validate": "30.0.2",
- "micromatch": "^4.0.8",
- "parse-json": "^5.2.0",
- "pretty-format": "30.0.2",
- "slash": "^3.0.0",
- "strip-json-comments": "^3.1.1"
+ "node_modules/eslint/node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "peerDependencies": {
- "@types/node": "*",
- "esbuild-register": ">=3.4.0",
- "ts-node": ">=9.0.0"
+ "node": ">=10"
},
- "peerDependenciesMeta": {
- "@types/node": {
- "optional": true
- },
- "esbuild-register": {
- "optional": true
- },
- "ts-node": {
- "optional": true
- }
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/jest-config/node_modules/glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "node_modules/eslint/node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "foreground-child": "^3.1.0",
- "jackspeak": "^3.1.2",
- "minimatch": "^9.0.4",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^1.11.1"
+ "p-locate": "^5.0.0"
},
- "bin": {
- "glob": "dist/esm/bin.mjs"
+ "engines": {
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/jest-config/node_modules/jackspeak": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
- "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "node_modules/eslint/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
+ "license": "ISC",
"dependencies": {
- "@isaacs/cliui": "^8.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "brace-expansion": "^1.1.7"
},
- "optionalDependencies": {
- "@pkgjs/parseargs": "^0.11.0"
+ "engines": {
+ "node": "*"
}
},
- "node_modules/jest-config/node_modules/lru-cache": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "dev": true
- },
- "node_modules/jest-config/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "node_modules/eslint/node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "brace-expansion": "^2.0.1"
+ "p-limit": "^3.0.2"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/jest-config/node_modules/path-scurry": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
- "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "lru-cache": "^10.2.0",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
},
"engines": {
- "node": ">=16 || 14 >=14.18"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/jest-ctrf-json-reporter": {
- "version": "0.0.9",
- "resolved": "https://registry.npmjs.org/jest-ctrf-json-reporter/-/jest-ctrf-json-reporter-0.0.9.tgz",
- "integrity": "sha512-mxuUPZ/npUEoPyjE/vHQhdNVhuxV3NzdIPIWjoreW4rMisaDKlD7x4oERU4HEC9mlI7dQkwcOHo9BJzGIgieKw==",
- "dev": true
- },
- "node_modules/jest-diff": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.4.tgz",
- "integrity": "sha512-TSjceIf6797jyd+R64NXqicttROD+Qf98fex7CowmlSn7f8+En0da1Dglwr1AXxDtVizoxXYZBlUQwNhoOXkNw==",
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "@jest/diff-sequences": "30.0.1",
- "@jest/get-type": "30.0.1",
- "chalk": "^4.1.2",
- "pretty-format": "30.0.2"
+ "estraverse": "^5.1.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=0.10"
}
},
- "node_modules/jest-docblock": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.0.1.tgz",
- "integrity": "sha512-/vF78qn3DYphAaIc3jy4gA7XSAz167n9Bm/wn/1XhTLW7tTBIzXtCJpb/vcmc73NIIeeohCbdL94JasyXUZsGA==",
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "detect-newline": "^3.1.0"
+ "estraverse": "^5.2.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=4.0"
}
},
- "node_modules/jest-each": {
- "version": "30.0.2",
- "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.0.2.tgz",
- "integrity": "sha512-ZFRsTpe5FUWFQ9cWTMguCaiA6kkW5whccPy9JjD1ezxh+mJeqmz8naL8Fl/oSbNJv3rgB0x87WBIkA5CObIUZQ==",
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
- "dependencies": {
- "@jest/get-type": "30.0.1",
- "@jest/types": "30.0.1",
- "chalk": "^4.1.2",
- "jest-util": "30.0.2",
- "pretty-format": "30.0.2"
- },
+ "license": "BSD-2-Clause",
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=4.0"
}
},
- "node_modules/jest-environment-node": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.0.4.tgz",
- "integrity": "sha512-p+rLEzC2eThXqiNh9GHHTC0OW5Ca4ZfcURp7scPjYBcmgpR9HG6750716GuUipYf2AcThU3k20B31USuiaaIEg==",
+ "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": {
- "@jest/environment": "30.0.4",
- "@jest/fake-timers": "30.0.4",
- "@jest/types": "30.0.1",
- "@types/node": "*",
- "jest-mock": "30.0.2",
- "jest-util": "30.0.2",
- "jest-validate": "30.0.2"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "@types/estree": "^1.0.0"
}
},
- "node_modules/jest-haste-map": {
- "version": "30.0.2",
- "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.2.tgz",
- "integrity": "sha512-telJBKpNLeCb4MaX+I5k496556Y2FiKR/QLZc0+MGBYl4k3OO0472drlV2LUe7c1Glng5HuAu+5GLYp//GpdOQ==",
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true,
- "dependencies": {
- "@jest/types": "30.0.1",
- "@types/node": "*",
- "anymatch": "^3.1.3",
- "fb-watchman": "^2.0.2",
- "graceful-fs": "^4.2.11",
- "jest-regex-util": "30.0.1",
- "jest-util": "30.0.2",
- "jest-worker": "30.0.2",
- "micromatch": "^4.0.8",
- "walker": "^1.0.8"
- },
+ "license": "BSD-2-Clause",
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
- },
- "optionalDependencies": {
- "fsevents": "^2.3.3"
+ "node": ">=0.10.0"
}
},
- "node_modules/jest-leak-detector": {
- "version": "30.0.2",
- "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.0.2.tgz",
- "integrity": "sha512-U66sRrAYdALq+2qtKffBLDWsQ/XoNNs2Lcr83sc9lvE/hEpNafJlq2lXCPUBMNqamMECNxSIekLfe69qg4KMIQ==",
+ "node_modules/expect-type": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz",
+ "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==",
"dev": true,
- "dependencies": {
- "@jest/get-type": "30.0.1",
- "pretty-format": "30.0.2"
- },
+ "license": "Apache-2.0",
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=12.0.0"
}
},
- "node_modules/jest-matcher-utils": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.4.tgz",
- "integrity": "sha512-ubCewJ54YzeAZ2JeHHGVoU+eDIpQFsfPQs0xURPWoNiO42LGJ+QGgfSf+hFIRplkZDkhH5MOvuxHKXRTUU3dUQ==",
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/get-type": "30.0.1",
- "chalk": "^4.1.2",
- "jest-diff": "30.0.4",
- "pretty-format": "30.0.2"
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=8.6.0"
}
},
- "node_modules/jest-message-util": {
- "version": "30.0.2",
- "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.2.tgz",
- "integrity": "sha512-vXywcxmr0SsKXF/bAD7t7nMamRvPuJkras00gqYeB1V0WllxZrbZ0paRr3XqpFU2sYYjD0qAaG2fRyn/CGZ0aw==",
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
+ "license": "ISC",
"dependencies": {
- "@babel/code-frame": "^7.27.1",
- "@jest/types": "30.0.1",
- "@types/stack-utils": "^2.0.3",
- "chalk": "^4.1.2",
- "graceful-fs": "^4.2.11",
- "micromatch": "^4.0.8",
- "pretty-format": "30.0.2",
- "slash": "^3.0.0",
- "stack-utils": "^2.0.6"
+ "is-glob": "^4.0.1"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">= 6"
}
},
- "node_modules/jest-mock": {
- "version": "30.0.2",
- "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.2.tgz",
- "integrity": "sha512-PnZOHmqup/9cT/y+pXIVbbi8ID6U1XHRmbvR7MvUy4SLqhCbwpkmXhLbsWbGewHrV5x/1bF7YDjs+x24/QSvFA==",
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fastq": {
+ "version": "1.19.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
+ "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
"dev": true,
+ "license": "ISC",
"dependencies": {
- "@jest/types": "30.0.1",
- "@types/node": "*",
- "jest-util": "30.0.2"
- },
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "reusify": "^1.0.4"
}
},
- "node_modules/jest-pnp-resolver": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
- "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
"dev": true,
- "engines": {
- "node": ">=6"
- },
- "peerDependencies": {
- "jest-resolve": "*"
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
},
- "peerDependenciesMeta": {
- "jest-resolve": {
- "optional": true
- }
+ "engines": {
+ "node": ">=16.0.0"
}
},
- "node_modules/jest-regex-util": {
- "version": "30.0.1",
- "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz",
- "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==",
+ "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,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=8"
}
},
- "node_modules/jest-resolve": {
- "version": "30.0.2",
- "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.0.2.tgz",
- "integrity": "sha512-q/XT0XQvRemykZsvRopbG6FQUT6/ra+XV6rPijyjT6D0msOyCvR2A5PlWZLd+fH0U8XWKZfDiAgrUNDNX2BkCw==",
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "chalk": "^4.1.2",
- "graceful-fs": "^4.2.11",
- "jest-haste-map": "30.0.2",
- "jest-pnp-resolver": "^1.2.3",
- "jest-util": "30.0.2",
- "jest-validate": "30.0.2",
- "slash": "^3.0.0",
- "unrs-resolver": "^1.7.11"
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=16"
}
},
- "node_modules/jest-resolve-dependencies": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.0.4.tgz",
- "integrity": "sha512-EQBYow19B/hKr4gUTn+l8Z+YLlP2X0IoPyp0UydOtrcPbIOYzJ8LKdFd+yrbwztPQvmlBFUwGPPEzHH1bAvFAw==",
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
"dev": true,
+ "license": "ISC"
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
+ "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
"dependencies": {
- "jest-regex-util": "30.0.1",
- "jest-snapshot": "30.0.4"
+ "cross-spawn": "^7.0.6",
+ "signal-exit": "^4.0.1"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/jest-runner": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.0.4.tgz",
- "integrity": "sha512-mxY0vTAEsowJwvFJo5pVivbCpuu6dgdXRmt3v3MXjBxFly7/lTk3Td0PaMyGOeNQUFmSuGEsGYqhbn7PA9OekQ==",
+ "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,
- "dependencies": {
- "@jest/console": "30.0.4",
- "@jest/environment": "30.0.4",
- "@jest/test-result": "30.0.4",
- "@jest/transform": "30.0.4",
- "@jest/types": "30.0.1",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "emittery": "^0.13.1",
- "exit-x": "^0.2.2",
- "graceful-fs": "^4.2.11",
- "jest-docblock": "30.0.1",
- "jest-environment-node": "30.0.4",
- "jest-haste-map": "30.0.2",
- "jest-leak-detector": "30.0.2",
- "jest-message-util": "30.0.2",
- "jest-resolve": "30.0.2",
- "jest-runtime": "30.0.4",
- "jest-util": "30.0.2",
- "jest-watcher": "30.0.4",
- "jest-worker": "30.0.2",
- "p-limit": "^3.1.0",
- "source-map-support": "0.5.13"
- },
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-east-asian-width": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz",
+ "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==",
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/jest-runtime": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.0.4.tgz",
- "integrity": "sha512-tUQrZ8+IzoZYIHoPDQEB4jZoPyzBjLjq7sk0KVyd5UPRjRDOsN7o6UlvaGF8ddpGsjznl9PW+KRgWqCNO+Hn7w==",
+ "node_modules/get-tsconfig": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz",
+ "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==",
"dev": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
- "@jest/environment": "30.0.4",
- "@jest/fake-timers": "30.0.4",
- "@jest/globals": "30.0.4",
- "@jest/source-map": "30.0.1",
- "@jest/test-result": "30.0.4",
- "@jest/transform": "30.0.4",
- "@jest/types": "30.0.1",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "cjs-module-lexer": "^2.1.0",
- "collect-v8-coverage": "^1.0.2",
- "glob": "^10.3.10",
- "graceful-fs": "^4.2.11",
- "jest-haste-map": "30.0.2",
- "jest-message-util": "30.0.2",
- "jest-mock": "30.0.2",
- "jest-regex-util": "30.0.1",
- "jest-resolve": "30.0.2",
- "jest-snapshot": "30.0.4",
- "jest-util": "30.0.2",
- "slash": "^3.0.0",
- "strip-bom": "^4.0.0"
+ "resolve-pkg-maps": "^1.0.0"
},
- "engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "funding": {
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
- "node_modules/jest-runtime/node_modules/glob": {
- "version": "10.4.5",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
- "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
- "dev": true,
+ "node_modules/glob": {
+ "version": "11.0.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz",
+ "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==",
"dependencies": {
- "foreground-child": "^3.1.0",
- "jackspeak": "^3.1.2",
- "minimatch": "^9.0.4",
+ "foreground-child": "^3.3.1",
+ "jackspeak": "^4.1.1",
+ "minimatch": "^10.0.3",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
- "path-scurry": "^1.11.1"
+ "path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
+ "engines": {
+ "node": "20 || >=22"
+ },
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/jest-runtime/node_modules/jackspeak": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
- "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dev": true,
+ "license": "ISC",
"dependencies": {
- "@isaacs/cliui": "^8.0.2"
+ "is-glob": "^4.0.3"
},
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
},
- "optionalDependencies": {
- "@pkgjs/parseargs": "^0.11.0"
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/jest-runtime/node_modules/lru-cache": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "dev": true
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/jest-runtime/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "brace-expansion": "^2.0.1"
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
},
"engines": {
- "node": ">=16 || 14 >=14.17"
+ "node": ">=6"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/jest-runtime/node_modules/path-scurry": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
- "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "node_modules/import-fresh/node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true,
- "dependencies": {
- "lru-cache": "^10.2.0",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=16 || 14 >=14.18"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "node": ">=4"
}
},
- "node_modules/jest-snapshot": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.4.tgz",
- "integrity": "sha512-S/8hmSkeUib8WRUq9pWEb5zMfsOjiYWDWzFzKnjX7eDyKKgimsu9hcmsUEg8a7dPAw8s/FacxsXquq71pDgPjQ==",
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true,
- "dependencies": {
- "@babel/core": "^7.27.4",
- "@babel/generator": "^7.27.5",
- "@babel/plugin-syntax-jsx": "^7.27.1",
- "@babel/plugin-syntax-typescript": "^7.27.1",
- "@babel/types": "^7.27.3",
- "@jest/expect-utils": "30.0.4",
- "@jest/get-type": "30.0.1",
- "@jest/snapshot-utils": "30.0.4",
- "@jest/transform": "30.0.4",
- "@jest/types": "30.0.1",
- "babel-preset-current-node-syntax": "^1.1.0",
- "chalk": "^4.1.2",
- "expect": "30.0.4",
- "graceful-fs": "^4.2.11",
- "jest-diff": "30.0.4",
- "jest-matcher-utils": "30.0.4",
- "jest-message-util": "30.0.2",
- "jest-util": "30.0.2",
- "pretty-format": "30.0.2",
- "semver": "^7.7.2",
- "synckit": "^0.11.8"
- },
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=0.8.19"
}
},
- "node_modules/jest-snapshot/node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
- "bin": {
- "semver": "bin/semver.js"
- },
+ "license": "MIT",
"engines": {
- "node": ">=10"
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/jest-util": {
- "version": "30.0.2",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.2.tgz",
- "integrity": "sha512-8IyqfKS4MqprBuUpZNlFB5l+WFehc8bfCe1HSZFHzft2mOuND8Cvi9r1musli+u6F3TqanCZ/Ik4H4pXUolZIg==",
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jest/types": "30.0.1",
- "@types/node": "*",
- "chalk": "^4.1.2",
- "ci-info": "^4.2.0",
- "graceful-fs": "^4.2.11",
- "picomatch": "^4.0.2"
+ "is-extglob": "^2.1.1"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=0.10.0"
}
},
- "node_modules/jest-util/node_modules/picomatch": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
- "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "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,
"engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
+ "node": ">=0.12.0"
}
},
- "node_modules/jest-validate": {
- "version": "30.0.2",
- "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.0.2.tgz",
- "integrity": "sha512-noOvul+SFER4RIvNAwGn6nmV2fXqBq67j+hKGHKGFCmK4ks/Iy1FSrqQNBLGKlu4ZZIRL6Kg1U72N1nxuRCrGQ==",
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
"dev": true,
- "dependencies": {
- "@jest/get-type": "30.0.1",
- "@jest/types": "30.0.1",
- "camelcase": "^6.3.0",
- "chalk": "^4.1.2",
- "leven": "^3.1.0",
- "pretty-format": "30.0.2"
- },
+ "license": "BSD-3-Clause",
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=8"
}
},
- "node_modules/jest-validate/node_modules/camelcase": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
- "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
"dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
"engines": {
"node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/jest-watcher": {
- "version": "30.0.4",
- "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.0.4.tgz",
- "integrity": "sha512-YESbdHDs7aQOCSSKffG8jXqOKFqw4q4YqR+wHYpR5GWEQioGvL0BfbcjvKIvPEM0XGfsfJrka7jJz3Cc3gI4VQ==",
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz",
+ "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "@jest/test-result": "30.0.4",
- "@jest/types": "30.0.1",
- "@types/node": "*",
- "ansi-escapes": "^4.3.2",
- "chalk": "^4.1.2",
- "emittery": "^0.13.1",
- "jest-util": "30.0.2",
- "string-length": "^4.0.2"
+ "@jridgewell/trace-mapping": "^0.3.23",
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=10"
}
},
- "node_modules/jest-worker": {
- "version": "30.0.2",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.2.tgz",
- "integrity": "sha512-RN1eQmx7qSLFA+o9pfJKlqViwL5wt+OL3Vff/A+/cPsmuw7NPwfgl33AP+/agRmHzPOFgXviRycR9kYwlcRQXg==",
+ "node_modules/istanbul-reports": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
+ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "@types/node": "*",
- "@ungap/structured-clone": "^1.3.0",
- "jest-util": "30.0.2",
- "merge-stream": "^2.0.0",
- "supports-color": "^8.1.1"
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=8"
}
},
- "node_modules/jest-worker/node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dev": true,
+ "node_modules/jackspeak": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz",
+ "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==",
"dependencies": {
- "has-flag": "^4.0.0"
+ "@isaacs/cliui": "^8.0.2"
},
"engines": {
- "node": ">=10"
+ "node": "20 || >=22"
},
"funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
+ "url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/js-tokens": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
- "dev": true
+ "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/js-yaml": {
- "version": "3.14.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
- "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
"dev": true,
- "dependencies": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
+ "license": "MIT"
},
- "node_modules/jsesc": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
- "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true,
- "bin": {
- "jsesc": "bin/jsesc"
- },
- "engines": {
- "node": ">=6"
- }
+ "license": "MIT"
},
- "node_modules/json-parse-even-better-errors": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
- "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
- "dev": true
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "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==",
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"dev": true,
- "bin": {
- "json5": "lib/cli.js"
- },
- "engines": {
- "node": ">=6"
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
}
},
- "node_modules/leven": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
- "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
"engines": {
- "node": ">=6"
+ "node": ">= 0.8.0"
}
},
- "node_modules/lines-and-columns": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true
- },
"node_modules/linkify-it": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
@@ -3992,23 +2855,19 @@
"uc.micro": "^2.0.0"
}
},
- "node_modules/locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
- "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true,
- "dependencies": {
- "p-locate": "^4.1.0"
- },
- "engines": {
- "node": ">=8"
- }
+ "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
+ "node_modules/loupe": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.0.tgz",
+ "integrity": "sha512-2NCfZcT5VGVNX9mSZIxLRkEAegDGBpuQZBy13desuHeVORmBDyAET4TkJr4SjqQy3A8JDofMN6LpkK8Xcm/dlw==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/lru-cache": {
"version": "11.1.0",
@@ -4024,11 +2883,34 @@
"integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
"dev": true
},
+ "node_modules/magic-string": {
+ "version": "0.30.17",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
+ "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0"
+ }
+ },
+ "node_modules/magicast": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz",
+ "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.25.4",
+ "@babel/types": "^7.25.4",
+ "source-map-js": "^1.2.0"
+ }
+ },
"node_modules/make-dir": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
"integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"semver": "^7.5.3"
},
@@ -4039,33 +2921,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/make-dir/node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "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
- },
- "node_modules/makeerror": {
- "version": "1.0.12",
- "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
- "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
- "dev": true,
- "dependencies": {
- "tmpl": "1.0.5"
- }
- },
"node_modules/markdown-it": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
@@ -4095,11 +2950,15 @@
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
"dev": true
},
- "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
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
},
"node_modules/micromatch": {
"version": "4.0.8",
@@ -4114,15 +2973,6 @@
"node": ">=8.6"
}
},
- "node_modules/mimic-fn": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
- "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/minimatch": {
"version": "10.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz",
@@ -4151,19 +3001,23 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
- "node_modules/napi-postinstall": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.0.tgz",
- "integrity": "sha512-M7NqKyhODKV1gRLdkwE7pDsZP2/SC2a2vHkOYh9MCpKMbWVfyVfUw5MaH83Fv6XMjxr5jryUp3IDDL9rlxsTeA==",
+ "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": {
- "napi-postinstall": "lib/cli.js"
+ "nanoid": "bin/nanoid.cjs"
},
"engines": {
- "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/napi-postinstall"
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/natural-compare": {
@@ -4172,135 +3026,55 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
- "node_modules/node-int64": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
- "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
- "dev": true
- },
- "node_modules/node-releases": {
- "version": "2.0.19",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
- "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
- "dev": true
- },
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/npm-run-path": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
- "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
- "dev": true,
- "dependencies": {
- "path-key": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "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,
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/onetime": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
- "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "mimic-fn": "^2.1.0"
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
},
"engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">= 0.8.0"
}
},
"node_modules/p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
- "dependencies": {
- "yocto-queue": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
- "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
- "dev": true,
- "dependencies": {
- "p-limit": "^2.2.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/p-locate/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==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"dependencies": {
- "p-try": "^2.0.0"
+ "yocto-queue": "^0.1.0"
},
"engines": {
- "node": ">=6"
+ "node": ">=10"
},
"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,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
},
- "node_modules/parse-json": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
- "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.0.0",
- "error-ex": "^1.3.1",
- "json-parse-even-better-errors": "^2.3.0",
- "lines-and-columns": "^1.1.6"
+ "callsites": "^3.0.0"
},
"engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">=6"
}
},
"node_modules/path-exists": {
@@ -4312,15 +3086,6 @@
"node": ">=8"
}
},
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
- "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",
@@ -4344,6 +3109,23 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "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/pathval": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz",
+ "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.16"
+ }
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -4362,51 +3144,69 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/pirates": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
- "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "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": ">= 6"
+ "node": "^10 || ^12 || >=14"
}
},
- "node_modules/pkg-dir": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
- "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true,
- "dependencies": {
- "find-up": "^4.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">= 0.8.0"
}
},
- "node_modules/pretty-format": {
- "version": "30.0.2",
- "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.2.tgz",
- "integrity": "sha512-yC5/EBSOrTtqhCKfLHqoUIAXVRZnukHPwWBJWR7h84Q3Be1DRQZLncwcfLoPA5RPQ65qfiCMqgYwdUuQ//eVpg==",
+ "node_modules/prettier": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
+ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
"dev": true,
- "dependencies": {
- "@jest/schemas": "30.0.1",
- "ansi-styles": "^5.2.0",
- "react-is": "^18.3.1"
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
},
"engines": {
- "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
}
},
- "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==",
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ "node": ">=6"
}
},
"node_modules/punycode.js": {
@@ -4418,74 +3218,124 @@
"node": ">=6"
}
},
- "node_modules/pure-rand": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz",
- "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==",
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
"dev": true,
"funding": [
{
- "type": "individual",
- "url": "https://github.com/sponsors/dubzzz"
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
},
{
- "type": "opencollective",
- "url": "https://opencollective.com/fast-check"
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
}
- ]
+ ],
+ "license": "MIT"
},
- "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
+ "node_modules/resolve-pkg-maps": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
+ "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "dev": true,
+ "optional": true,
+ "peer": true,
+ "funding": {
+ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ }
},
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
"dev": true,
+ "license": "MIT",
"engines": {
+ "iojs": ">=1.0.0",
"node": ">=0.10.0"
}
},
- "node_modules/resolve-cwd": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
- "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "node_modules/rollup": {
+ "version": "4.46.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz",
+ "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "resolve-from": "^5.0.0"
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
},
"engines": {
- "node": ">=8"
- }
- },
- "node_modules/resolve-from": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
- "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/resolve-pkg-maps": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
- "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.46.2",
+ "@rollup/rollup-android-arm64": "4.46.2",
+ "@rollup/rollup-darwin-arm64": "4.46.2",
+ "@rollup/rollup-darwin-x64": "4.46.2",
+ "@rollup/rollup-freebsd-arm64": "4.46.2",
+ "@rollup/rollup-freebsd-x64": "4.46.2",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.46.2",
+ "@rollup/rollup-linux-arm-musleabihf": "4.46.2",
+ "@rollup/rollup-linux-arm64-gnu": "4.46.2",
+ "@rollup/rollup-linux-arm64-musl": "4.46.2",
+ "@rollup/rollup-linux-loongarch64-gnu": "4.46.2",
+ "@rollup/rollup-linux-ppc64-gnu": "4.46.2",
+ "@rollup/rollup-linux-riscv64-gnu": "4.46.2",
+ "@rollup/rollup-linux-riscv64-musl": "4.46.2",
+ "@rollup/rollup-linux-s390x-gnu": "4.46.2",
+ "@rollup/rollup-linux-x64-gnu": "4.46.2",
+ "@rollup/rollup-linux-x64-musl": "4.46.2",
+ "@rollup/rollup-win32-arm64-msvc": "4.46.2",
+ "@rollup/rollup-win32-ia32-msvc": "4.46.2",
+ "@rollup/rollup-win32-x64-msvc": "4.46.2",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
"dev": true,
- "funding": {
- "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
+ "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",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
}
},
"node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"dev": true,
+ "license": "ISC",
"bin": {
"semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
}
},
"node_modules/shebang-command": {
@@ -4507,6 +3357,13 @@
"node": ">=8"
}
},
+ "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",
@@ -4518,85 +3375,29 @@
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/slash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "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/source-map-support": {
- "version": "0.5.13",
- "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
- "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
- "dev": true,
- "dependencies": {
- "buffer-from": "^1.0.0",
- "source-map": "^0.6.0"
- }
- },
- "node_modules/sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
- "dev": true
- },
- "node_modules/stack-utils": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
- "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
- "dev": true,
- "dependencies": {
- "escape-string-regexp": "^2.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/string-length": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
- "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
- "dev": true,
- "dependencies": {
- "char-regex": "^1.0.2",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/string-length/node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "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,
- "engines": {
- "node": ">=8"
- }
+ "license": "MIT"
},
- "node_modules/string-length/node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "node_modules/std-env": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz",
+ "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==",
"dev": true,
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
+ "license": "MIT"
},
"node_modules/string-width": {
"version": "5.1.2",
@@ -4686,24 +3487,6 @@
"node": ">=8"
}
},
- "node_modules/strip-bom": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
- "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-final-newline": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
- "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -4716,6 +3499,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/strip-literal": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz",
+ "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "js-tokens": "^9.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -4728,193 +3524,219 @@
"node": ">=8"
}
},
- "node_modules/synckit": {
- "version": "0.11.8",
- "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz",
- "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==",
+ "node_modules/test-exclude": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz",
+ "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==",
"dev": true,
+ "license": "ISC",
"dependencies": {
- "@pkgr/core": "^0.2.4"
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^10.4.1",
+ "minimatch": "^9.0.4"
},
"engines": {
- "node": "^14.18.0 || >=16.0.0"
+ "node": ">=18"
+ }
+ },
+ "node_modules/test-exclude/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
},
"funding": {
- "url": "https://opencollective.com/synckit"
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/test-exclude": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
- "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "node_modules/test-exclude/node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"dev": true,
+ "license": "BlueOak-1.0.0",
"dependencies": {
- "@istanbuljs/schema": "^0.1.2",
- "glob": "^7.1.4",
- "minimatch": "^3.0.4"
+ "@isaacs/cliui": "^8.0.2"
},
- "engines": {
- "node": ">=8"
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
}
},
- "node_modules/test-exclude/node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "node_modules/test-exclude/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/test-exclude/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
+ "license": "ISC",
"dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/test-exclude/node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
+ "node_modules/test-exclude/node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"dev": true,
+ "license": "BlueOak-1.0.0",
"dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
- "node": "*"
+ "node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
- "node_modules/test-exclude/node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "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,
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
+ "license": "MIT"
},
- "node_modules/tmpl": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
- "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
- "dev": true
+ "node_modules/tinyexec": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
+ "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
+ "dev": true,
+ "license": "MIT"
},
- "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==",
+ "node_modules/tinyglobby": {
+ "version": "0.2.14",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
+ "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-number": "^7.0.0"
+ "fdir": "^6.4.4",
+ "picomatch": "^4.0.2"
},
"engines": {
- "node": ">=8.0"
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
}
},
- "node_modules/ts-jest": {
- "version": "29.4.0",
- "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.0.tgz",
- "integrity": "sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==",
+ "node_modules/tinyglobby/node_modules/fdir": {
+ "version": "6.4.6",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz",
+ "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==",
"dev": true,
- "dependencies": {
- "bs-logger": "^0.2.6",
- "ejs": "^3.1.10",
- "fast-json-stable-stringify": "^2.1.0",
- "json5": "^2.2.3",
- "lodash.memoize": "^4.1.2",
- "make-error": "^1.3.6",
- "semver": "^7.7.2",
- "type-fest": "^4.41.0",
- "yargs-parser": "^21.1.1"
- },
- "bin": {
- "ts-jest": "cli.js"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0"
- },
+ "license": "MIT",
"peerDependencies": {
- "@babel/core": ">=7.0.0-beta.0 <8",
- "@jest/transform": "^29.0.0 || ^30.0.0",
- "@jest/types": "^29.0.0 || ^30.0.0",
- "babel-jest": "^29.0.0 || ^30.0.0",
- "jest": "^29.0.0 || ^30.0.0",
- "jest-util": "^29.0.0 || ^30.0.0",
- "typescript": ">=4.3 <6"
+ "picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
- "@babel/core": {
- "optional": true
- },
- "@jest/transform": {
- "optional": true
- },
- "@jest/types": {
- "optional": true
- },
- "babel-jest": {
- "optional": true
- },
- "esbuild": {
- "optional": true
- },
- "jest-util": {
+ "picomatch": {
"optional": true
}
}
},
- "node_modules/ts-jest/node_modules/semver": {
- "version": "7.7.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
- "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "node_modules/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
- "bin": {
- "semver": "bin/semver.js"
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
},
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/tinypool": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz",
+ "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=10"
+ "node": "^18.0.0 || >=20.0.0"
}
},
- "node_modules/ts-jest/node_modules/type-fest": {
- "version": "4.41.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
- "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
+ "node_modules/tinyrainbow": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz",
+ "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=16"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">=14.0.0"
}
},
- "node_modules/ts-jest/node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "node_modules/tinyspy": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.3.tgz",
+ "integrity": "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=12"
+ "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,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
}
},
- "node_modules/tslib": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
- "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "node_modules/ts-api-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
+ "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
"dev": true,
- "optional": true
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4"
+ }
},
"node_modules/tsx": {
"version": "4.20.3",
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz",
"integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==",
"dev": true,
+ "optional": true,
+ "peer": true,
"dependencies": {
"esbuild": "~0.25.0",
"get-tsconfig": "^4.7.5"
@@ -4929,34 +3751,27 @@
"fsevents": "~2.3.3"
}
},
- "node_modules/type-detect": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
- "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/type-fest": {
- "version": "0.21.3",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
- "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
"dev": true,
- "engines": {
- "node": ">=10"
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
},
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "engines": {
+ "node": ">= 0.8.0"
}
},
"node_modules/typedoc": {
- "version": "0.28.8",
- "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.8.tgz",
- "integrity": "sha512-16GfLopc8icHfdvqZDqdGBoS2AieIRP2rpf9mU+MgN+gGLyEQvAO0QgOa6NJ5QNmQi0LFrDY9in4F2fUNKgJKA==",
+ "version": "0.28.9",
+ "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.9.tgz",
+ "integrity": "sha512-aw45vwtwOl3QkUAmWCnLV9QW1xY+FSX2zzlit4MAfE99wX+Jij4ycnpbAWgBXsRrxmfs9LaYktg/eX5Bpthd3g==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@gerrit0/mini-shiki": "^3.7.0",
+ "@gerrit0/mini-shiki": "^3.9.0",
"lunr": "^2.3.9",
"markdown-it": "^14.1.0",
"minimatch": "^9.0.5",
@@ -4970,7 +3785,20 @@
"pnpm": ">= 10"
},
"peerDependencies": {
- "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x"
+ "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x"
+ }
+ },
+ "node_modules/typedoc-plugin-markdown": {
+ "version": "4.8.0",
+ "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.8.0.tgz",
+ "integrity": "sha512-BQqXnT9PETe6WEFf8bcsvvGEGQHbwTo/BFyY+RUIsSB05Y0Wn56iF+fK1PY2OKJJIhV4kp4dp7osaP9Bm5a0Zw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "typedoc": "0.28.x"
}
},
"node_modules/typedoc/node_modules/minimatch": {
@@ -5001,6 +3829,30 @@
"node": ">=14.17"
}
},
+ "node_modules/typescript-eslint": {
+ "version": "8.39.0",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.39.0.tgz",
+ "integrity": "sha512-lH8FvtdtzcHJCkMOKnN73LIn6SLTpoojgJqDAxPm1jCR14eWSGPX8ul/gggBdPMk/d5+u9V854vTYQ8T5jF/1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.39.0",
+ "@typescript-eslint/parser": "8.39.0",
+ "@typescript-eslint/typescript-estree": "8.39.0",
+ "@typescript-eslint/utils": "8.39.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
"node_modules/uc.micro": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
@@ -5013,91 +3865,226 @@
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
"dev": true
},
- "node_modules/unrs-resolver": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz",
- "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==",
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true,
- "hasInstallScript": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.0.6.tgz",
+ "integrity": "sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "napi-postinstall": "^0.3.0"
+ "esbuild": "^0.25.0",
+ "fdir": "^6.4.6",
+ "picomatch": "^4.0.3",
+ "postcss": "^8.5.6",
+ "rollup": "^4.40.0",
+ "tinyglobby": "^0.2.14"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
},
"funding": {
- "url": "https://opencollective.com/unrs-resolver"
+ "url": "https://github.com/vitejs/vite?sponsor=1"
},
"optionalDependencies": {
- "@unrs/resolver-binding-android-arm-eabi": "1.11.1",
- "@unrs/resolver-binding-android-arm64": "1.11.1",
- "@unrs/resolver-binding-darwin-arm64": "1.11.1",
- "@unrs/resolver-binding-darwin-x64": "1.11.1",
- "@unrs/resolver-binding-freebsd-x64": "1.11.1",
- "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1",
- "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1",
- "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-arm64-musl": "1.11.1",
- "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1",
- "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-x64-gnu": "1.11.1",
- "@unrs/resolver-binding-linux-x64-musl": "1.11.1",
- "@unrs/resolver-binding-wasm32-wasi": "1.11.1",
- "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1",
- "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1",
- "@unrs/resolver-binding-win32-x64-msvc": "1.11.1"
- }
- },
- "node_modules/update-browserslist-db": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
- "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^20.19.0 || >=22.12.0",
+ "jiti": ">=1.21.0",
+ "less": "^4.0.0",
+ "lightningcss": "^1.21.0",
+ "sass": "^1.70.0",
+ "sass-embedded": "^1.70.0",
+ "stylus": ">=0.54.8",
+ "sugarss": "^5.0.0",
+ "terser": "^5.16.0",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
},
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/browserslist"
+ "jiti": {
+ "optional": true
},
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
}
- ],
+ }
+ },
+ "node_modules/vite-node": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz",
+ "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "escalade": "^3.2.0",
- "picocolors": "^1.1.1"
+ "cac": "^6.7.14",
+ "debug": "^4.4.1",
+ "es-module-lexer": "^1.7.0",
+ "pathe": "^2.0.3",
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
},
"bin": {
- "update-browserslist-db": "cli.js"
+ "vite-node": "vite-node.mjs"
},
+ "engines": {
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ }
+ },
+ "node_modules/vite/node_modules/fdir": {
+ "version": "6.4.6",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz",
+ "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==",
+ "dev": true,
+ "license": "MIT",
"peerDependencies": {
- "browserslist": ">= 4.21.0"
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vite/node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/v8-to-istanbul": {
- "version": "9.3.0",
- "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
- "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
+ "node_modules/vitest": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz",
+ "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jridgewell/trace-mapping": "^0.3.12",
- "@types/istanbul-lib-coverage": "^2.0.1",
- "convert-source-map": "^2.0.0"
+ "@types/chai": "^5.2.2",
+ "@vitest/expect": "3.2.4",
+ "@vitest/mocker": "3.2.4",
+ "@vitest/pretty-format": "^3.2.4",
+ "@vitest/runner": "3.2.4",
+ "@vitest/snapshot": "3.2.4",
+ "@vitest/spy": "3.2.4",
+ "@vitest/utils": "3.2.4",
+ "chai": "^5.2.0",
+ "debug": "^4.4.1",
+ "expect-type": "^1.2.1",
+ "magic-string": "^0.30.17",
+ "pathe": "^2.0.3",
+ "picomatch": "^4.0.2",
+ "std-env": "^3.9.0",
+ "tinybench": "^2.9.0",
+ "tinyexec": "^0.3.2",
+ "tinyglobby": "^0.2.14",
+ "tinypool": "^1.1.1",
+ "tinyrainbow": "^2.0.0",
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0",
+ "vite-node": "3.2.4",
+ "why-is-node-running": "^2.3.0"
+ },
+ "bin": {
+ "vitest": "vitest.mjs"
},
"engines": {
- "node": ">=10.12.0"
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/vitest"
+ },
+ "peerDependencies": {
+ "@edge-runtime/vm": "*",
+ "@types/debug": "^4.1.12",
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+ "@vitest/browser": "3.2.4",
+ "@vitest/ui": "3.2.4",
+ "happy-dom": "*",
+ "jsdom": "*"
+ },
+ "peerDependenciesMeta": {
+ "@edge-runtime/vm": {
+ "optional": true
+ },
+ "@types/debug": {
+ "optional": true
+ },
+ "@types/node": {
+ "optional": true
+ },
+ "@vitest/browser": {
+ "optional": true
+ },
+ "@vitest/ui": {
+ "optional": true
+ },
+ "happy-dom": {
+ "optional": true
+ },
+ "jsdom": {
+ "optional": true
+ }
}
},
- "node_modules/walker": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
- "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "node_modules/vitest/node_modules/picomatch": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
- "dependencies": {
- "makeerror": "1.0.12"
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/which": {
@@ -5114,6 +4101,33 @@
"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/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
@@ -5198,25 +4212,6 @@
"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
- },
- "node_modules/write-file-atomic": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz",
- "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==",
- "dev": true,
- "dependencies": {
- "imurmurhash": "^0.1.4",
- "signal-exit": "^4.0.1"
- },
- "engines": {
- "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
- }
- },
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
@@ -5225,12 +4220,6 @@
"node": ">=10"
}
},
- "node_modules/yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
- },
"node_modules/yaml": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
diff --git a/package.json b/package.json
index f62a4f1..fa261a3 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ctrf",
- "version": "0.0.13-next.0",
+ "version": "0.0.13",
"description": "Common library for working with CTRF reports",
"type": "module",
"main": "dist/index.js",
@@ -12,24 +12,26 @@
"node": ">=20.19.0"
},
"scripts": {
- "build": "tsc",
- "test": "jest",
- "test:watch": "jest --watch",
- "test:coverage": "jest --coverage",
- "test:e2e": "jest --testPathPattern=e2e",
- "enrich-reports": "tsx scripts/enrich-reports.ts",
+ "build": "tsc -p .",
+ "build:check": "tsc -p . -noEmit",
+ "build:watch": "tsc -p . --watch",
+ "clean": "rm -rf dist && rm -rf coverage && rm -rf ctrf",
+ "test": "vitest run",
+ "test:coverage": "vitest run --coverage",
+ "lint": "eslint . --ext .ts --fix",
+ "lint:check": "eslint . --ext .ts",
+ "format": "prettier --write .",
+ "format:check": "prettier --check .",
"docs": "typedoc",
- "docs:watch": "typedoc --watch"
+ "docs:watch": "typedoc --watch",
+ "all": "npm run build:check && npm run test:coverage && npm run lint && npm run format && npm run docs && npm run build"
},
"files": [
"dist/",
"types/",
"README.md"
],
- "repository": {
- "type": "git",
- "url": "https://github.com/ctrf-io/ctrf-cli"
- },
+ "repository": "github:ctrf-io/ctrf-core-js",
"homepage": "https://ctrf.io",
"author": "Matthew Thomas",
"license": "MIT",
@@ -39,15 +41,17 @@
"yargs": "^18.0.0"
},
"devDependencies": {
- "@types/jest": "^30.0.0",
+ "@d2t/vitest-ctrf-json-reporter": "^1.2.0",
+ "@eslint/js": "^9.32.0",
"@types/node": "^20.12.7",
"@types/yargs": "^17.0.32",
- "jest": "^30.0.4",
- "jest-ctrf-json-reporter": "^0.0.9",
- "jest-environment-node": "^30.0.4",
- "ts-jest": "^29.4.0",
- "tsx": "^4.19.2",
- "typedoc": "^0.28.8",
- "typescript": "^5.8.3"
+ "@vitest/coverage-v8": "^3.2.4",
+ "eslint": "^9.32.0",
+ "prettier": "^3.5.3",
+ "typedoc": "^0.28.9",
+ "typedoc-plugin-markdown": "^4.8.0",
+ "typescript": "^5.8.3",
+ "typescript-eslint": "^8.38.0",
+ "vitest": "^3.2.4"
}
}
diff --git a/src/__tests__/read-reports.test.ts b/src/__tests__/read-reports.test.ts
deleted file mode 100644
index c4b611e..0000000
--- a/src/__tests__/read-reports.test.ts
+++ /dev/null
@@ -1,235 +0,0 @@
-import fs from 'fs';
-import path from 'path';
-import { readSingleReport, readReportsFromDirectory, readReportsFromGlobPattern } from '../methods/read-reports';
-import { Report } from '../../types/ctrf';
-
-// Mock fs module for testing
-jest.mock('fs');
-jest.mock('glob');
-
-const mockFs = fs as jest.Mocked;
-const mockGlob = require('glob') as jest.Mocked;
-
-describe('read-reports', () => {
- beforeEach(() => {
- jest.clearAllMocks();
- });
-
- describe('readSingleReport', () => {
- const validCtrfReport: Report = {
- reportFormat: 'ctrf',
- specVersion: '1.0.0',
- results: {
- tool: { name: 'jest' },
- summary: {
- tests: 1,
- passed: 1,
- failed: 0,
- skipped: 0,
- pending: 0,
- other: 0,
- start: Date.now(),
- stop: Date.now() + 1000
- },
- tests: [
- {
- name: 'test1',
- status: 'passed',
- duration: 100
- }
- ]
- }
- };
-
- it('should read and parse a valid CTRF report file', () => {
- const filePath = '/path/to/report.json';
- mockFs.existsSync.mockReturnValue(true);
- mockFs.readFileSync.mockReturnValue(JSON.stringify(validCtrfReport));
-
- const result = readSingleReport(filePath);
-
- expect(result).toEqual(validCtrfReport);
- expect(mockFs.readFileSync).toHaveBeenCalledWith(path.resolve(filePath), 'utf8');
- });
-
- it('should throw error when file does not exist', () => {
- const filePath = '/path/to/nonexistent.json';
- mockFs.existsSync.mockReturnValue(false);
-
- expect(() => readSingleReport(filePath)).toThrow('JSON file not found: /path/to/nonexistent.json');
- });
-
- it('should throw error when file is not valid JSON', () => {
- const filePath = '/path/to/invalid.json';
- mockFs.existsSync.mockReturnValue(true);
- mockFs.readFileSync.mockReturnValue('invalid json');
-
- expect(() => readSingleReport(filePath)).toThrow(/Failed to read or parse the file/);
- });
-
- it('should throw error when file is not a valid CTRF report', () => {
- const filePath = '/path/to/invalid-ctrf.json';
- mockFs.existsSync.mockReturnValue(true);
- mockFs.readFileSync.mockReturnValue(JSON.stringify({ invalid: 'data' }));
-
- expect(() => readSingleReport(filePath)).toThrow(/is not a valid CTRF report/);
- });
- });
-
- describe('readReportsFromDirectory', () => {
- it('should read valid CTRF reports from directory', () => {
- const directoryPath = '/path/to/reports';
- const validCtrfReport: Report = {
- reportFormat: 'ctrf',
- specVersion: '1.0.0',
- results: {
- tool: { name: 'jest' },
- summary: {
- tests: 1,
- passed: 1,
- failed: 0,
- skipped: 0,
- pending: 0,
- other: 0,
- start: Date.now(),
- stop: Date.now() + 1000
- },
- tests: [
- {
- name: 'test1',
- status: 'passed',
- duration: 100
- }
- ]
- }
- };
-
- mockFs.existsSync.mockReturnValue(true);
- mockFs.readdirSync.mockReturnValue(['report1.json', 'report2.json', 'not-json.txt'] as any);
- mockFs.readFileSync.mockReturnValue(JSON.stringify(validCtrfReport));
-
- const result = readReportsFromDirectory(directoryPath);
-
- expect(result).toHaveLength(2);
- expect(result[0]).toEqual(validCtrfReport);
- expect(result[1]).toEqual(validCtrfReport);
- });
-
- it('should throw error when directory does not exist', () => {
- const directoryPath = '/path/to/nonexistent';
- mockFs.existsSync.mockReturnValue(false);
-
- expect(() => readReportsFromDirectory(directoryPath)).toThrow(/does not exist/);
- });
-
- it('should throw error when no valid CTRF reports are found', () => {
- const directoryPath = '/path/to/empty';
- mockFs.existsSync.mockReturnValue(true);
- mockFs.readdirSync.mockReturnValue(['not-json.txt'] as any);
-
- expect(() => readReportsFromDirectory(directoryPath)).toThrow(/No valid CTRF reports found/);
- });
-
- it('should skip invalid files and warn about them', () => {
- const directoryPath = '/path/to/mixed';
- const validCtrfReport: Report = {
- reportFormat: 'ctrf',
- specVersion: '1.0.0',
- results: {
- tool: { name: 'jest' },
- summary: {
- tests: 1,
- passed: 1,
- failed: 0,
- skipped: 0,
- pending: 0,
- other: 0,
- start: Date.now(),
- stop: Date.now() + 1000
- },
- tests: [
- {
- name: 'test1',
- status: 'passed',
- duration: 100
- }
- ]
- }
- };
-
- mockFs.existsSync.mockReturnValue(true);
- mockFs.readdirSync.mockReturnValue(['valid.json', 'invalid.json'] as any);
- mockFs.readFileSync
- .mockReturnValueOnce(JSON.stringify(validCtrfReport))
- .mockReturnValueOnce(JSON.stringify({ invalid: 'data' }));
-
- const consoleSpy = jest.spyOn(console, 'warn').mockImplementation();
-
- const result = readReportsFromDirectory(directoryPath);
-
- expect(result).toHaveLength(1);
- expect(result[0]).toEqual(validCtrfReport);
- expect(consoleSpy).toHaveBeenCalledWith('Skipping invalid CTRF report file: invalid.json');
-
- consoleSpy.mockRestore();
- });
- });
-
- describe('readReportsFromGlobPattern', () => {
- it('should read valid CTRF reports from glob pattern', () => {
- const pattern = 'reports/*.json';
- const validCtrfReport: Report = {
- reportFormat: 'ctrf',
- specVersion: '1.0.0',
- results: {
- tool: { name: 'jest' },
- summary: {
- tests: 1,
- passed: 1,
- failed: 0,
- skipped: 0,
- pending: 0,
- other: 0,
- start: Date.now(),
- stop: Date.now() + 1000
- },
- tests: [
- {
- name: 'test1',
- status: 'passed',
- duration: 100
- }
- ]
- }
- };
-
- mockGlob.sync.mockReturnValue(['report1.json', 'report2.json']);
- mockFs.readFileSync.mockReturnValue(JSON.stringify(validCtrfReport));
-
- const result = readReportsFromGlobPattern(pattern);
-
- expect(result).toHaveLength(2);
- expect(result[0]).toEqual(validCtrfReport);
- expect(result[1]).toEqual(validCtrfReport);
- });
-
- it('should throw error when no files match the pattern', () => {
- const pattern = 'nonexistent/*.json';
- mockGlob.sync.mockReturnValue([]);
-
- expect(() => readReportsFromGlobPattern(pattern)).toThrow(/No files found matching the pattern/);
- });
-
- it('should throw error when no valid CTRF reports are found', () => {
- const pattern = 'invalid/*.json';
- mockGlob.sync.mockReturnValue(['invalid.json']);
- mockFs.readFileSync.mockReturnValue(JSON.stringify({ invalid: 'data' }));
-
- const consoleSpy = jest.spyOn(console, 'warn').mockImplementation();
-
- expect(() => readReportsFromGlobPattern(pattern)).toThrow(/No valid CTRF reports found/);
-
- consoleSpy.mockRestore();
- });
- });
-});
\ No newline at end of file
diff --git a/src/__tests__/run-insights.test.ts b/src/__tests__/run-insights.test.ts
deleted file mode 100644
index eacba73..0000000
--- a/src/__tests__/run-insights.test.ts
+++ /dev/null
@@ -1,371 +0,0 @@
-// Test the public API and utility functions
-import {
- isTestFlaky,
- formatAsPercentage,
- formatInsightsMetricAsPercentage,
- enrichReportWithInsights
-} from '../methods/run-insights';
-
-import { Report, Test, InsightsMetric } from '../../types/ctrf.js';
-import { CTRF_REPORT_FORMAT, CTRF_SPEC_VERSION } from '../constants';
-
-// Mock data helpers
-const createMockTest = (overrides: Partial = {}): Test => ({
- name: 'test-name',
- status: 'passed',
- duration: 100,
- ...overrides
-});
-
-const createMockReport = (tests: Test[] = [], overrides: Partial = {}): Report => ({
- reportFormat: CTRF_REPORT_FORMAT,
- specVersion: CTRF_SPEC_VERSION,
- results: {
- tool: { name: 'jest' },
- summary: {
- tests: tests.length,
- passed: tests.filter(t => t.status === 'passed').length,
- failed: tests.filter(t => t.status === 'failed').length,
- skipped: tests.filter(t => t.status === 'skipped').length,
- pending: tests.filter(t => t.status === 'pending').length,
- other: tests.filter(t => t.status === 'other').length,
- start: Date.now(),
- stop: Date.now() + 1000
- },
- tests
- },
- ...overrides
-});
-
-describe('run-insights utility functions', () => {
- describe('isTestFlaky', () => {
- it('should return true for explicitly flaky tests', () => {
- const test = createMockTest({ flaky: true });
- expect(isTestFlaky(test)).toBe(true);
- });
-
- it('should return true for passed tests with retries', () => {
- const test = createMockTest({
- status: 'passed',
- retries: 2
- });
- expect(isTestFlaky(test)).toBe(true);
- });
-
- it('should return false for failed tests with retries', () => {
- const test = createMockTest({
- status: 'failed',
- retries: 2
- });
- expect(isTestFlaky(test)).toBe(false);
- });
-
- it('should return false for passed tests without retries', () => {
- const test = createMockTest({
- status: 'passed',
- retries: 0
- });
- expect(isTestFlaky(test)).toBe(false);
- });
-
- it('should return false for passed tests without retries property', () => {
- const test = createMockTest({ status: 'passed' });
- expect(isTestFlaky(test)).toBe(false);
- });
- });
-
- describe('formatAsPercentage', () => {
- it('should format ratio as percentage with default 2 decimals', () => {
- expect(formatAsPercentage(0.25)).toBe('25.00%');
- expect(formatAsPercentage(0.5)).toBe('50.00%');
- expect(formatAsPercentage(0.75)).toBe('75.00%');
- expect(formatAsPercentage(1)).toBe('100.00%');
- });
-
- it('should format ratio as percentage with custom decimals', () => {
- expect(formatAsPercentage(0.25, 1)).toBe('25.0%');
- expect(formatAsPercentage(0.25, 0)).toBe('25%');
- expect(formatAsPercentage(0.25, 3)).toBe('25.000%');
- });
-
- it('should handle edge cases', () => {
- expect(formatAsPercentage(0)).toBe('0.00%');
- expect(formatAsPercentage(0.00001)).toBe('0.00%');
- expect(formatAsPercentage(0.999)).toBe('99.90%');
- });
- });
-
- describe('formatInsightsMetricAsPercentage', () => {
- it('should format all metric values as percentages', () => {
- const metric: InsightsMetric = {
- current: 0.25,
- previous: 0.2,
- change: 0.05
- };
-
- const result = formatInsightsMetricAsPercentage(metric);
-
- expect(result).toEqual({
- current: '25.00%',
- previous: '20.00%',
- change: '+5.00%'
- });
- });
-
- it('should handle negative change values', () => {
- const metric: InsightsMetric = {
- current: 0.15,
- previous: 0.2,
- change: -0.05
- };
-
- const result = formatInsightsMetricAsPercentage(metric);
-
- expect(result).toEqual({
- current: '15.00%',
- previous: '20.00%',
- change: '-5.00%'
- });
- });
-
- it('should handle zero change values', () => {
- const metric: InsightsMetric = {
- current: 0.2,
- previous: 0.2,
- change: 0
- };
-
- const result = formatInsightsMetricAsPercentage(metric);
-
- expect(result).toEqual({
- current: '20.00%',
- previous: '20.00%',
- change: '+0.00%'
- });
- });
- });
-});
-
-describe('enrichReportWithInsights - Main API', () => {
- describe('basic functionality', () => {
- it('should enrich a report with run-level insights when no previous reports', () => {
- const tests = [
- createMockTest({ name: 'test1', status: 'passed', duration: 100 }),
- createMockTest({ name: 'test2', status: 'failed', duration: 200 }),
- createMockTest({ name: 'test3', status: 'passed', retries: 1, flaky: true, duration: 150 })
- ];
- const currentReport = createMockReport(tests);
-
- const result = enrichReportWithInsights(currentReport, []);
-
- expect(result.insights).toBeDefined();
- expect(result.insights!.flakyRate.current).toBeGreaterThan(0);
- expect(result.insights!.failRate.current).toBeGreaterThan(0);
- expect(result.insights!.averageTestDuration.current).toBe(150); // (100+200+150)/3
- expect(result.insights!.reportsAnalyzed).toBe(1);
-
- // Should have no baseline comparison (previous/change should be 0)
- expect(result.insights!.flakyRate.previous).toBe(0);
- expect(result.insights!.flakyRate.change).toBe(0);
- });
-
- it('should add test-level insights to each test', () => {
- const tests = [
- createMockTest({ name: 'test1', status: 'passed', duration: 100 }),
- createMockTest({ name: 'test2', status: 'failed', duration: 200 })
- ];
- const currentReport = createMockReport(tests);
-
- const result = enrichReportWithInsights(currentReport, []);
-
- expect(result.results.tests[0].insights).toBeDefined();
- expect(result.results.tests[1].insights).toBeDefined();
-
- expect(result.results.tests[0].insights!.failRate.current).toBe(0);
- expect(result.results.tests[1].insights!.failRate.current).toBe(1);
- expect(result.results.tests[0].insights!.averageTestDuration.current).toBe(100);
- expect(result.results.tests[1].insights!.averageTestDuration.current).toBe(200);
- });
- });
-
- describe('baseline comparison functionality', () => {
- it('should compare against previous report by default', () => {
- const currentTests = [
- createMockTest({ name: 'test1', status: 'passed', duration: 100 }),
- createMockTest({ name: 'test2', status: 'passed', duration: 200 })
- ];
- const previousTests = [
- createMockTest({ name: 'test1', status: 'failed', duration: 150 }),
- createMockTest({ name: 'test2', status: 'failed', duration: 250 })
- ];
-
- const currentReport = createMockReport(currentTests, {
- results: {
- ...createMockReport(currentTests).results,
- summary: { ...createMockReport(currentTests).results.summary, start: 2000 }
- }
- });
- const previousReport = createMockReport(previousTests, {
- results: {
- ...createMockReport(previousTests).results,
- summary: { ...createMockReport(previousTests).results.summary, start: 1000 }
- }
- });
-
- const result = enrichReportWithInsights(currentReport, [previousReport]);
-
- expect(result.insights).toBeDefined();
- expect(result.insights!.failRate.current).toBe(0.5); // Overall: 2 passed + 2 failed = 50% fail rate
- expect(result.insights!.failRate.previous).toBe(1); // Previous: all failed
- expect(result.insights!.failRate.change).toBe(-0.5); // Improvement of 50%
- expect(result.insights!.reportsAnalyzed).toBe(2);
- });
-
- it('should handle baseline by index', () => {
- const currentTests = [createMockTest({ name: 'test1', status: 'passed' })];
- const previous1Tests = [createMockTest({ name: 'test1', status: 'failed' })];
- const previous2Tests = [createMockTest({ name: 'test1', status: 'passed' })];
-
- const currentReport = createMockReport(currentTests);
- const previousReport1 = createMockReport(previous1Tests);
- const previousReport2 = createMockReport(previous2Tests);
-
- // Use index 1 (second previous report)
- const result = enrichReportWithInsights(currentReport, [previousReport1, previousReport2], 1);
-
- expect(result.insights!.failRate.current).toBe(0.3333); // 1 passed + 1 failed + 1 passed = 1/3 fail rate
- expect(result.insights!.failRate.previous).toBe(0); // previous2 had no failures
- expect(result.insights!.failRate.change).toBe(0.3333);
- });
-
- it('should handle baseline by report ID', () => {
- const currentTests = [createMockTest({ name: 'test1', status: 'passed' })];
- const previousTests = [createMockTest({ name: 'test1', status: 'failed' })];
-
- const currentReport = createMockReport(currentTests);
- const previousReport = createMockReport(previousTests, {
- results: {
- ...createMockReport(previousTests).results,
- summary: { ...createMockReport(previousTests).results.summary, start: 12345 }
- }
- });
-
- const result = enrichReportWithInsights(currentReport, [previousReport], "12345");
-
- expect(result.insights!.failRate.current).toBe(0.5); // 1 passed + 1 failed = 50% fail rate
- expect(result.insights!.failRate.previous).toBe(1);
- expect(result.insights!.failRate.change).toBe(-0.5);
- });
-
- it('should handle invalid baseline gracefully', () => {
- const currentTests = [createMockTest({ name: 'test1', status: 'passed' })];
- const previousTests = [createMockTest({ name: 'test1', status: 'failed' })];
-
- const currentReport = createMockReport(currentTests);
- const previousReport = createMockReport(previousTests);
-
- // Invalid index
- const result1 = enrichReportWithInsights(currentReport, [previousReport], 999);
- expect(result1.insights!.failRate.previous).toBe(0);
- expect(result1.insights!.failRate.change).toBe(0);
-
- // Invalid ID
- const result2 = enrichReportWithInsights(currentReport, [previousReport], "invalid-id");
- expect(result2.insights!.failRate.previous).toBe(0);
- expect(result2.insights!.failRate.change).toBe(0);
- });
- });
-
- describe('added/removed tests tracking', () => {
- it('should track tests added since baseline', () => {
- const currentTests = [
- createMockTest({ name: 'test1', status: 'passed' }),
- createMockTest({ name: 'test2', status: 'passed' }), // New test
- createMockTest({ name: 'test3', status: 'passed' }) // New test
- ];
- const previousTests = [
- createMockTest({ name: 'test1', status: 'passed' })
- ];
-
- const currentReport = createMockReport(currentTests);
- const previousReport = createMockReport(previousTests);
-
- const result = enrichReportWithInsights(currentReport, [previousReport]);
-
- expect(result.insights!.extra!.testsAdded).toHaveLength(2);
- expect((result.insights!.extra!.testsAdded as any[])[0].name).toBe('test2');
- expect((result.insights!.extra!.testsAdded as any[])[1].name).toBe('test3');
- });
-
- it('should track tests removed since baseline', () => {
- const currentTests = [
- createMockTest({ name: 'test1', status: 'passed' })
- ];
- const previousTests = [
- createMockTest({ name: 'test1', status: 'passed' }),
- createMockTest({ name: 'test2', status: 'passed' }), // Removed test
- createMockTest({ name: 'test3', status: 'passed' }) // Removed test
- ];
-
- const currentReport = createMockReport(currentTests);
- const previousReport = createMockReport(previousTests);
-
- const result = enrichReportWithInsights(currentReport, [previousReport]);
-
- expect(result.insights!.extra!.testsRemoved).toHaveLength(2);
- expect((result.insights!.extra!.testsRemoved as any[])[0].name).toBe('test2');
- expect((result.insights!.extra!.testsRemoved as any[])[1].name).toBe('test3');
- });
-
- it('should handle single report no added/removed tests', () => {
- const currentTests = [createMockTest({ name: 'test1', status: 'passed' })];
-
- const currentReport = createMockReport(currentTests);
- const result = enrichReportWithInsights(currentReport, []);
-
- expect(result.insights!.extra!.testsAdded).toBeUndefined();
- expect(result.insights!.extra!.testsRemoved).toBeUndefined();
- });
- });
-
- describe('edge cases', () => {
- it('should handle empty current report', () => {
- const currentReport = createMockReport([]);
- const previousReport = createMockReport([createMockTest()]);
-
- const result = enrichReportWithInsights(currentReport, [previousReport]);
-
- expect(result.insights).toBeDefined();
- expect(result.insights!.failRate.current).toBe(0); // Previous report has 1 test, current has 0, so 0 failed overall
- expect(result.insights!.averageTestDuration.current).toBe(100); // Previous report had 1 test with 100ms duration
- });
-
- it('should handle invalid current report', () => {
- const invalidReport = { results: null } as any;
-
- const result = enrichReportWithInsights(invalidReport, []);
-
- expect(result).toBe(invalidReport); // Should return unchanged
- });
-
- it('should handle multiple previous reports', () => {
- const currentTests = [createMockTest({ name: 'test1', status: 'passed' })];
- const previous1Tests = [createMockTest({ name: 'test1', status: 'failed' })];
- const previous2Tests = [createMockTest({ name: 'test1', status: 'passed' })];
- const previous3Tests = [createMockTest({ name: 'test1', status: 'failed' })];
-
- const currentReport = createMockReport(currentTests);
- const previousReports = [
- createMockReport(previous1Tests),
- createMockReport(previous2Tests),
- createMockReport(previous3Tests)
- ];
-
- const result = enrichReportWithInsights(currentReport, previousReports);
-
- expect(result.insights!.reportsAnalyzed).toBe(4); // Current + 3 previous
- expect(result.insights!.failRate.current).toBeDefined();
- expect(result.insights!.failRate.previous).toBeDefined();
- });
- });
-});
\ No newline at end of file
diff --git a/src/cli.ts b/src/cli.ts
index 2ccf88d..3564acf 100644
--- a/src/cli.ts
+++ b/src/cli.ts
@@ -1,15 +1,15 @@
#!/usr/bin/env node
-import yargs from 'yargs/yargs';
-import { hideBin } from 'yargs/helpers';
-import { mergeReports } from './merge.js';
-import { identifyFlakyTests } from './flaky.js';
+import yargs from 'yargs/yargs'
+import { hideBin } from 'yargs/helpers'
+import { mergeReports } from './merge.js'
+import { identifyFlakyTests } from './flaky.js'
const argv = yargs(hideBin(process.argv))
.command(
'merge ',
'Merge CTRF reports into a single report',
- (yargs) => {
+ yargs => {
return yargs
.positional('directory', {
describe: 'Directory of the CTRF reports',
@@ -32,27 +32,30 @@ const argv = yargs(hideBin(process.argv))
describe: 'Keep existing reports after merging',
type: 'boolean',
default: false,
- });
+ })
},
- async (argv) => {
- await mergeReports(argv.directory as string, argv.output as string, argv['output-dir'] as string, argv['keep-reports'] as boolean);
+ async argv => {
+ await mergeReports(
+ argv.directory as string,
+ argv.output as string,
+ argv['output-dir'] as string,
+ argv['keep-reports'] as boolean
+ )
}
)
.command(
'flaky ',
'Identify flaky tests from a CTRF report file',
- (yargs) => {
- return yargs
- .positional('file', {
- describe: 'CTRF report file',
- type: 'string',
- demandOption: true,
- });
+ yargs => {
+ return yargs.positional('file', {
+ describe: 'CTRF report file',
+ type: 'string',
+ demandOption: true,
+ })
},
- async (argv) => {
- await identifyFlakyTests(argv.file as string);
+ async argv => {
+ await identifyFlakyTests(argv.file as string)
}
)
.help()
- .demandCommand(1, 'You need at least one command before moving on')
- .argv;
\ No newline at end of file
+ .demandCommand(1, 'You need at least one command before moving on').argv
diff --git a/src/constants.ts b/src/constants.ts
index e9c18a7..8970989 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -1,2 +1,2 @@
-export const CTRF_REPORT_FORMAT = 'ctrf';
-export const CTRF_SPEC_VERSION = '0.0.0';
\ No newline at end of file
+export const CTRF_REPORT_FORMAT = 'CTRF'
+export const CTRF_SPEC_VERSION = '0.0.0'
diff --git a/src/flaky.ts b/src/flaky.ts
index 108e48f..a095736 100644
--- a/src/flaky.ts
+++ b/src/flaky.ts
@@ -1,29 +1,32 @@
-import fs from 'fs';
-import path from 'path';
+import fs from 'fs'
+import path from 'path'
+import { Test } from '../types/ctrf.js'
export async function identifyFlakyTests(filePath: string) {
try {
- const resolvedFilePath = path.resolve(filePath);
+ const resolvedFilePath = path.resolve(filePath)
if (!fs.existsSync(resolvedFilePath)) {
- console.error(`The file ${resolvedFilePath} does not exist.`);
- return;
+ console.error(`The file ${resolvedFilePath} does not exist.`)
+ return
}
- const fileContent = fs.readFileSync(resolvedFilePath, 'utf8');
- const report = JSON.parse(fileContent);
+ const fileContent = fs.readFileSync(resolvedFilePath, 'utf8')
+ const report = JSON.parse(fileContent)
- const flakyTests = report.results.tests.filter((test: any) => test.flaky === true);
+ const flakyTests = report.results.tests.filter(
+ (test: Test) => test.flaky === true
+ )
if (flakyTests.length > 0) {
- console.log(`Found ${flakyTests.length} flaky test(s):`);
- flakyTests.forEach((test: any) => {
- console.log(`- Test Name: ${test.name}, Retries: ${test.retries}`);
- });
+ console.log(`Found ${flakyTests.length} flaky test(s):`)
+ flakyTests.forEach((test: Test) => {
+ console.log(`- Test Name: ${test.name}, Retries: ${test.retries}`)
+ })
} else {
- console.log(`No flaky tests found in ${resolvedFilePath}.`);
+ console.log(`No flaky tests found in ${resolvedFilePath}.`)
}
} catch (error) {
- console.error('Error identifying flaky tests:', error);
+ console.error('Error identifying flaky tests:', error)
}
}
diff --git a/src/index.ts b/src/index.ts
index 2a99cfd..abbf7ac 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,10 +1,13 @@
-export { mergeReports } from './methods/merge-reports.js';
-export { readReportsFromDirectory } from './methods/read-reports.js';
-export { readReportsFromGlobPattern } from './methods/read-reports.js';
-export {
- enrichReportWithInsights,
-} from './methods/run-insights.js';
-export { storePreviousResults } from './methods/store-previous-results.js';
+export { mergeReports } from './methods/merge-reports.js'
+export { readReportsFromDirectory } from './methods/read-reports.js'
+export { readReportsFromGlobPattern } from './methods/read-reports.js'
+export { enrichReportWithInsights } from './methods/run-insights.js'
+export {
+ sortReportsByTimestamp,
+ SortOrder,
+} from './methods/utilities/sort-reports.js'
+export { storePreviousResults } from './methods/store-previous-results.js'
+export { readReportFromFile } from './methods/read-reports.js'
export type {
Report,
@@ -15,10 +18,9 @@ export type {
Tool,
Step,
Attachment,
- RetryAttempts,
+ RetryAttempt,
Insights,
TestInsights,
InsightsMetric,
- TestState
-} from '../types/ctrf.js';
-
+ TestStatus,
+} from '../types/ctrf.js'
diff --git a/src/merge.ts b/src/merge.ts
index cad75d6..38ba3d9 100644
--- a/src/merge.ts
+++ b/src/merge.ts
@@ -1,92 +1,108 @@
-import fs from 'fs';
-import path from 'path';
+import fs from 'fs'
+import path from 'path'
-export async function mergeReports(directory: string, output: string, outputDir: string, keepReports: boolean) {
- try {
- const directoryPath = path.resolve(directory);
- const outputFileName = output;
- const resolvedOutputDir = outputDir ? path.resolve(outputDir) : directoryPath;
- const outputPath = path.join(resolvedOutputDir, outputFileName);
+export async function mergeReports(
+ directory: string,
+ output: string,
+ outputDir: string,
+ keepReports: boolean
+) {
+ try {
+ const directoryPath = path.resolve(directory)
+ const outputFileName = output
+ const resolvedOutputDir = outputDir
+ ? path.resolve(outputDir)
+ : directoryPath
+ const outputPath = path.join(resolvedOutputDir, outputFileName)
- console.log("Merging CTRF reports...");
+ console.log('Merging CTRF reports...')
- const files = fs.readdirSync(directoryPath);
+ const files = fs.readdirSync(directoryPath)
- files.forEach((file) => {
- console.log('Found file:', file);
- });
+ files.forEach(file => {
+ console.log('Found file:', file)
+ })
- const ctrfReportFiles = files.filter((file) => {
- try {
- if (path.extname(file) !== '.json') {
- console.log(`Skipping non-CTRF file: ${file}`);
- return false;
- }
- const filePath = path.join(directoryPath, file);
- const fileContent = fs.readFileSync(filePath, 'utf8');
- const jsonData = JSON.parse(fileContent);
- if (!jsonData.hasOwnProperty('results')) {
- console.log(`Skipping non-CTRF file: ${file}`);
- return false;
- }
- return true;
- } catch (error) {
- console.error(`Error reading JSON file '${file}':`, error);
- return false;
- }
- });
-
- if (ctrfReportFiles.length === 0) {
- console.log('No CTRF reports found in the specified directory.');
- return;
+ const ctrfReportFiles = files.filter(file => {
+ try {
+ if (path.extname(file) !== '.json') {
+ console.log(`Skipping non-CTRF file: ${file}`)
+ return false
}
-
- if (!fs.existsSync(resolvedOutputDir)) {
- fs.mkdirSync(resolvedOutputDir, { recursive: true });
- console.log(`Created output directory: ${resolvedOutputDir}`);
+ const filePath = path.join(directoryPath, file)
+ const fileContent = fs.readFileSync(filePath, 'utf8')
+ const jsonData = JSON.parse(fileContent)
+ if (!('results' in jsonData)) {
+ console.log(`Skipping non-CTRF file: ${file}`)
+ return false
}
+ return true
+ } catch (error) {
+ console.error(`Error reading JSON file '${file}':`, error)
+ return false
+ }
+ })
+
+ if (ctrfReportFiles.length === 0) {
+ console.log('No CTRF reports found in the specified directory.')
+ return
+ }
- const mergedReport = ctrfReportFiles
- .map((file) => {
- console.log("Merging report:", file);
- const filePath = path.join(directoryPath, file);
- const fileContent = fs.readFileSync(filePath, 'utf8');
- return JSON.parse(fileContent);
- })
- .reduce((acc, curr) => {
- if (!acc.results) {
- return curr;
- }
+ if (!fs.existsSync(resolvedOutputDir)) {
+ fs.mkdirSync(resolvedOutputDir, { recursive: true })
+ console.log(`Created output directory: ${resolvedOutputDir}`)
+ }
- acc.results.summary.tests += curr.results.summary.tests;
- acc.results.summary.passed += curr.results.summary.passed;
- acc.results.summary.failed += curr.results.summary.failed;
- acc.results.summary.skipped += curr.results.summary.skipped;
- acc.results.summary.pending += curr.results.summary.pending;
- acc.results.summary.other += curr.results.summary.other;
+ const mergedReport = ctrfReportFiles
+ .map(file => {
+ console.log('Merging report:', file)
+ const filePath = path.join(directoryPath, file)
+ const fileContent = fs.readFileSync(filePath, 'utf8')
+ return JSON.parse(fileContent)
+ })
+ .reduce(
+ (acc, curr) => {
+ if (!acc.results) {
+ return curr
+ }
- acc.results.tests.push(...curr.results.tests);
+ acc.results.summary.tests += curr.results.summary.tests
+ acc.results.summary.passed += curr.results.summary.passed
+ acc.results.summary.failed += curr.results.summary.failed
+ acc.results.summary.skipped += curr.results.summary.skipped
+ acc.results.summary.pending += curr.results.summary.pending
+ acc.results.summary.other += curr.results.summary.other
- acc.results.summary.start = Math.min(acc.results.summary.start, curr.results.summary.start);
- acc.results.summary.stop = Math.max(acc.results.summary.stop, curr.results.summary.stop);
+ acc.results.tests.push(...curr.results.tests)
- return acc;
- }, { results: null });
+ acc.results.summary.start = Math.min(
+ acc.results.summary.start,
+ curr.results.summary.start
+ )
+ acc.results.summary.stop = Math.max(
+ acc.results.summary.stop,
+ curr.results.summary.stop
+ )
- fs.writeFileSync(outputPath, JSON.stringify(mergedReport, null, 2));
+ return acc
+ },
+ { results: null }
+ )
- if (!keepReports) {
- ctrfReportFiles.forEach((file) => {
- const filePath = path.join(directoryPath, file);
- if (file !== outputFileName) {
- fs.unlinkSync(filePath);
- }
- });
- }
+ fs.writeFileSync(outputPath, JSON.stringify(mergedReport, null, 2))
- console.log('CTRF reports merged successfully.');
- console.log(`Merged report saved to: ${outputPath}`);
- } catch (error) {
- console.error('Error merging CTRF reports:', error);
+ if (!keepReports) {
+ ctrfReportFiles.forEach(file => {
+ const filePath = path.join(directoryPath, file)
+ if (file !== outputFileName) {
+ fs.unlinkSync(filePath)
+ }
+ })
}
+
+ console.log('CTRF reports merged successfully.')
+ console.log(`Merged report saved to: ${outputPath}`)
+ } catch (error) {
+ console.error('Error merging CTRF reports:', error)
+ }
}
diff --git a/src/methods/merge-reports.ts b/src/methods/merge-reports.ts
index 3f19f55..c306fb8 100644
--- a/src/methods/merge-reports.ts
+++ b/src/methods/merge-reports.ts
@@ -1,5 +1,5 @@
-import { Report, Summary } from "../../types/ctrf.js";
-import { CTRF_REPORT_FORMAT, CTRF_SPEC_VERSION } from "../constants.js";
+import { Report, Summary } from '../../types/ctrf.js'
+import { CTRF_REPORT_FORMAT, CTRF_SPEC_VERSION } from '../constants.js'
/**
* Merges multiple CTRF reports into a single report.
@@ -9,7 +9,7 @@ import { CTRF_REPORT_FORMAT, CTRF_SPEC_VERSION } from "../constants.js";
*/
export function mergeReports(reports: Report[]): Report {
if (!reports || reports.length === 0) {
- throw new Error('No reports provided for merging.');
+ throw new Error('No reports provided for merging.')
}
const mergedReport: Report = {
@@ -20,50 +20,50 @@ export function mergeReports(reports: Report[]): Report {
summary: initializeEmptySummary(),
tests: [],
},
- };
+ }
- reports.forEach((report) => {
- const { summary, tests, environment, extra } = report.results;
+ reports.forEach(report => {
+ const { summary, tests, environment, extra } = report.results
- mergedReport.results.summary.tests += summary.tests;
- mergedReport.results.summary.passed += summary.passed;
- mergedReport.results.summary.failed += summary.failed;
- mergedReport.results.summary.skipped += summary.skipped;
- mergedReport.results.summary.pending += summary.pending;
- mergedReport.results.summary.other += summary.other;
+ mergedReport.results.summary.tests += summary.tests
+ mergedReport.results.summary.passed += summary.passed
+ mergedReport.results.summary.failed += summary.failed
+ mergedReport.results.summary.skipped += summary.skipped
+ mergedReport.results.summary.pending += summary.pending
+ mergedReport.results.summary.other += summary.other
if (summary.suites !== undefined) {
mergedReport.results.summary.suites =
- (mergedReport.results.summary.suites || 0) + summary.suites;
+ (mergedReport.results.summary.suites || 0) + summary.suites
}
mergedReport.results.summary.start = Math.min(
mergedReport.results.summary.start,
summary.start
- );
+ )
mergedReport.results.summary.stop = Math.max(
mergedReport.results.summary.stop,
summary.stop
- );
+ )
- mergedReport.results.tests.push(...tests);
+ mergedReport.results.tests.push(...tests)
if (environment) {
mergedReport.results.environment = {
...mergedReport.results.environment,
...environment,
- };
+ }
}
if (extra) {
mergedReport.results.extra = {
...mergedReport.results.extra,
...extra,
- };
+ }
}
- });
+ })
- return mergedReport;
+ return mergedReport
}
/**
@@ -79,7 +79,9 @@ function initializeEmptySummary(): Summary {
skipped: 0,
pending: 0,
other: 0,
+ flaky: 0,
+ duration: 0,
start: Number.MAX_SAFE_INTEGER,
stop: 0,
- };
+ }
}
diff --git a/src/methods/read-reports.test.ts b/src/methods/read-reports.test.ts
new file mode 100644
index 0000000..5d4f621
--- /dev/null
+++ b/src/methods/read-reports.test.ts
@@ -0,0 +1,271 @@
+import fs from 'fs'
+import path from 'path'
+import { describe, it, expect, beforeEach, vi } from 'vitest'
+import {
+ readReportFromFile,
+ readReportsFromDirectory,
+ readReportsFromGlobPattern,
+} from './read-reports'
+import { Report } from '../../types/ctrf'
+
+// Mock fs module for testing
+vi.mock('fs')
+vi.mock('glob')
+
+const mockFs = vi.mocked(fs)
+const mockGlob = vi.mocked(await import('glob'))
+
+describe('read-reports', () => {
+ beforeEach(() => {
+ vi.clearAllMocks()
+ })
+
+ describe('readSingleReport', () => {
+ const validCtrfReport: Report = {
+ reportFormat: 'CTRF',
+ specVersion: '1.0.0',
+ results: {
+ tool: { name: 'jest' },
+ summary: {
+ tests: 1,
+ passed: 1,
+ failed: 0,
+ skipped: 0,
+ pending: 0,
+ other: 0,
+ flaky: 0,
+ start: Date.now(),
+ stop: Date.now() + 1000,
+ duration: 1000,
+ },
+ tests: [
+ {
+ name: 'test1',
+ status: 'passed',
+ duration: 100,
+ },
+ ],
+ },
+ }
+
+ it('should read and parse a valid CTRF report file', () => {
+ const filePath = '/path/to/report.json'
+ mockFs.existsSync.mockReturnValue(true)
+ mockFs.readFileSync.mockReturnValue(JSON.stringify(validCtrfReport))
+
+ const result = readReportFromFile(filePath)
+
+ expect(result).toEqual(validCtrfReport)
+ expect(mockFs.readFileSync).toHaveBeenCalledWith(
+ path.resolve(filePath),
+ 'utf8'
+ )
+ })
+
+ it('should throw error when file does not exist', () => {
+ const filePath = '/path/to/nonexistent.json'
+ mockFs.existsSync.mockReturnValue(false)
+
+ expect(() => readReportFromFile(filePath)).toThrow(
+ 'JSON file not found: /path/to/nonexistent.json'
+ )
+ })
+
+ it('should throw error when file is not valid JSON', () => {
+ const filePath = '/path/to/invalid.json'
+ mockFs.existsSync.mockReturnValue(true)
+ mockFs.readFileSync.mockReturnValue('invalid json')
+
+ expect(() => readReportFromFile(filePath)).toThrow(
+ /Failed to read or parse the file/
+ )
+ })
+
+ it('should throw error when file is not a valid CTRF report', () => {
+ const filePath = '/path/to/invalid-ctrf.json'
+ mockFs.existsSync.mockReturnValue(true)
+ mockFs.readFileSync.mockReturnValue(JSON.stringify({ invalid: 'data' }))
+
+ expect(() => readReportFromFile(filePath)).toThrow(
+ /is not a valid CTRF report/
+ )
+ })
+ })
+
+ describe('readReportsFromDirectory', () => {
+ it('should read valid CTRF reports from directory', () => {
+ const directoryPath = '/path/to/reports'
+ const validCtrfReport: Report = {
+ reportFormat: 'CTRF',
+ specVersion: '1.0.0',
+ results: {
+ tool: { name: 'jest' },
+ summary: {
+ tests: 1,
+ passed: 1,
+ failed: 0,
+ skipped: 0,
+ pending: 0,
+ other: 0,
+ flaky: 0,
+ start: Date.now(),
+ stop: Date.now() + 1000,
+ duration: 1000,
+ },
+ tests: [
+ {
+ name: 'test1',
+ status: 'passed',
+ duration: 100,
+ },
+ ],
+ },
+ }
+
+ mockFs.existsSync.mockReturnValue(true)
+ mockFs.readdirSync.mockReturnValue([
+ 'report1.json',
+ 'report2.json',
+ 'not-json.txt',
+ ] as any)
+ mockFs.readFileSync.mockReturnValue(JSON.stringify(validCtrfReport))
+
+ const result = readReportsFromDirectory(directoryPath)
+
+ expect(result).toHaveLength(2)
+ expect(result[0]).toEqual(validCtrfReport)
+ expect(result[1]).toEqual(validCtrfReport)
+ })
+
+ it('should throw error when directory does not exist', () => {
+ const directoryPath = '/path/to/nonexistent'
+ mockFs.existsSync.mockReturnValue(false)
+
+ expect(() => readReportsFromDirectory(directoryPath)).toThrow(
+ /does not exist/
+ )
+ })
+
+ it('should throw error when no valid CTRF reports are found', () => {
+ const directoryPath = '/path/to/empty'
+ mockFs.existsSync.mockReturnValue(true)
+ mockFs.readdirSync.mockReturnValue(['not-json.txt'] as any)
+
+ expect(() => readReportsFromDirectory(directoryPath)).toThrow(
+ /No valid CTRF reports found/
+ )
+ })
+
+ it('should skip invalid files and warn about them', () => {
+ const directoryPath = '/path/to/mixed'
+ const validCtrfReport: Report = {
+ reportFormat: 'CTRF',
+ specVersion: '1.0.0',
+ results: {
+ tool: { name: 'jest' },
+ summary: {
+ tests: 1,
+ passed: 1,
+ failed: 0,
+ skipped: 0,
+ pending: 0,
+ other: 0,
+ flaky: 0,
+ start: Date.now(),
+ stop: Date.now() + 1000,
+ duration: 1000,
+ },
+ tests: [
+ {
+ name: 'test1',
+ status: 'passed',
+ duration: 100,
+ },
+ ],
+ },
+ }
+
+ mockFs.existsSync.mockReturnValue(true)
+ mockFs.readdirSync.mockReturnValue(['valid.json', 'invalid.json'] as any)
+ mockFs.readFileSync
+ .mockReturnValueOnce(JSON.stringify(validCtrfReport))
+ .mockReturnValueOnce(JSON.stringify({ invalid: 'data' }))
+
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
+
+ const result = readReportsFromDirectory(directoryPath)
+
+ expect(result).toHaveLength(1)
+ expect(result[0]).toEqual(validCtrfReport)
+ expect(consoleSpy).toHaveBeenCalledWith(
+ 'Skipping invalid CTRF report file: invalid.json'
+ )
+
+ consoleSpy.mockRestore()
+ })
+ })
+
+ describe('readReportsFromGlobPattern', () => {
+ it('should read valid CTRF reports from glob pattern', () => {
+ const pattern = 'reports/*.json'
+ const validCtrfReport: Report = {
+ reportFormat: 'CTRF',
+ specVersion: '1.0.0',
+ results: {
+ tool: { name: 'jest' },
+ summary: {
+ tests: 1,
+ passed: 1,
+ failed: 0,
+ skipped: 0,
+ pending: 0,
+ other: 0,
+ flaky: 0,
+ start: Date.now(),
+ stop: Date.now() + 1000,
+ duration: 1000,
+ },
+ tests: [
+ {
+ name: 'test1',
+ status: 'passed',
+ duration: 100,
+ },
+ ],
+ },
+ }
+
+ mockGlob.sync.mockReturnValue(['report1.json', 'report2.json'])
+ mockFs.readFileSync.mockReturnValue(JSON.stringify(validCtrfReport))
+
+ const result = readReportsFromGlobPattern(pattern)
+
+ expect(result).toHaveLength(2)
+ expect(result[0]).toEqual(validCtrfReport)
+ expect(result[1]).toEqual(validCtrfReport)
+ })
+
+ it('should throw error when no files match the pattern', () => {
+ const pattern = 'nonexistent/*.json'
+ mockGlob.sync.mockReturnValue([])
+
+ expect(() => readReportsFromGlobPattern(pattern)).toThrow(
+ /No files found matching the pattern/
+ )
+ })
+
+ it('should throw error when no valid CTRF reports are found', () => {
+ const pattern = 'invalid/*.json'
+ mockGlob.sync.mockReturnValue(['invalid.json'])
+ mockFs.readFileSync.mockReturnValue(JSON.stringify({ invalid: 'data' }))
+
+ const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
+
+ expect(() => readReportsFromGlobPattern(pattern)).toThrow(
+ /No valid CTRF reports found/
+ )
+
+ consoleSpy.mockRestore()
+ })
+ })
+})
diff --git a/src/methods/read-reports.ts b/src/methods/read-reports.ts
index 36debe1..20d3d6f 100644
--- a/src/methods/read-reports.ts
+++ b/src/methods/read-reports.ts
@@ -1,7 +1,7 @@
-import fs from 'fs';
-import path from 'path';
-import { Report } from '../../types/ctrf.js';
-import { glob } from 'glob';
+import fs from 'fs'
+import path from 'path'
+import { Report } from '../../types/ctrf.js'
+import { glob } from 'glob'
/**
* Reads a single CTRF report file from a specified path.
@@ -10,32 +10,33 @@ import { glob } from 'glob';
* @returns The parsed `CtrfReport` object.
* @throws If the file does not exist, is not a valid JSON, or does not conform to the `CtrfReport` structure.
*/
-export function readSingleReport(filePath: string): Report {
- if (!fs.existsSync(filePath)) {
- throw new Error(`JSON file not found: ${filePath}`)
- }
- const resolvedPath = path.resolve(filePath);
-
- if (!fs.existsSync(resolvedPath)) {
- throw new Error(`The file '${resolvedPath}' does not exist.`);
- }
+export function readReportFromFile(filePath: string): Report {
+ if (!fs.existsSync(filePath)) {
+ throw new Error(`JSON file not found: ${filePath}`)
+ }
+ const resolvedPath = path.resolve(filePath)
- try {
- const content = fs.readFileSync(resolvedPath, 'utf8');
+ if (!fs.existsSync(resolvedPath)) {
+ throw new Error(`The file '${resolvedPath}' does not exist.`)
+ }
- const parsed = JSON.parse(content);
+ try {
+ const content = fs.readFileSync(resolvedPath, 'utf8')
- if (!isCtrfReport(parsed)) {
- throw new Error(`The file '${resolvedPath}' is not a valid CTRF report.`);
- }
+ const parsed = JSON.parse(content)
- return parsed as Report;
- } catch (error) {
- const errorMessage = (error as any).message || 'Unknown error';
- throw new Error(`Failed to read or parse the file '${resolvedPath}': ${errorMessage}`);
+ if (!isCtrfReport(parsed)) {
+ throw new Error(`The file '${resolvedPath}' is not a valid CTRF report.`)
}
-}
+ return parsed as Report
+ } catch (error) {
+ const errorMessage = (error as Error).message || 'Unknown error'
+ throw new Error(
+ `Failed to read or parse the file '${resolvedPath}': ${errorMessage}`
+ )
+ }
+}
/**
* Reads all CTRF report files from a given directory.
@@ -45,82 +46,85 @@ export function readSingleReport(filePath: string): Report {
* @throws If the directory does not exist or no valid CTRF reports are found.
*/
export function readReportsFromDirectory(directoryPath: string): Report[] {
- directoryPath = path.resolve(directoryPath);
+ directoryPath = path.resolve(directoryPath)
- if (!fs.existsSync(directoryPath)) {
- throw new Error(`The directory '${directoryPath}' does not exist.`);
- }
+ if (!fs.existsSync(directoryPath)) {
+ throw new Error(`The directory '${directoryPath}' does not exist.`)
+ }
- const files = fs.readdirSync(directoryPath);
-
- const reports: Report[] = files
- .filter((file) => path.extname(file) === '.json')
- .map((file) => {
- const filePath = path.join(directoryPath, file);
- try {
- const content = fs.readFileSync(filePath, 'utf8');
- const parsed = JSON.parse(content);
-
- if (!isCtrfReport(parsed)) {
- console.warn(`Skipping invalid CTRF report file: ${file}`);
- return null;
- }
-
- return parsed as Report;
- } catch (error) {
- console.warn(`Failed to read or parse file '${file}':`, error);
- return null;
- }
- })
- .filter((report): report is Report => report !== null);
-
- if (reports.length === 0) {
- throw new Error(`No valid CTRF reports found in the directory '${directoryPath}'.`);
- }
+ const files = fs.readdirSync(directoryPath)
- return reports;
+ const reports: Report[] = files
+ .filter(file => path.extname(file) === '.json')
+ .map(file => {
+ const filePath = path.join(directoryPath, file)
+ try {
+ const content = fs.readFileSync(filePath, 'utf8')
+ const parsed = JSON.parse(content)
+
+ if (!isCtrfReport(parsed)) {
+ console.warn(`Skipping invalid CTRF report file: ${file}`)
+ return null
+ }
+
+ return parsed as Report
+ } catch (error) {
+ console.warn(`Failed to read or parse file '${file}':`, error)
+ return null
+ }
+ })
+ .filter((report): report is Report => report !== null)
+
+ if (reports.length === 0) {
+ throw new Error(
+ `No valid CTRF reports found in the directory '${directoryPath}'.`
+ )
+ }
+
+ return reports
}
/**
* Reads all CTRF report files matching a glob pattern.
*
* @param pattern The glob pattern to match files (e.g., ctrf/*.json).
-* @returns An array of parsed `CtrfReport` objects.
-* @throws If no valid CTRF reports are found.
-*/
+ * @returns An array of parsed `CtrfReport` objects.
+ * @throws If no valid CTRF reports are found.
+ */
export function readReportsFromGlobPattern(pattern: string): Report[] {
- const files = glob.sync(pattern);
-
- if (files.length === 0) {
- throw new Error(`No files found matching the pattern '${pattern}'.`);
- }
-
- const reports: Report[] = files
- .map((file) => {
- try {
+ const files = glob.sync(pattern)
- const content = fs.readFileSync(file, 'utf8');
- const parsed = JSON.parse(content);
+ if (files.length === 0) {
+ throw new Error(`No files found matching the pattern '${pattern}'.`)
+ }
- if (!isCtrfReport(parsed)) {
- console.warn(`Skipping invalid CTRF report file: ${file}`);
- return null;
- }
+ const reports: Report[] = files
+ .map(file => {
+ try {
+ const content = fs.readFileSync(file, 'utf8')
+ const parsed = JSON.parse(content)
- return parsed as Report;
- } catch (error) {
- console.warn(`Failed to read or parse file '${file}':`, error);
- return null;
- }
- })
- .filter((report): report is Report => report !== null);
-
- if (reports.length === 0) {
- throw new Error(`No valid CTRF reports found matching the pattern '${pattern}'.`);
- }
+ if (!isCtrfReport(parsed)) {
+ console.warn(`Skipping invalid CTRF report file: ${file}`)
+ return null
+ }
- return reports;
+ return parsed as Report
+ } catch (error) {
+ console.warn(`Failed to read or parse file '${file}':`, error)
+ return null
+ }
+ })
+ .filter((report): report is Report => report !== null)
+
+ if (reports.length === 0) {
+ throw new Error(
+ `No valid CTRF reports found matching the pattern '${pattern}'.`
+ )
+ }
+
+ return reports
}
/**
@@ -129,13 +133,15 @@ export function readReportsFromGlobPattern(pattern: string): Report[] {
* @param obj The object to validate.
* @returns `true` if the object matches the `CtrfReport` type; otherwise, `false`.
*/
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
function isCtrfReport(obj: any): obj is Report {
- return (
- obj &&
- typeof obj === 'object' &&
- obj.results &&
- Array.isArray(obj.results.tests) &&
- typeof obj.results.summary === 'object' &&
- typeof obj.results.tool === 'object'
- );
+ return (
+ obj &&
+ typeof obj === 'object' &&
+ obj.results &&
+ Array.isArray(obj.results.tests) &&
+ typeof obj.results.summary === 'object' &&
+ typeof obj.results.tool === 'object'
+ )
}
diff --git a/src/methods/run-insights.test.ts b/src/methods/run-insights.test.ts
new file mode 100644
index 0000000..57e9eb2
--- /dev/null
+++ b/src/methods/run-insights.test.ts
@@ -0,0 +1,436 @@
+import { describe, it, expect } from 'vitest'
+import {
+ isTestFlaky,
+ formatAsPercentage,
+ formatInsightsMetricAsPercentage,
+ enrichReportWithInsights,
+} from './run-insights'
+
+import { Report, Test, InsightsMetric } from '../../types/ctrf.js'
+import { CTRF_REPORT_FORMAT, CTRF_SPEC_VERSION } from '../constants'
+
+const createMockTest = (overrides: Partial = {}): Test => ({
+ name: 'test-name',
+ status: 'passed',
+ duration: 100,
+ ...overrides,
+})
+
+const createMockReport = (
+ tests: Test[] = [],
+ overrides: Partial = {}
+): Report => ({
+ reportFormat: CTRF_REPORT_FORMAT,
+ specVersion: CTRF_SPEC_VERSION,
+ results: {
+ tool: { name: 'jest' },
+ summary: {
+ tests: tests.length,
+ passed: tests.filter(t => t.status === 'passed').length,
+ failed: tests.filter(t => t.status === 'failed').length,
+ skipped: tests.filter(t => t.status === 'skipped').length,
+ pending: tests.filter(t => t.status === 'pending').length,
+ other: tests.filter(t => t.status === 'other').length,
+ flaky: tests.filter(t => t.flaky === true).length,
+ start: Date.now(),
+ stop: Date.now() + 1000,
+ duration: 1000,
+ },
+ tests,
+ },
+ ...overrides,
+})
+
+describe('run-insights utility functions', () => {
+ describe('isTestFlaky', () => {
+ it('should return true for explicitly flaky tests', () => {
+ const test = createMockTest({ flaky: true })
+ expect(isTestFlaky(test)).toBe(true)
+ })
+
+ it('should return true for passed tests with retries', () => {
+ const test = createMockTest({
+ status: 'passed',
+ retries: 2,
+ })
+ expect(isTestFlaky(test)).toBe(true)
+ })
+
+ it('should return false for failed tests with retries', () => {
+ const test = createMockTest({
+ status: 'failed',
+ retries: 2,
+ })
+ expect(isTestFlaky(test)).toBe(false)
+ })
+
+ it('should return false for passed tests without retries', () => {
+ const test = createMockTest({
+ status: 'passed',
+ retries: 0,
+ })
+ expect(isTestFlaky(test)).toBe(false)
+ })
+
+ it('should return false for passed tests without retries property', () => {
+ const test = createMockTest({ status: 'passed' })
+ expect(isTestFlaky(test)).toBe(false)
+ })
+ })
+
+ describe('formatAsPercentage', () => {
+ it('should format ratio as percentage with default 2 decimals', () => {
+ expect(formatAsPercentage(0.25)).toBe('25.00%')
+ expect(formatAsPercentage(0.5)).toBe('50.00%')
+ expect(formatAsPercentage(0.75)).toBe('75.00%')
+ expect(formatAsPercentage(1)).toBe('100.00%')
+ })
+
+ it('should format ratio as percentage with custom decimals', () => {
+ expect(formatAsPercentage(0.25, 1)).toBe('25.0%')
+ expect(formatAsPercentage(0.25, 0)).toBe('25%')
+ expect(formatAsPercentage(0.25, 3)).toBe('25.000%')
+ })
+
+ it('should handle edge cases', () => {
+ expect(formatAsPercentage(0)).toBe('0.00%')
+ expect(formatAsPercentage(0.00001)).toBe('0.00%')
+ expect(formatAsPercentage(0.999)).toBe('99.90%')
+ })
+ })
+
+ describe('formatInsightsMetricAsPercentage', () => {
+ it('should format all metric values as percentages', () => {
+ const metric: InsightsMetric = {
+ current: 0.25,
+ baseline: 0.2,
+ change: 0.05,
+ }
+
+ const result = formatInsightsMetricAsPercentage(metric)
+
+ expect(result).toEqual({
+ current: '25.00%',
+ baseline: '20.00%',
+ change: '+5.00%',
+ })
+ })
+
+ it('should handle negative change values', () => {
+ const metric: InsightsMetric = {
+ current: 0.15,
+ baseline: 0.2,
+ change: -0.05,
+ }
+
+ const result = formatInsightsMetricAsPercentage(metric)
+
+ expect(result).toEqual({
+ current: '15.00%',
+ baseline: '20.00%',
+ change: '-5.00%',
+ })
+ })
+
+ it('should handle zero change values', () => {
+ const metric: InsightsMetric = {
+ current: 0.2,
+ baseline: 0.2,
+ change: 0,
+ }
+
+ const result = formatInsightsMetricAsPercentage(metric)
+
+ expect(result).toEqual({
+ current: '20.00%',
+ baseline: '20.00%',
+ change: '+0.00%',
+ })
+ })
+ })
+})
+
+describe('enrichReportWithInsights - Main API', () => {
+ describe('basic functionality', () => {
+ it('should enrich a report with run-level insights when no baseline reports', () => {
+ const tests = [
+ createMockTest({ name: 'test1', status: 'passed', duration: 100 }),
+ createMockTest({ name: 'test2', status: 'failed', duration: 200 }),
+ createMockTest({
+ name: 'test3',
+ status: 'passed',
+ retries: 1,
+ flaky: true,
+ duration: 150,
+ }),
+ ]
+ const currentReport = createMockReport(tests)
+
+ const result = enrichReportWithInsights(currentReport, [])
+
+ expect(result.insights).toBeDefined()
+ expect(result.insights!.flakyRate?.current).toBeGreaterThan(0)
+ expect(result.insights!.failRate?.current).toBeGreaterThan(0)
+ expect(result.insights!.averageTestDuration?.current).toBe(150) // (100+200+150)/3
+ expect(result.insights!.runsAnalyzed).toBe(1)
+
+ expect(result.insights!.flakyRate?.baseline).toBe(0)
+ expect(result.insights!.flakyRate?.change).toBe(0)
+ })
+
+ it('should add test-level insights to each test', () => {
+ const tests = [
+ createMockTest({ name: 'test1', status: 'passed', duration: 100 }),
+ createMockTest({ name: 'test2', status: 'failed', duration: 200 }),
+ ]
+ const currentReport = createMockReport(tests)
+
+ const result = enrichReportWithInsights(currentReport, [])
+
+ expect(result.results.tests[0].insights).toBeDefined()
+ expect(result.results.tests[1].insights).toBeDefined()
+
+ expect(result.results.tests[0].insights!.failRate?.current).toBe(0)
+ expect(result.results.tests[1].insights!.failRate?.current).toBe(1)
+ expect(
+ result.results.tests[0].insights!.averageTestDuration?.current
+ ).toBe(100)
+ expect(
+ result.results.tests[1].insights!.averageTestDuration?.current
+ ).toBe(200)
+ })
+ })
+
+ describe('baseline comparison functionality', () => {
+ it('should compare against previous report by default', () => {
+ const currentTests = [
+ createMockTest({ name: 'test1', status: 'passed', duration: 100 }),
+ createMockTest({ name: 'test2', status: 'passed', duration: 200 }),
+ ]
+ const previousTests = [
+ createMockTest({ name: 'test1', status: 'failed', duration: 150 }),
+ createMockTest({ name: 'test2', status: 'failed', duration: 250 }),
+ ]
+
+ const currentReport = createMockReport(currentTests, {
+ results: {
+ ...createMockReport(currentTests).results,
+ summary: {
+ ...createMockReport(currentTests).results.summary,
+ start: 2000,
+ },
+ },
+ })
+ const previousReport = createMockReport(previousTests, {
+ results: {
+ ...createMockReport(previousTests).results,
+ summary: {
+ ...createMockReport(previousTests).results.summary,
+ start: 1000,
+ },
+ },
+ })
+
+ const result = enrichReportWithInsights(
+ currentReport,
+ [previousReport],
+ previousReport
+ )
+
+ expect(result.insights).toBeDefined()
+ expect(result.insights!.failRate?.current).toBe(0.5) // Overall: 2 passed + 2 failed = 50% fail rate
+ expect(result.insights!.failRate?.baseline).toBe(1) // Previous: all failed
+ expect(result.insights!.failRate?.change).toBe(-0.5) // Improvement of 50%
+ expect(result.insights!.runsAnalyzed).toBe(2)
+ })
+
+ it('should handle baseline by index', () => {
+ const currentTests = [createMockTest({ name: 'test1', status: 'passed' })]
+ const previous1Tests = [
+ createMockTest({ name: 'test1', status: 'failed' }),
+ ]
+ const previous2Tests = [
+ createMockTest({ name: 'test1', status: 'passed' }),
+ ]
+
+ const currentReport = createMockReport(currentTests)
+ const previousReport1 = createMockReport(previous1Tests)
+ const previousReport2 = createMockReport(previous2Tests)
+
+ // Use previousReport2 as baseline (second previous report)
+ const result = enrichReportWithInsights(
+ currentReport,
+ [previousReport1, previousReport2],
+ previousReport2
+ )
+
+ expect(result.insights!.failRate?.current).toBe(0.3333) // 1 passed + 1 failed + 1 passed = 1/3 fail rate
+ expect(result.insights!.failRate?.baseline).toBe(0) // previous2 had no failures
+ expect(result.insights!.failRate?.change).toBe(0.3333)
+ })
+
+ it('should handle baseline by report ID', () => {
+ const currentTests = [createMockTest({ name: 'test1', status: 'passed' })]
+ const previousTests = [
+ createMockTest({ name: 'test1', status: 'failed' }),
+ ]
+
+ const currentReport = createMockReport(currentTests)
+ const previousReport = createMockReport(previousTests, {
+ results: {
+ ...createMockReport(previousTests).results,
+ summary: {
+ ...createMockReport(previousTests).results.summary,
+ start: 12345,
+ },
+ },
+ })
+
+ const result = enrichReportWithInsights(
+ currentReport,
+ [previousReport],
+ previousReport
+ )
+
+ expect(result.insights!.failRate?.current).toBe(0.5)
+ expect(result.insights!.failRate?.baseline).toBe(1)
+ expect(result.insights!.failRate?.change).toBe(-0.5)
+ })
+
+ it('should handle invalid baseline gracefully', () => {
+ const currentTests = [createMockTest({ name: 'test1', status: 'passed' })]
+ const previousTests = [
+ createMockTest({ name: 'test1', status: 'failed' }),
+ ]
+
+ const currentReport = createMockReport(currentTests)
+ const previousReport = createMockReport(previousTests)
+
+ const invalidBaseline = createMockReport([], { results: null } as any)
+ const result1 = enrichReportWithInsights(
+ currentReport,
+ [previousReport],
+ invalidBaseline
+ )
+ expect(result1.insights!.failRate?.baseline).toBe(0)
+ expect(result1.insights!.failRate?.change).toBe(0)
+
+ const result2 = enrichReportWithInsights(currentReport, [previousReport])
+ expect(result2.insights!.failRate?.baseline).toBe(0)
+ expect(result2.insights!.failRate?.change).toBe(0)
+ })
+ })
+
+ describe('added/removed tests tracking', () => {
+ it.skip('should track tests added since baseline', () => {
+ const currentTests = [
+ createMockTest({ name: 'test1', status: 'passed' }),
+ createMockTest({ name: 'test2', status: 'passed' }),
+ createMockTest({ name: 'test3', status: 'passed' }),
+ ]
+ const previousTests = [
+ createMockTest({ name: 'test1', status: 'passed' }),
+ ]
+
+ const currentReport = createMockReport(currentTests)
+ const previousReport = createMockReport(previousTests)
+
+ const result = enrichReportWithInsights(
+ currentReport,
+ [previousReport],
+ previousReport
+ )
+
+ expect(result.insights!.extra!.testsAdded).toHaveLength(2)
+ expect((result.insights!.extra!.testsAdded as any[])[0].name).toBe(
+ 'test2'
+ )
+ expect((result.insights!.extra!.testsAdded as any[])[1].name).toBe(
+ 'test3'
+ )
+ })
+
+ it.skip('should track tests removed since baseline', () => {
+ const currentTests = [createMockTest({ name: 'test1', status: 'passed' })]
+ const previousTests = [
+ createMockTest({ name: 'test1', status: 'passed' }),
+ createMockTest({ name: 'test2', status: 'passed' }),
+ createMockTest({ name: 'test3', status: 'passed' }),
+ ]
+
+ const currentReport = createMockReport(currentTests)
+ const previousReport = createMockReport(previousTests)
+
+ const result = enrichReportWithInsights(
+ currentReport,
+ [previousReport],
+ previousReport
+ )
+
+ expect(result.insights!.extra!.testsRemoved).toHaveLength(2)
+ expect((result.insights!.extra!.testsRemoved as any[])[0].name).toBe(
+ 'test2'
+ )
+ expect((result.insights!.extra!.testsRemoved as any[])[1].name).toBe(
+ 'test3'
+ )
+ })
+
+ it.skip('should handle single report no added/removed tests', () => {
+ const currentTests = [createMockTest({ name: 'test1', status: 'passed' })]
+
+ const currentReport = createMockReport(currentTests)
+ const result = enrichReportWithInsights(currentReport, [])
+
+ expect(result.insights!.extra!.testsAdded).toBeUndefined()
+ expect(result.insights!.extra!.testsRemoved).toBeUndefined()
+ })
+ })
+
+ describe('edge cases', () => {
+ it('should handle empty current report', () => {
+ const currentReport = createMockReport([])
+ const previousReport = createMockReport([createMockTest()])
+
+ const result = enrichReportWithInsights(currentReport, [previousReport])
+
+ expect(result.insights).toBeDefined()
+ expect(result.insights!.failRate?.current).toBe(0)
+ expect(result.insights!.averageTestDuration?.current).toBe(100)
+ })
+
+ it('should handle invalid current report', () => {
+ const invalidReport = { results: null } as any
+
+ const result = enrichReportWithInsights(invalidReport, [])
+
+ expect(result).toBe(invalidReport)
+ })
+
+ it('should handle multiple previous reports', () => {
+ const currentTests = [createMockTest({ name: 'test1', status: 'passed' })]
+ const previous1Tests = [
+ createMockTest({ name: 'test1', status: 'failed' }),
+ ]
+ const previous2Tests = [
+ createMockTest({ name: 'test1', status: 'passed' }),
+ ]
+ const previous3Tests = [
+ createMockTest({ name: 'test1', status: 'failed' }),
+ ]
+
+ const currentReport = createMockReport(currentTests)
+ const previousReports = [
+ createMockReport(previous1Tests),
+ createMockReport(previous2Tests),
+ createMockReport(previous3Tests),
+ ]
+
+ const result = enrichReportWithInsights(currentReport, previousReports)
+
+ expect(result.insights!.runsAnalyzed).toBe(4)
+ expect(result.insights!.failRate?.current).toBeDefined()
+ expect(result.insights!.failRate?.baseline).toBeDefined()
+ })
+ })
+})
diff --git a/src/methods/run-insights.ts b/src/methods/run-insights.ts
index 281da22..8388f78 100644
--- a/src/methods/run-insights.ts
+++ b/src/methods/run-insights.ts
@@ -1,4 +1,11 @@
-import { InsightsMetric, Report, Test, TestInsights, Insights } from "../../types/ctrf.js"
+import {
+ InsightsMetric,
+ Report,
+ Test,
+ TestInsights,
+ Insights,
+} from '../../types/ctrf.js'
+import { sortReportsByTimestamp } from './utilities/sort-reports.js'
export interface SimplifiedTestData {
name: string
@@ -6,10 +13,6 @@ export interface SimplifiedTestData {
filePath?: string
}
-// ========================================
-// UTILITY FUNCTIONS
-// ========================================
-
/**
* Utility function that determines if a test is flaky based on its retries and status.
*
@@ -31,7 +34,10 @@ export function isTestFlaky(test: Test): boolean {
* @param decimals - Number of decimal places (default: 2)
* @returns Formatted percentage string (e.g., "25.50%")
*/
-export function formatAsPercentage(ratio: number, decimals: number = 2): string {
+export function formatAsPercentage(
+ ratio: number,
+ decimals: number = 2
+): string {
return `${(ratio * 100).toFixed(decimals)}%`
}
@@ -45,14 +51,34 @@ export function formatAsPercentage(ratio: number, decimals: number = 2): string
export function formatInsightsMetricAsPercentage(
metric: InsightsMetric,
decimals: number = 2
-): { current: string; previous: string; change: string } {
+): { current: string; baseline: string; change: string } {
return {
current: formatAsPercentage(metric.current, decimals),
- previous: formatAsPercentage(metric.previous, decimals),
- change: `${metric.change >= 0 ? '+' : ''}${formatAsPercentage(metric.change, decimals)}`
+ baseline: formatAsPercentage(metric.baseline, decimals),
+ change: `${metric.change >= 0 ? '+' : ''}${formatAsPercentage(metric.change, decimals)}`,
}
}
+/**
+ * Utility function that calculates percent fractional change between current and baseline values.
+ * Used for duration metrics where the change should be expressed as a ratio (e.g., 0.25 = 25% increase).
+ *
+ * @param current - The current value
+ * @param baseline - The baseline value to compare against
+ * @param decimals - Number of decimal places (default: 4)
+ * @returns Percent fractional change, or 0 if baseline is 0
+ */
+export function calculatePercentChange(
+ current: number,
+ baseline: number,
+ decimals: number = 4
+): number {
+ if (baseline === 0) {
+ return 0
+ }
+ return Number(((current - baseline) / baseline).toFixed(decimals))
+}
+
/**
* Calculates the 95th percentile from an array of numbers.
*
@@ -61,10 +87,10 @@ export function formatInsightsMetricAsPercentage(
*/
function calculateP95(values: number[]): number {
if (values.length === 0) return 0
-
+
const sorted = [...values].sort((a, b) => a - b)
const index = Math.ceil(sorted.length * 0.95) - 1
-
+
return Number(sorted[Math.max(0, index)].toFixed(2))
}
@@ -80,22 +106,22 @@ function validateReportForInsights(report: Report): boolean {
* Key distinction: "Attempts" include retries, "Results" are final test outcomes only.
*/
interface AggregatedRunMetrics {
- // ATTEMPT METRICS (includes retries)
- totalAttempts: number // Total test executions including retries (e.g., test fails 2x then passes = 3 attempts)
- totalAttemptsFailed: number // Total failed test executions including retries (e.g., 2 failed attempts + 1 final pass = 2 failed attempts)
- totalAttemptsFlaky: number // Total retry attempts for flaky tests only, failed before the final result was passed (e.g., flaky test with 2 retries = 2 flaky attempts)
-
- // RESULT METRICS (final test outcomes only, no retries counted)
- totalResults: number // Total number of tests executed (each test counted once regardless of retries)
- totalResultsFailed: number // Number of tests with final status "failed" (1 per test regardless of retry count)
- totalResultsPassed: number // Number of tests with final status "passed" (1 per test regardless of retry count)
- totalResultsSkipped: number // Number of tests with final status "skipped/pending/other" (1 per test)
- totalResultsFlaky: number // Number of tests marked as flaky (1 per test regardless of retry count)
-
- // OTHER METRICS
- totalResultsDuration: number // Total duration of all final test results (retries not included in duration)
- reportsAnalyzed: number // Total number of reports analyzed
- }
+ // ATTEMPT METRICS (includes retries)
+ totalAttempts: number // Total test executions including retries (e.g., test fails 2x then passes = 3 attempts)
+ totalAttemptsFailed: number // Total failed test executions including retries (e.g., 2 failed attempts + 1 final pass = 2 failed attempts)
+ totalAttemptsFlaky: number // Total retry attempts for flaky tests only, failed before the final result was passed (e.g., flaky test with 2 retries = 2 flaky attempts)
+
+ // RESULT METRICS (final test outcomes only, no retries counted)
+ totalResults: number // Total number of tests executed (each test counted once regardless of retries)
+ totalResultsFailed: number // Number of tests with final status "failed" (1 per test regardless of retry count)
+ totalResultsPassed: number // Number of tests with final status "passed" (1 per test regardless of retry count)
+ totalResultsSkipped: number // Number of tests with final status "skipped/pending/other" (1 per test)
+ totalResultsFlaky: number // Number of tests marked as flaky (1 per test regardless of retry count)
+
+ // OTHER METRICS
+ totalResultsDuration: number // Total duration of all final test results (retries not included in duration)
+ reportsAnalyzed: number // Total number of reports analyzed
+}
/**
* Aggregated run metrics for a single test across multiple reports,
@@ -139,7 +165,7 @@ function aggregateTestMetricsAcrossReports(
totalResultsDuration: 0,
appearsInRuns: 0,
reportsAnalyzed: 0,
- durations: []
+ durations: [],
})
}
@@ -221,14 +247,10 @@ function consolidateTestMetricsToRunMetrics(
totalResultsFlaky,
totalAttemptsFlaky,
totalResultsDuration,
- reportsAnalyzed: metricsMap.size
+ reportsAnalyzed: metricsMap.size,
}
}
-// ========================================
-// INSIGHT Flaky Rate FUNCTIONS
-// ========================================
-
/**
* Calculates overall flaky rate from consolidated run metrics.
* Flaky rate = (failed attempts from flaky tests) / (total attempts) as ratio 0-1
@@ -240,33 +262,11 @@ function calculateFlakyRateFromMetrics(
return 0
}
- return Number((runMetrics.totalAttemptsFlaky / runMetrics.totalAttempts).toFixed(4))
-}
-
-/**
- * Internal helper function that calculates flaky rate insights across all reports (current + all previous).
- *
- * @param currentReport - The current CTRF report
- * @param previousReports - Array of historical CTRF reports
- * @returns InsightsMetric with current value calculated across all reports
- */
-function calculateInsightFlakyRateCurrent(
- currentReport: Report,
- previousReports: Report[]
-): InsightsMetric {
- const allReports = [currentReport, ...previousReports]
-
- const testMetrics = aggregateTestMetricsAcrossReports(allReports)
- const runMetrics = consolidateTestMetricsToRunMetrics(testMetrics)
- const current = calculateFlakyRateFromMetrics(runMetrics)
-
- return { current, previous: 0, change: 0 }
+ return Number(
+ (runMetrics.totalAttemptsFlaky / runMetrics.totalAttempts).toFixed(4)
+ )
}
-// ========================================
-// INSIGHT Fail Rate FUNCTIONS
-// ========================================
-
/**
* Calculates overall fail rate from consolidated run metrics.
* Fail rate = (totalResultsFailed / totalResults) as ratio 0-1
@@ -278,71 +278,27 @@ function calculateFailRateFromMetrics(
return 0
}
- return Number((runMetrics.totalResultsFailed / runMetrics.totalResults).toFixed(4))
-}
-
-/**
- * Internal helper function that calculates fail rate insights across all reports (current + all previous).
- *
- * @param currentReport - The current CTRF report
- * @param previousReports - Array of historical CTRF reports
- * @returns InsightsMetric with current value calculated across all reports
- */
-function calculateFailRateInsight(
- currentReport: Report,
- previousReports: Report[]
-): InsightsMetric {
- const allReports = [currentReport, ...previousReports]
-
- const testMetrics = aggregateTestMetricsAcrossReports(allReports)
- const runMetrics = consolidateTestMetricsToRunMetrics(testMetrics)
- const current = calculateFailRateFromMetrics(runMetrics)
-
- return { current, previous: 0, change: 0 }
+ return Number(
+ (runMetrics.totalResultsFailed / runMetrics.totalResults).toFixed(4)
+ )
}
-// ========================================
-// INSIGHT Skipped Rate FUNCTIONS
-// ========================================
-
/**
- * Calculates overall skipped rate from consolidated run metrics.
- * Skipped rate = (totalResultsSkipped / totalResults) as ratio 0-1
+ * Calculates overall pass rate from consolidated run metrics.
+ * Pass rate = (totalResultsPassed / totalResults) as ratio 0-1
*/
-function calculateSkippedRateFromMetrics(
+function calculatePassRateFromMetrics(
runMetrics: AggregatedRunMetrics
): number {
if (runMetrics.totalResults === 0) {
return 0
}
- return Number((runMetrics.totalResultsSkipped / runMetrics.totalResults).toFixed(4))
-}
-
-/**
- * Internal helper function that calculates skipped rate insights across all reports (current + all previous).
- *
- * @param currentReport - The current CTRF report
- * @param previousReports - Array of historical CTRF reports
- * @returns InsightsMetric with current value calculated across all reports
- */
-function calculateSkippedRateInsight(
- currentReport: Report,
- previousReports: Report[]
-): InsightsMetric {
- const allReports = [currentReport, ...previousReports]
-
- const testMetrics = aggregateTestMetricsAcrossReports(allReports)
- const runMetrics = consolidateTestMetricsToRunMetrics(testMetrics)
- const current = calculateSkippedRateFromMetrics(runMetrics)
-
- return { current, previous: 0, change: 0 }
+ return Number(
+ (runMetrics.totalResultsPassed / runMetrics.totalResults).toFixed(4)
+ )
}
-// ========================================
-// INSIGHT Average Test Duration FUNCTIONS
-// ========================================
-
/**
* Calculates average test duration from consolidated run metrics.
* Average test duration = (totalDuration / totalResults)
@@ -354,33 +310,11 @@ function calculateAverageTestDurationFromMetrics(
return 0
}
- return Number((runMetrics.totalResultsDuration / runMetrics.totalResults).toFixed(2))
-}
-
-/**
- * Internal helper function that calculates average test duration insights across all reports (current + all previous).
- *
- * @param currentReport - The current CTRF report
- * @param previousReports - Array of historical CTRF reports
- * @returns InsightsMetric with current value calculated across all reports
- */
-function calculateAverageTestDurationInsight(
- currentReport: Report,
- previousReports: Report[]
-): InsightsMetric {
- const allReports = [currentReport, ...previousReports]
-
- const testMetrics = aggregateTestMetricsAcrossReports(allReports)
- const runMetrics = consolidateTestMetricsToRunMetrics(testMetrics)
- const current = calculateAverageTestDurationFromMetrics(runMetrics)
-
- return { current, previous: 0, change: 0 }
+ return Number(
+ (runMetrics.totalResultsDuration / runMetrics.totalResults).toFixed(2)
+ )
}
-// ========================================
-// INSIGHT Average Run Duration FUNCTIONS
-// ========================================
-
/**
* Calculates average run duration from consolidated run metrics.
* Average run duration = (totalDuration / reportsAnalyzed)
@@ -392,34 +326,34 @@ function calculateAverageRunDurationFromMetrics(
return 0
}
- return Number((runMetrics.totalResultsDuration / runMetrics.reportsAnalyzed).toFixed(2))
+ return Number(
+ (runMetrics.totalResultsDuration / runMetrics.reportsAnalyzed).toFixed(2)
+ )
}
/**
- * Internal helper function that calculates average run duration insights across all reports (current + all previous).
+ * Calculates p95 run duration from a collection of reports.
+ * Uses the actual run duration (summary.stop - summary.start) for each report.
*
- * @param currentReport - The current CTRF report
- * @param previousReports - Array of historical CTRF reports
- * @returns InsightsMetric with current value calculated across all reports
- */
-function calculateAverageRunDurationInsight(
- currentReport: Report,
- previousReports: Report[]
-): InsightsMetric {
- const allReports = [currentReport, ...previousReports]
-
- const testMetrics = aggregateTestMetricsAcrossReports(allReports)
- const runMetrics = consolidateTestMetricsToRunMetrics(testMetrics)
-
- const current = calculateAverageRunDurationFromMetrics(runMetrics)
+ * @param reports - Array of CTRF reports to calculate p95 from
+ * @returns The 95th percentile run duration
+ */
+function calculateP95RunDurationFromReports(reports: Report[]): number {
+ const runDurations: number[] = []
+
+ for (const report of reports) {
+ if (validateReportForInsights(report) && report.results?.summary) {
+ const { start, stop } = report.results.summary
+ if (start && stop && stop > start) {
+ const runDuration = stop - start
+ runDurations.push(runDuration)
+ }
+ }
+ }
- return { current, previous: 0, change: 0 }
+ return calculateP95(runDurations)
}
-// ========================================
-// INSIGHT Current FUNCTIONS
-// ========================================
-
/**
* Internal helper function that recursively calculates insights for each report based on all reports that came before it chronologically.
* Only sets the `current` field for each report - `previous` and `change` are calculated later.
@@ -428,192 +362,61 @@ function calculateAverageRunDurationInsight(
* @param index - Current index being processed (default: 0)
* @returns The reports array with insights populated for each report
*/
-function calculateRunInsights(
- reports: Report[],
- index: number = 0
-): Report[] {
+function calculateRunInsights(reports: Report[], index: number = 0): Report[] {
if (index >= reports.length) {
return reports
}
const currentReport = reports[index]
- const previousReports = reports.slice(index + 1) // Reports that came before this one in time
+ const previousReports = reports.slice(index + 1)
const allReportsUpToThisPoint = [currentReport, ...previousReports]
const testMetrics = aggregateTestMetricsAcrossReports(allReportsUpToThisPoint)
const runMetrics = consolidateTestMetricsToRunMetrics(testMetrics)
- const { reportsAnalyzed, ...relevantMetrics } = runMetrics
-
+ const { ...relevantMetrics } = runMetrics
+
currentReport.insights = {
+ passRate: {
+ current: calculatePassRateFromMetrics(runMetrics),
+ baseline: 0,
+ change: 0,
+ },
flakyRate: {
current: calculateFlakyRateFromMetrics(runMetrics),
- previous: 0,
- change: 0
+ baseline: 0,
+ change: 0,
},
failRate: {
current: calculateFailRateFromMetrics(runMetrics),
- previous: 0,
- change: 0
- },
- skippedRate: {
- current: calculateSkippedRateFromMetrics(runMetrics),
- previous: 0,
- change: 0
+ baseline: 0,
+ change: 0,
},
averageTestDuration: {
current: calculateAverageTestDurationFromMetrics(runMetrics),
- previous: 0,
- change: 0
+ baseline: 0,
+ change: 0,
},
averageRunDuration: {
current: calculateAverageRunDurationFromMetrics(runMetrics),
- previous: 0,
- change: 0
+ baseline: 0,
+ change: 0,
},
- reportsAnalyzed: allReportsUpToThisPoint.length,
- extra: relevantMetrics
+ p95RunDuration: {
+ current: calculateP95RunDurationFromReports(allReportsUpToThisPoint),
+ baseline: 0,
+ change: 0,
+ },
+ runsAnalyzed: allReportsUpToThisPoint.length,
+ extra: relevantMetrics,
}
return calculateRunInsights(reports, index + 1)
}
-// ========================================
-// TEST-LEVEL INSIGHTS FUNCTIONS
-// ========================================
-
-/**
- * Calculates test-level flaky rate for a specific test.
- */
-function calculateTestFlakyRate(
- testName: string,
- testMetrics: AggregatedTestMetrics
-): InsightsMetric {
- const current = testMetrics.totalAttempts === 0 ? 0 :
- Number((testMetrics.totalAttemptsFlaky / testMetrics.totalAttempts).toFixed(4))
-
- return { current, previous: 0, change: 0 }
-}
-
-/**
- * Calculates test-level fail rate for a specific test.
- */
-function calculateTestFailRate(
- testName: string,
- testMetrics: AggregatedTestMetrics
-): InsightsMetric {
- const current = testMetrics.totalResults === 0 ? 0 :
- Number((testMetrics.totalResultsFailed / testMetrics.totalResults).toFixed(4))
- return { current, previous: 0, change: 0 }
-}
-
-/**
- * Calculates test-level skipped rate for a specific test.
- */
-function calculateTestSkippedRate(
- testName: string,
- testMetrics: AggregatedTestMetrics
-): InsightsMetric {
- const current = testMetrics.totalResults === 0 ? 0 :
- Number((testMetrics.totalResultsSkipped / testMetrics.totalResults).toFixed(4))
-
- return { current, previous: 0, change: 0 }
-}
-
-/**
- * Calculates test-level average duration for a specific test.
- */
-function calculateTestAverageDuration(
- testName: string,
- testMetrics: AggregatedTestMetrics
-): InsightsMetric {
- const current = testMetrics.totalResults === 0 ? 0 :
- Number((testMetrics.totalResultsDuration / testMetrics.totalResults).toFixed(2))
-
- return { current, previous: 0, change: 0 }
-}
-
-/**
- * Calculates test-level p95 duration for a specific test.
- */
-function calculateTestP95Duration(
- testName: string,
- testMetrics: AggregatedTestMetrics
-): InsightsMetric {
- const current = calculateP95(testMetrics.durations)
-
- return { current, previous: 0, change: 0 }
-}
-
-/**
- * Calculates test-level insights for a specific test.
- */
-function calculateTestInsights(
- testName: string,
- testMetrics: AggregatedTestMetrics,
-): TestInsights {
- const { appearsInRuns, reportsAnalyzed, ...relevantMetrics } = testMetrics
-
- return {
- flakyRate: calculateTestFlakyRate(testName, testMetrics),
- failRate: calculateTestFailRate(testName, testMetrics),
- skippedRate: calculateTestSkippedRate(testName, testMetrics),
- averageTestDuration: calculateTestAverageDuration(testName, testMetrics),
- p95Duration: calculateTestP95Duration(testName, testMetrics),
- appearsInRuns: testMetrics.appearsInRuns,
- extra: relevantMetrics
- }
-}
-
-/**
- * Internal helper function that adds test-level insights to all tests in the current report.
- *
- * @param currentReport - The current CTRF report to add insights to
- * @param previousReports - Array of historical CTRF reports
- * @returns The current report with test-level insights added to each test
- */
-function addTestInsightsToCurrentReport(
- currentReport: Report,
- previousReports: Report[]
-): Report {
- if (!validateReportForInsights(currentReport)) {
- return currentReport
- }
-
- const allReports = [currentReport, ...previousReports]
- const testMetrics = aggregateTestMetricsAcrossReports(allReports)
-
- const reportWithInsights: Report = {
- ...currentReport,
- results: {
- ...currentReport.results,
- tests: currentReport.results.tests.map(test => {
- const testName = test.name
- const metrics = testMetrics.get(testName)
-
- if (metrics) {
- const testInsights = calculateTestInsights(testName, metrics)
- return {
- ...test,
- insights: testInsights
- }
- }
-
- return test
- })
- }
- }
-
- return reportWithInsights
-}
-
-// ========================================
-// BASELINE INSIGHTS FUNCTIONS
-// ========================================
-
/**
* Calculates test-level insights with baseline comparison for a specific test.
- *
+ *
* @param testName - Name of the test
* @param currentTestMetrics - Current aggregated test metrics
* @param baselineTestMetrics - Baseline aggregated test metrics (optional)
@@ -624,64 +427,121 @@ function calculateTestInsightsWithBaseline(
currentTestMetrics: AggregatedTestMetrics,
baselineTestMetrics?: AggregatedTestMetrics
): TestInsights {
- const currentFlakyRate = currentTestMetrics.totalAttempts === 0 ? 0 :
- Number((currentTestMetrics.totalAttemptsFlaky / currentTestMetrics.totalAttempts).toFixed(4))
- const currentFailRate = currentTestMetrics.totalResults === 0 ? 0 :
- Number((currentTestMetrics.totalResultsFailed / currentTestMetrics.totalResults).toFixed(4))
- const currentSkippedRate = currentTestMetrics.totalResults === 0 ? 0 :
- Number((currentTestMetrics.totalResultsSkipped / currentTestMetrics.totalResults).toFixed(4))
- const currentAverageDuration = currentTestMetrics.totalResults === 0 ? 0 :
- Number((currentTestMetrics.totalResultsDuration / currentTestMetrics.totalResults).toFixed(2))
+ const currentPassRate =
+ currentTestMetrics.totalResults === 0
+ ? 0
+ : Number(
+ (
+ currentTestMetrics.totalResultsPassed /
+ currentTestMetrics.totalResults
+ ).toFixed(4)
+ )
+ const currentFlakyRate =
+ currentTestMetrics.totalAttempts === 0
+ ? 0
+ : Number(
+ (
+ currentTestMetrics.totalAttemptsFlaky /
+ currentTestMetrics.totalAttempts
+ ).toFixed(4)
+ )
+ const currentFailRate =
+ currentTestMetrics.totalResults === 0
+ ? 0
+ : Number(
+ (
+ currentTestMetrics.totalResultsFailed /
+ currentTestMetrics.totalResults
+ ).toFixed(4)
+ )
+ const currentAverageDuration =
+ currentTestMetrics.totalResults === 0
+ ? 0
+ : Number(
+ (
+ currentTestMetrics.totalResultsDuration /
+ currentTestMetrics.totalResults
+ ).toFixed(2)
+ )
const currentP95Duration = calculateP95(currentTestMetrics.durations)
+ let baselinePassRate = 0
let baselineFlakyRate = 0
let baselineFailRate = 0
- let baselineSkippedRate = 0
let baselineAverageDuration = 0
let baselineP95Duration = 0
if (baselineTestMetrics) {
- baselineFlakyRate = baselineTestMetrics.totalAttempts === 0 ? 0 :
- Number((baselineTestMetrics.totalAttemptsFlaky / baselineTestMetrics.totalAttempts).toFixed(4))
- baselineFailRate = baselineTestMetrics.totalResults === 0 ? 0 :
- Number((baselineTestMetrics.totalResultsFailed / baselineTestMetrics.totalResults).toFixed(4))
- baselineSkippedRate = baselineTestMetrics.totalResults === 0 ? 0 :
- Number((baselineTestMetrics.totalResultsSkipped / baselineTestMetrics.totalResults).toFixed(4))
- baselineAverageDuration = baselineTestMetrics.totalResults === 0 ? 0 :
- Number((baselineTestMetrics.totalResultsDuration / baselineTestMetrics.totalResults).toFixed(2))
+ baselinePassRate =
+ baselineTestMetrics.totalResults === 0
+ ? 0
+ : Number(
+ (
+ baselineTestMetrics.totalResultsPassed /
+ baselineTestMetrics.totalResults
+ ).toFixed(4)
+ )
+ baselineFlakyRate =
+ baselineTestMetrics.totalAttempts === 0
+ ? 0
+ : Number(
+ (
+ baselineTestMetrics.totalAttemptsFlaky /
+ baselineTestMetrics.totalAttempts
+ ).toFixed(4)
+ )
+ baselineFailRate =
+ baselineTestMetrics.totalResults === 0
+ ? 0
+ : Number(
+ (
+ baselineTestMetrics.totalResultsFailed /
+ baselineTestMetrics.totalResults
+ ).toFixed(4)
+ )
+ baselineAverageDuration =
+ baselineTestMetrics.totalResults === 0
+ ? 0
+ : Number(
+ (
+ baselineTestMetrics.totalResultsDuration /
+ baselineTestMetrics.totalResults
+ ).toFixed(2)
+ )
baselineP95Duration = calculateP95(baselineTestMetrics.durations)
}
- const { appearsInRuns, reportsAnalyzed, ...relevantMetrics } = currentTestMetrics
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ const { durations: _durations, ...relevantMetrics } = currentTestMetrics
return {
+ passRate: {
+ current: currentPassRate,
+ baseline: baselinePassRate,
+ change: Number((currentPassRate - baselinePassRate).toFixed(4)),
+ },
flakyRate: {
current: currentFlakyRate,
- previous: baselineFlakyRate,
- change: Number((currentFlakyRate - baselineFlakyRate).toFixed(4))
+ baseline: baselineFlakyRate,
+ change: Number((currentFlakyRate - baselineFlakyRate).toFixed(4)),
},
failRate: {
current: currentFailRate,
- previous: baselineFailRate,
- change: Number((currentFailRate - baselineFailRate).toFixed(4))
- },
- skippedRate: {
- current: currentSkippedRate,
- previous: baselineSkippedRate,
- change: Number((currentSkippedRate - baselineSkippedRate).toFixed(4))
+ baseline: baselineFailRate,
+ change: Number((currentFailRate - baselineFailRate).toFixed(4)),
},
averageTestDuration: {
current: currentAverageDuration,
- previous: baselineAverageDuration,
- change: Number((currentAverageDuration - baselineAverageDuration).toFixed(2))
+ baseline: baselineAverageDuration,
+ change: currentAverageDuration - baselineAverageDuration,
},
- p95Duration: {
+ p95TestDuration: {
current: currentP95Duration,
- previous: baselineP95Duration,
- change: Number((currentP95Duration - baselineP95Duration).toFixed(2))
+ baseline: baselineP95Duration,
+ change: currentP95Duration - baselineP95Duration,
},
- appearsInRuns: currentTestMetrics.appearsInRuns,
- extra: relevantMetrics
+ executedInRuns: currentTestMetrics.appearsInRuns,
+ extra: relevantMetrics,
}
}
@@ -707,13 +567,16 @@ function addTestInsightsWithBaselineToCurrentReport(
let baselineTestMetrics: Map | undefined
if (baselineReport && validateReportForInsights(baselineReport)) {
- const baselineIndex = previousReports.findIndex(report =>
- report.results?.summary?.start === baselineReport.results?.summary?.start
+ const baselineIndex = previousReports.findIndex(
+ report =>
+ report.results?.summary?.start ===
+ baselineReport.results?.summary?.start
)
-
+
if (baselineIndex >= 0) {
const reportsUpToBaseline = previousReports.slice(baselineIndex)
- baselineTestMetrics = aggregateTestMetricsAcrossReports(reportsUpToBaseline)
+ baselineTestMetrics =
+ aggregateTestMetricsAcrossReports(reportsUpToBaseline)
}
}
@@ -724,19 +587,23 @@ function addTestInsightsWithBaselineToCurrentReport(
tests: currentReport.results.tests.map(test => {
const testName = test.name
const currentMetrics = currentTestMetrics.get(testName)
-
+
if (currentMetrics) {
const baselineMetrics = baselineTestMetrics?.get(testName)
- const testInsights = calculateTestInsightsWithBaseline(testName, currentMetrics, baselineMetrics)
+ const testInsights = calculateTestInsightsWithBaseline(
+ testName,
+ currentMetrics,
+ baselineMetrics
+ )
return {
...test,
- insights: testInsights
+ insights: testInsights,
}
}
-
+
return test
- })
- }
+ }),
+ },
}
return reportWithInsights
@@ -763,33 +630,59 @@ function calculateReportInsightsBaseline(
}
return {
+ passRate: {
+ current: currentInsights?.passRate?.current ?? 0,
+ baseline: previousInsights?.passRate?.current ?? 0,
+ change: Number(
+ (
+ (currentInsights?.passRate?.current ?? 0) -
+ (previousInsights?.passRate?.current ?? 0)
+ ).toFixed(4)
+ ),
+ },
flakyRate: {
- current: currentInsights.flakyRate.current,
- previous: previousInsights.flakyRate.current,
- change: Number((currentInsights.flakyRate.current - previousInsights.flakyRate.current).toFixed(4))
+ current: currentInsights?.flakyRate?.current ?? 0,
+ baseline: previousInsights?.flakyRate?.current ?? 0,
+ change: Number(
+ (
+ (currentInsights?.flakyRate?.current ?? 0) -
+ (previousInsights?.flakyRate?.current ?? 0)
+ ).toFixed(4)
+ ),
},
failRate: {
- current: currentInsights.failRate.current,
- previous: previousInsights.failRate.current,
- change: Number((currentInsights.failRate.current - previousInsights.failRate.current).toFixed(4))
- },
- skippedRate: {
- current: currentInsights.skippedRate.current,
- previous: previousInsights.skippedRate.current,
- change: Number((currentInsights.skippedRate.current - previousInsights.skippedRate.current).toFixed(4))
+ current: currentInsights?.failRate?.current ?? 0,
+ baseline: previousInsights?.failRate?.current ?? 0,
+ change: Number(
+ (
+ (currentInsights?.failRate?.current ?? 0) -
+ (previousInsights?.failRate?.current ?? 0)
+ ).toFixed(4)
+ ),
},
averageTestDuration: {
- current: currentInsights.averageTestDuration.current,
- previous: previousInsights.averageTestDuration.current,
- change: Number((currentInsights.averageTestDuration.current - previousInsights.averageTestDuration.current).toFixed(2))
+ current: currentInsights?.averageTestDuration?.current ?? 0,
+ baseline: previousInsights?.averageTestDuration?.current ?? 0,
+ change:
+ (currentInsights?.averageTestDuration?.current ?? 0) -
+ (previousInsights?.averageTestDuration?.current ?? 0),
},
averageRunDuration: {
- current: currentInsights.averageRunDuration.current,
- previous: previousInsights.averageRunDuration.current,
- change: Number((currentInsights.averageRunDuration.current - previousInsights.averageRunDuration.current).toFixed(2))
+ current: currentInsights?.averageRunDuration?.current ?? 0,
+ baseline: previousInsights?.averageRunDuration?.current ?? 0,
+ change:
+ (currentInsights?.averageRunDuration?.current ?? 0) -
+ (previousInsights?.averageRunDuration?.current ?? 0),
+ },
+ p95RunDuration: {
+ current: currentInsights?.p95RunDuration?.current ?? 0,
+ baseline: previousInsights?.p95RunDuration?.current ?? 0,
+ change:
+ (currentInsights?.p95RunDuration?.current ?? 0) -
+ (previousInsights?.p95RunDuration?.current ?? 0),
},
- reportsAnalyzed: currentInsights.reportsAnalyzed,
- extra: currentInsights.extra
+ runsAnalyzed: currentInsights?.runsAnalyzed ?? 0,
+ extra: currentInsights.extra,
}
}
@@ -805,17 +698,24 @@ function getTestsRemovedSinceBaseline(
currentReport: Report,
baselineReport: Report
): SimplifiedTestData[] {
- if (!validateReportForInsights(currentReport) || !validateReportForInsights(baselineReport)) {
+ if (
+ !validateReportForInsights(currentReport) ||
+ !validateReportForInsights(baselineReport)
+ ) {
return []
}
- const currentTestNames = new Set(currentReport.results.tests.map(test => test.name))
- const removedTests = baselineReport.results.tests.filter(test => !currentTestNames.has(test.name))
+ const currentTestNames = new Set(
+ currentReport.results.tests.map(test => test.name)
+ )
+ const removedTests = baselineReport.results.tests.filter(
+ test => !currentTestNames.has(test.name)
+ )
return removedTests.map(test => ({
name: test.name,
suite: test.suite,
- filePath: test.filePath
+ filePath: test.filePath,
}))
}
@@ -828,20 +728,27 @@ function getTestsRemovedSinceBaseline(
* @returns Array of CtrfTest objects that were added since baseline
*/
function getTestsAddedSinceBaseline(
- currentReport: Report,
+ currentReport: Report,
baselineReport: Report
): SimplifiedTestData[] {
- if (!validateReportForInsights(currentReport) || !validateReportForInsights(baselineReport)) {
+ if (
+ !validateReportForInsights(currentReport) ||
+ !validateReportForInsights(baselineReport)
+ ) {
return []
}
- const baselineTestNames = new Set(baselineReport.results.tests.map(test => test.name))
- const addedTests = currentReport.results.tests.filter(test => !baselineTestNames.has(test.name))
+ const baselineTestNames = new Set(
+ baselineReport.results.tests.map(test => test.name)
+ )
+ const addedTests = currentReport.results.tests.filter(
+ test => !baselineTestNames.has(test.name)
+ )
return addedTests.map(test => ({
name: test.name,
suite: test.suite,
- filePath: test.filePath
+ filePath: test.filePath,
}))
}
@@ -859,14 +766,17 @@ function setTestsRemovedToInsights(
currentReport: Report,
baselineReport: Report
): Insights {
- const removedTests = getTestsRemovedSinceBaseline(currentReport, baselineReport)
-
+ const removedTests = getTestsRemovedSinceBaseline(
+ currentReport,
+ baselineReport
+ )
+
return {
...insights,
extra: {
...insights.extra,
- testsRemoved: removedTests
- }
+ testsRemoved: removedTests,
+ },
}
}
@@ -885,13 +795,13 @@ function setTestsAddedToInsights(
baselineReport: Report
): Insights {
const addedTests = getTestsAddedSinceBaseline(currentReport, baselineReport)
-
+
return {
...insights,
extra: {
...insights.extra,
- testsAdded: addedTests
- }
+ testsAdded: addedTests,
+ },
}
}
@@ -899,103 +809,66 @@ function setTestsAddedToInsights(
// MAIN CONSUMER API FUNCTION
// ========================================
-/**
- * Helper function to find the baseline report based on the baseline parameter.
- *
- * @param reportsWithRunInsights - Array of reports with run insights (current first, then previous)
- * @param baseline - Baseline specification (undefined, number, or string)
- * @returns The baseline report to use for comparison, or null if not found
- */
-function findBaselineReport(
- reportsWithRunInsights: Report[],
- baseline?: number | string
-): Report | null {
- if (baseline === undefined) {
- return reportsWithRunInsights[1] || null
- }
-
- if (typeof baseline === 'number') {
- const targetIndex = baseline + 1
- if (targetIndex < reportsWithRunInsights.length) {
- return reportsWithRunInsights[targetIndex]
- }
- console.warn(`Baseline index ${baseline} is out of range. Available previous reports: ${reportsWithRunInsights.length - 1}`)
- return null
- }
-
- if (typeof baseline === 'string') {
- const report = reportsWithRunInsights.find(
- report => report.results?.summary?.start?.toString() === baseline
- )
- if (!report) {
- console.warn(`No report found with start timestamp ID: ${baseline}`)
- return null
- }
- return report
- }
-
- return null
-}
-
/**
* @param currentReport - The current CTRF report to enrich
- * @param previousReports - Array of historical CTRF reports (ordered newest to oldest)
- * @param baseline - Optional baseline specification:
- * - undefined: Use most recent previous report (default)
- * - number: Use report at this index in previousReports array (0 = most recent)
- * - string: Use reportId
- * @returns The current report fully enriched with run-level insights, test-level insights, and baseline comparisons
+ * @param previousReports - Array of historical CTRF reports
+ * @param baseline - Optional baseline report to compare against. If not provided, no baseline comparisons are made.
+ * @returns The current report fully enriched with run-level insights, test-level insights, and baseline comparisons (if baseline provided)
*/
export function enrichReportWithInsights(
- currentReport: Report,
+ currentReport: Report,
previousReports: Report[] = [],
- baseline?: number | string
+ baseline?: Report
): Report {
if (!validateReportForInsights(currentReport)) {
console.warn('Current report is not valid for insights calculation')
return currentReport
}
- const allReports = [currentReport, ...previousReports]
+ const sortedPreviousReports = sortReportsByTimestamp(previousReports)
+
+ const allReports = [currentReport, ...sortedPreviousReports]
const reportsWithRunInsights = calculateRunInsights([...allReports])
-
- const baselineReport = previousReports.length > 0 ?
- findBaselineReport(reportsWithRunInsights, baseline) : null
-
- const currentReportWithRunInsights = reportsWithRunInsights[0] // Current report is first
- const currentReportWithTestInsights = addTestInsightsWithBaselineToCurrentReport(
- currentReportWithRunInsights,
- previousReports,
- baselineReport || undefined
- )
- if (previousReports.length === 0) {
- return currentReportWithTestInsights
- }
+ const currentReportWithRunInsights = reportsWithRunInsights[0]
+ const currentReportWithTestInsights =
+ addTestInsightsWithBaselineToCurrentReport(
+ currentReportWithRunInsights,
+ sortedPreviousReports,
+ baseline
+ )
- if (!baselineReport) {
+ if (!baseline) {
return currentReportWithTestInsights
}
-
+
let baselineInsights = calculateReportInsightsBaseline(
currentReportWithTestInsights,
- baselineReport
+ baseline
)
baselineInsights = setTestsAddedToInsights(
baselineInsights,
currentReportWithTestInsights,
- baselineReport
+ baseline
)
-
+
baselineInsights = setTestsRemovedToInsights(
baselineInsights,
currentReportWithTestInsights,
- baselineReport
+ baseline
)
+ // Remove testsAdded and testsRemoved as they're not part of the official schema yet
+ if (baselineInsights.extra?.testsAdded) {
+ delete baselineInsights.extra.testsAdded
+ }
+ if (baselineInsights.extra?.testsRemoved) {
+ delete baselineInsights.extra.testsRemoved
+ }
+
return {
...currentReportWithTestInsights,
- insights: baselineInsights
+ insights: baselineInsights,
}
-}
\ No newline at end of file
+}
diff --git a/src/methods/store-previous-results.ts b/src/methods/store-previous-results.ts
index a0fdf31..1d68f93 100644
--- a/src/methods/store-previous-results.ts
+++ b/src/methods/store-previous-results.ts
@@ -1,67 +1,72 @@
// This should be added to library, as not standard CTRF thing
-import { Environment, Report } from '../../types/ctrf.js';
+import { Environment, Report } from '../../types/ctrf.js'
/**
* Interface for a previous result entry stored in the current report
*/
interface PreviousResult {
- start: number;
- stop: number;
- buildId?: string;
+ start: number
+ stop: number
+ buildId?: string
buildName?: string
- buildNumber?: string
+ buildNumber?: number
buildUrl?: string
- result: string;
- tests: number;
- passed: number;
- failed: number;
- skipped: number;
- flaky: number;
- other: number;
- duration: number;
- environment?: Environment;
+ result: string
+ tests: number
+ passed: number
+ failed: number
+ skipped: number
+ flaky: number
+ other: number
+ duration: number
+ environment?: Environment
}
/**
* Stores previous results in the current report's previousResults array.
* Extracts key metrics from each previous report and adds them to the current report.
- *
+ *
* @param currentReport The current CTRF report to enrich with previous results
* @param previousReports Array of previous CTRF reports to extract metrics from
* @returns The current report with previousResults populated
*/
export function storePreviousResults(
- currentReport: Report,
+ currentReport: Report,
previousReports: Report[]
): Report {
if (!currentReport || !Array.isArray(previousReports)) {
- throw new Error('Invalid input: currentReport must be a valid CTRF report and previousReports must be an array');
+ throw new Error(
+ 'Invalid input: currentReport must be a valid CTRF report and previousReports must be an array'
+ )
}
if (!currentReport.extra) {
- currentReport.extra = {};
+ currentReport.extra = {}
}
- const previousResults: PreviousResult[] = previousReports.map((report) => {
+ const previousResults: PreviousResult[] = previousReports.map(report => {
if (!report.results || !report.results.summary) {
- throw new Error('Invalid previous report: missing results or summary');
+ throw new Error('Invalid previous report: missing results or summary')
}
- const summary = report.results.summary;
- const tests = report.results.tests || [];
-
- const flakyCount = tests.filter(test => test.flaky === true).length;
-
- const duration = summary.stop - summary.start;
-
- let result = 'passed';
+ const summary = report.results.summary
+ const tests = report.results.tests || []
+
+ const flakyCount = tests.filter(test => test.flaky === true).length
+
+ const duration = summary.stop - summary.start
+
+ let result = 'passed'
if (summary.failed > 0) {
- result = 'failed';
- } else if ((summary.skipped > 0 || summary.pending > 0 || summary.other > 0) && summary.passed === 0) {
- result = 'skipped';
+ result = 'failed'
+ } else if (
+ (summary.skipped > 0 || summary.pending > 0 || summary.other > 0) &&
+ summary.passed === 0
+ ) {
+ result = 'skipped'
} else if (summary.tests === 0) {
- result = 'empty';
+ result = 'empty'
}
return {
@@ -79,13 +84,13 @@ export function storePreviousResults(
flaky: flakyCount,
other: summary.other,
duration,
- environment: report.results.environment
- };
- });
+ environment: report.results.environment,
+ }
+ })
- previousResults.sort((a, b) => a.start - b.start);
+ previousResults.sort((a, b) => a.start - b.start)
- currentReport.extra.previousResults = previousResults;
+ currentReport.extra.previousResults = previousResults
- return currentReport;
+ return currentReport
}
diff --git a/src/methods/utilities/sort-reports.ts b/src/methods/utilities/sort-reports.ts
new file mode 100644
index 0000000..58b0c19
--- /dev/null
+++ b/src/methods/utilities/sort-reports.ts
@@ -0,0 +1,54 @@
+import { Report } from '../../../types/ctrf'
+
+/**
+ * Sort order options for timestamp-based sorting.
+ */
+export enum SortOrder {
+ ASC = 'asc',
+ DESC = 'desc',
+}
+
+/**
+ * Sorts CTRF reports by their timestamp.
+ *
+ * This function uses a fallback strategy for timestamp selection:
+ * 1. First tries to use `report.timestamp` if available
+ * 2. Falls back to `report.results.summary.stop` if `timestamp` is not available
+ * 3. Reports without any timestamp are sorted to the end of the array
+ *
+ * @param reports - Array of CTRF reports to sort
+ * @param order - Sort order: SortOrder.DESC for newest first (default), SortOrder.ASC for oldest first
+ * @returns A new array with reports sorted by timestamp
+ *
+ * @example
+ * ```typescript
+ * const unsortedReports = [report1, report2, report3];
+ *
+ * const newestFirst = sortReportsByTimestamp(unsortedReports);
+ * // newestFirst[0] will be the most recent report
+ *
+ * const oldestFirst = sortReportsByTimestamp(unsortedReports, SortOrder.ASC);
+ * // oldestFirst[0] will be the oldest report
+ *
+
+ * const newestFirst = sortReportsByTimestamp(unsortedReports, SortOrder.DESC);
+ * ```
+ *
+ */
+export function sortReportsByTimestamp(
+ reports: Report[],
+ order: SortOrder = SortOrder.DESC
+): Report[] {
+ return [...reports].sort((a, b) => {
+ const aTimestamp = a.timestamp || a.results?.summary?.stop
+ const bTimestamp = b.timestamp || b.results?.summary?.stop
+
+ if (!aTimestamp && !bTimestamp) return 0
+ if (!aTimestamp) return 1
+ if (!bTimestamp) return -1
+
+ const timeDiff =
+ new Date(bTimestamp).getTime() - new Date(aTimestamp).getTime()
+ return order === SortOrder.ASC ? -timeDiff : timeDiff
+ })
+}
diff --git a/src/__tests__/test-helpers/report-enrichment-helper.ts b/src/test-utils/report-enrichment-helper.ts
similarity index 64%
rename from src/__tests__/test-helpers/report-enrichment-helper.ts
rename to src/test-utils/report-enrichment-helper.ts
index 875a576..99eb672 100644
--- a/src/__tests__/test-helpers/report-enrichment-helper.ts
+++ b/src/test-utils/report-enrichment-helper.ts
@@ -1,9 +1,12 @@
import * as fs from 'fs'
import * as path from 'path'
import * as os from 'os'
-import { enrichReportsWithInsights, EnrichmentConfig } from '../../../scripts/enrich-reports'
-import { Report, Test } from '../../../types/ctrf.js'
-import { CTRF_REPORT_FORMAT, CTRF_SPEC_VERSION } from '../../constants'
+import {
+ enrichReportsWithInsights,
+ EnrichmentConfig,
+} from '../../scripts/enrich-reports'
+import { Report, Test } from '../../types/ctrf.js'
+import { CTRF_REPORT_FORMAT, CTRF_SPEC_VERSION } from '../constants'
/**
* Test helper for creating and testing report enrichment scenarios
@@ -25,7 +28,7 @@ export class ReportEnrichmentTestHelper {
name: 'test-name',
status: 'passed',
duration: 100,
- ...overrides
+ ...overrides,
}
}
@@ -48,12 +51,16 @@ export class ReportEnrichmentTestHelper {
failed: tests.filter(t => t.status === 'failed').length,
skipped: tests.filter(t => t.status === 'skipped').length,
pending: tests.filter(t => t.status === 'pending').length,
- other: tests.filter(t => !['passed', 'failed', 'skipped', 'pending'].includes(t.status)).length,
+ other: tests.filter(
+ t => !['passed', 'failed', 'skipped', 'pending'].includes(t.status)
+ ).length,
+ flaky: tests.filter(t => t.flaky === true).length,
+ duration: tests.reduce((sum, t) => sum + t.duration, 0),
start: startTime,
- stop: startTime + 5000
+ stop: startTime + 5000,
},
- tests
- }
+ tests,
+ },
}
}
@@ -61,7 +68,10 @@ export class ReportEnrichmentTestHelper {
* Add a report to the test scenario
*/
addReport(report: Report, filename?: string): string {
- const reportPath = path.join(this.tempDir, filename || `report-${this.reportPaths.length + 1}.json`)
+ const reportPath = path.join(
+ this.tempDir,
+ filename || `report-${this.reportPaths.length + 1}.json`
+ )
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2))
this.reportPaths.push(reportPath)
return reportPath
@@ -70,14 +80,17 @@ export class ReportEnrichmentTestHelper {
/**
* Add multiple reports with timestamps spaced apart
*/
- addReportsWithTimestamps(reportsData: Array<{ tests: Test[], toolName?: string }>, intervalMs: number = 10000): string[] {
+ addReportsWithTimestamps(
+ reportsData: Array<{ tests: Test[]; toolName?: string }>,
+ intervalMs: number = 10000
+ ): string[] {
const baseTime = Date.now()
const paths: string[] = []
reportsData.forEach((reportData, index) => {
const report = this.createMockReport(
reportData.tests,
- baseTime - (index * intervalMs), // Earlier reports have smaller timestamps
+ baseTime - index * intervalMs, // Earlier reports have smaller timestamps
reportData.toolName
)
const path = this.addReport(report, `report-${index + 1}.json`)
@@ -96,33 +109,73 @@ export class ReportEnrichmentTestHelper {
reportPaths: string[]
} {
const currentTests = [
- this.createMockTest({ name: 'stable-test', status: 'passed', duration: 100 }),
- this.createMockTest({ name: 'flaky-test', status: 'passed', retries: 2, flaky: true, duration: 150 }),
- this.createMockTest({ name: 'failing-test', status: 'failed', duration: 200 })
+ this.createMockTest({
+ name: 'stable-test',
+ status: 'passed',
+ duration: 100,
+ }),
+ this.createMockTest({
+ name: 'flaky-test',
+ status: 'passed',
+ retries: 2,
+ flaky: true,
+ duration: 150,
+ }),
+ this.createMockTest({
+ name: 'failing-test',
+ status: 'failed',
+ duration: 200,
+ }),
]
const previousTests1 = [
- this.createMockTest({ name: 'stable-test', status: 'passed', duration: 95 }),
- this.createMockTest({ name: 'flaky-test', status: 'failed', duration: 180 }),
- this.createMockTest({ name: 'failing-test', status: 'passed', duration: 190 })
+ this.createMockTest({
+ name: 'stable-test',
+ status: 'passed',
+ duration: 95,
+ }),
+ this.createMockTest({
+ name: 'flaky-test',
+ status: 'failed',
+ duration: 180,
+ }),
+ this.createMockTest({
+ name: 'failing-test',
+ status: 'passed',
+ duration: 190,
+ }),
]
const previousTests2 = [
- this.createMockTest({ name: 'stable-test', status: 'passed', duration: 105 }),
- this.createMockTest({ name: 'flaky-test', status: 'passed', retries: 1, flaky: true, duration: 160 }),
- this.createMockTest({ name: 'failing-test', status: 'failed', duration: 210 })
+ this.createMockTest({
+ name: 'stable-test',
+ status: 'passed',
+ duration: 105,
+ }),
+ this.createMockTest({
+ name: 'flaky-test',
+ status: 'passed',
+ retries: 1,
+ flaky: true,
+ duration: 160,
+ }),
+ this.createMockTest({
+ name: 'failing-test',
+ status: 'failed',
+ duration: 210,
+ }),
]
const reportPaths = this.addReportsWithTimestamps([
{ tests: currentTests },
{ tests: previousTests1 },
- { tests: previousTests2 }
+ { tests: previousTests2 },
])
const currentReport = this.createMockReport(currentTests)
const previousReports = [
this.createMockReport(previousTests1, Date.now() - 10000),
- this.createMockReport(previousTests2, Date.now() - 20000)
+ this.createMockReport(previousTests2, Date.now() - 20000),
]
return { currentReport, previousReports, reportPaths }
@@ -131,11 +184,14 @@ export class ReportEnrichmentTestHelper {
/**
* Run enrichment on the collected reports
*/
- async enrichReports(outputFilename: string = 'enriched-report.json', verbose: boolean = false): Promise {
+ async enrichReports(
+ outputFilename: string = 'enriched-report.json',
+ verbose: boolean = false
+ ): Promise {
const config: EnrichmentConfig = {
inputReports: this.reportPaths,
outputPath: path.join(this.tempDir, outputFilename),
- verbose
+ verbose,
}
return await enrichReportsWithInsights(config)
@@ -187,7 +243,7 @@ export async function testReportEnrichment(
outputPath?: string
): Promise {
const helper = new ReportEnrichmentTestHelper()
-
+
try {
// Add all reports
reports.forEach((report, index) => {
@@ -196,9 +252,9 @@ export async function testReportEnrichment(
// Run enrichment
const result = await helper.enrichReports(outputPath, false)
-
+
return result
} finally {
helper.cleanup()
}
-}
\ No newline at end of file
+}
diff --git a/tsconfig.json b/tsconfig.json
index 4f317f4..005ab5c 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -2,7 +2,7 @@
"compilerOptions": {
"target": "ES2023",
"module": "ESNext",
- "moduleResolution": "node",
+ "moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
@@ -14,11 +14,10 @@
},
"include": ["src/**/*"],
"exclude": [
- "examples/**/*",
- "scripts/**/*",
- "final/**/*",
"src/__tests__/**/*",
"dist/**/*",
- "node_modules/**/*"
+ "node_modules/**/*",
+ "src/test-utils/**/*",
+ "scripts/**/*"
]
}
diff --git a/tsconfig.test.json b/tsconfig.test.json
new file mode 100644
index 0000000..d318266
--- /dev/null
+++ b/tsconfig.test.json
@@ -0,0 +1,11 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "types": ["vitest/globals", "node"],
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": false,
+ "noEmit": true
+ },
+ "include": ["src/**/*"],
+ "exclude": ["dist/**/*", "node_modules/**/*"]
+}
diff --git a/typedoc.json b/typedoc.json
index 5fa0a21..633d598 100644
--- a/typedoc.json
+++ b/typedoc.json
@@ -1,20 +1,17 @@
{
"entryPoints": ["src/index.ts"],
"out": "docs",
- "exclude": [
- "src/__tests__/**/*",
- "src/**/*.test.ts",
- "src/**/*.spec.ts"
- ],
+ "exclude": ["src/__tests__/**/*", "src/**/*.test.ts", "src/**/*.spec.ts"],
"excludePrivate": true,
"excludeProtected": true,
"excludeExternals": true,
"includeVersion": true,
"categorizeByGroup": true,
- "categoryOrder": ["Core", "Methods", "*"],
- "readme": "README.md",
- "theme": "default",
- "name": "CTRF JavaScript Common Library",
+ "categoryOrder": ["Methods", "*"],
+ "readme": "none",
+ "plugin": ["typedoc-plugin-markdown"],
+ "name": "CTRF ",
"githubPages": false,
- "gitRevision": "main"
-}
\ No newline at end of file
+ "gitRevision": "main",
+ "cleanOutputDir": true
+}
diff --git a/types/ctrf.d.ts b/types/ctrf.d.ts
index 2ad45a2..cfebc82 100644
--- a/types/ctrf.d.ts
+++ b/types/ctrf.d.ts
@@ -1,11 +1,12 @@
export interface Report {
- reportFormat: string
- specVersion: string
+ reportFormat: 'CTRF'
+ specVersion: `${number}.${number}.${number}`
reportId?: string
- timestamp?: number
+ timestamp?: string
generatedBy?: string
results: Results
insights?: Insights
+ baseline?: Baseline
extra?: Record
}
@@ -24,16 +25,18 @@ export interface Summary {
skipped: number
pending: number
other: number
+ flaky?: number
suites?: number
start: number
stop: number
+ duration?: number
extra?: Record
}
export interface Test {
id?: string
name: string
- status: TestState
+ status: TestStatus
duration: number
start?: number
stop?: number
@@ -48,12 +51,12 @@ export interface Test {
type?: string
filePath?: string
retries?: number
+ retryAttempts?: RetryAttempt[]
flaky?: boolean
stdout?: string[]
stderr?: string[]
threadId?: string
attachments?: Attachment[]
- retryAttempts?: RetryAttempts[]
browser?: string
device?: string
screenshot?: string
@@ -67,17 +70,17 @@ export interface Environment {
reportName?: string
appName?: string
appVersion?: string
- osPlatform?: string
- osRelease?: string
- osVersion?: string
buildId?: string
buildName?: string
- buildNumber?: string
+ buildNumber?: number
buildUrl?: string
repositoryName?: string
repositoryUrl?: string
commit?: string
branchName?: string
+ osPlatform?: string
+ osRelease?: string
+ osVersion?: string
testEnvironment?: string
extra?: Record
}
@@ -90,7 +93,7 @@ export interface Tool {
export interface Step {
name: string
- status: TestState
+ status: TestStatus
extra?: Record
}
@@ -98,54 +101,61 @@ export interface Attachment {
name: string
contentType: string
path: string
+ extra?: Record
}
-export interface RetryAttempts {
- retry: number;
- status: TestState;
- rawStatus?: string;
- duration?: number;
- message?: string;
- trace?: string;
- snippet?: string;
- line?: number;
- stdout?: string[];
- stderr?: string[];
- start?: number;
- stop?: number;
- attachments?: Attachment[];
- extra?: Record;
+export interface RetryAttempt {
+ attempt: number
+ status: TestStatus
+ duration?: number
+ message?: string
+ trace?: string
+ line?: number
+ snippet?: string
+ stdout?: string[]
+ stderr?: string[]
+ start?: number
+ stop?: number
+ attachments?: Attachment[]
+ extra?: Record
}
export interface Insights {
- flakyRate: InsightsMetric
- failRate: InsightsMetric
- skippedRate: InsightsMetric
- averageTestDuration: InsightsMetric
- averageRunDuration: InsightsMetric
- reportsAnalyzed: number
+ runsAnalyzed?: number
+ passRate?: InsightsMetric
+ failRate?: InsightsMetric
+ flakyRate?: InsightsMetric
+ averageRunDuration?: InsightsMetric
+ p95RunDuration?: InsightsMetric
+ averageTestDuration?: InsightsMetric
extra?: Record
}
export interface TestInsights {
- flakyRate: InsightsMetric
- failRate: InsightsMetric
- skippedRate: InsightsMetric
- averageTestDuration: InsightsMetric
- p95Duration: InsightsMetric
- appearsInRuns: number
+ passRate?: InsightsMetric
+ failRate?: InsightsMetric
+ flakyRate?: InsightsMetric
+ averageTestDuration?: InsightsMetric
+ p95TestDuration?: InsightsMetric
+ executedInRuns?: number
extra?: Record
}
export interface InsightsMetric {
current: number
- previous: number
+ baseline: number
change: number
}
-export type TestState =
- | 'passed'
- | 'failed'
- | 'skipped'
- | 'pending'
- | 'other'
+export interface Baseline {
+ reportId: string
+ source?: string
+ timestamp?: string
+ commit?: string
+ buildName?: string
+ buildNumber?: number
+ buildUrl?: string
+ extra?: Record
+}
+
+export type TestStatus = 'passed' | 'failed' | 'skipped' | 'pending' | 'other'
diff --git a/vitest.config.ts b/vitest.config.ts
new file mode 100644
index 0000000..4ccca2f
--- /dev/null
+++ b/vitest.config.ts
@@ -0,0 +1,25 @@
+import { defineConfig } from 'vitest/config'
+
+export default defineConfig({
+ test: {
+ reporters: ['default', '@d2t/vitest-ctrf-json-reporter'],
+ coverage: {
+ provider: 'v8',
+ reporter: ['text', 'json', 'html'],
+ exclude: [
+ 'node_modules/',
+ 'dist/',
+ 'coverage/',
+ '**/*.d.ts',
+ '**/*.test.ts',
+ '**/*.spec.ts',
+ 'src/test-utils/**',
+ 'ctrf/',
+ ],
+ },
+ environment: 'node',
+ globals: false,
+ include: ['src/**/*.{test,spec}.{js,ts}'],
+ exclude: ['node_modules/', 'dist/', 'coverage/', 'src/test-utils/**'],
+ },
+})