From 86ba26b754257dbf1b107fe2d6c6a723e3f9e508 Mon Sep 17 00:00:00 2001 From: Adil Date: Sun, 15 Jun 2025 23:01:49 +0500 Subject: [PATCH 01/30] feat(cli): add pipe support and improve data handling --- src/cli.ts | 129 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 97 insertions(+), 32 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index 5f1a9e7..dd6d67a 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -1,3 +1,5 @@ +#!/usr/bin/env node + import * as path from 'path'; import * as fs from 'fs'; import { program } from 'commander'; @@ -6,46 +8,109 @@ import { OHLCV, IOHLCV } from './types'; program .description('Resample OHLCV between timeframes and file formats') - .option('-i, --input ', 'Input file path (csv, json)') - .option('-n, --name ', 'Output file name') - .option('-f, --format ', 'Output file format (csv, json)') - .option('-p, --placeholder', '') - ; + .option('-i, --input ', 'Input file path (csv, json) or use pipe') + .option('-o, --output ', 'Output file path (csv, json) or use pipe') + .option('-f, --format ', 'Output file format (csv, json)', 'csv') + .version('1.2.1'); program.parse(); program.showHelpAfterError(); const options = program.opts(); -(() => { - - const inFormat = path.extname(options.input).slice(1).toLowerCase(); - const inPath = path.resolve(options.input); +async function processInput(input: string | NodeJS.ReadableStream): Promise { + if (typeof input === 'string') { + const inFormat = path.extname(input).slice(1).toLowerCase(); + if (!['csv', 'json'].includes(inFormat)) { + throw new Error('Only CSV and JSON files are accepted as input'); + } - if (!['csv', 'json'].includes(inFormat)) { - program.error('Only CSV and JSON files are accepted as input'); - return; + const inPath = path.resolve(input); + const inBuffer = fs.readFileSync(inPath); + + if (inFormat === 'csv') { + return new Promise((resolve, reject) => { + const results: IOHLCV[] = []; + fs.createReadStream(inPath) + .pipe(csv.parse({ headers: true })) + .on('data', (row) => { + results.push({ + time: Number(row.time), + open: Number(row.open), + high: Number(row.high), + low: Number(row.low), + close: Number(row.close), + volume: Number(row.volume) + }); + }) + .on('end', () => resolve(results)) + .on('error', reject); + }); + } else { + return JSON.parse(inBuffer.toString()); + } + } else { + // Handle pipe input + return new Promise((resolve, reject) => { + const results: IOHLCV[] = []; + input + .pipe(csv.parse({ headers: true })) + .on('data', (row) => { + results.push({ + time: Number(row.time), + open: Number(row.open), + high: Number(row.high), + low: Number(row.low), + close: Number(row.close), + volume: Number(row.volume) + }); + }) + .on('end', () => resolve(results)) + .on('error', reject); + }); } +} - const inBuffer = fs.readFileSync(inPath); - const inStream = fs.createReadStream(inPath, { - start: 0 - }); - - if (inFormat === 'csv') { - csv.parseStream(inStream) - .on('data', (row) => { - console.log(row); - }) - .end(() => { - console.log("end"); - }); +async function main() { + try { + let input: string | NodeJS.ReadableStream; + + if (process.stdin.isTTY) { + // Read from file + if (!options.input) { + program.error('Input file is required when not using pipe'); + return; + } + input = options.input; + } else { + // Read from pipe + input = process.stdin; + } - // const data = inStream - // .pipe(csv.parse({ headers: true })); - } - if (inFormat === 'json') { - //@ts-ignore - const data: IOHLCV[] = JSON.parse(inBuffer); + const data = await processInput(input); + + // TODO: Process data (resample) + + // Output handling + if (options.output) { + const outStream = fs.createWriteStream(options.output); + if (options.format === 'csv') { + csv.write(data, { headers: true }).pipe(outStream); + } else { + outStream.write(JSON.stringify(data, null, 2)); + } + } else { + // Output to stdout + if (options.format === 'csv') { + csv.write(data, { headers: true }).pipe(process.stdout); + } else { + console.log(JSON.stringify(data, null, 2)); + } + } + } catch (error: unknown) { + console.error('Error:', error instanceof Error ? error.message : String(error)); + process.exit(1); } -})(); \ No newline at end of file +} + +main(); \ No newline at end of file From d8e0f4dad1d5e1a513fec89450076fc16d32ded9 Mon Sep 17 00:00:00 2001 From: Adil Date: Sun, 15 Jun 2025 23:07:13 +0500 Subject: [PATCH 02/30] test(cli): add comprehensive test cases for CLI functionality --- __tests__/cli.ts | 150 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 __tests__/cli.ts diff --git a/__tests__/cli.ts b/__tests__/cli.ts new file mode 100644 index 0000000..e66705a --- /dev/null +++ b/__tests__/cli.ts @@ -0,0 +1,150 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { exec } from 'child_process'; +import { promisify } from 'util'; + +const execAsync = promisify(exec); + +describe('CLI', () => { + const cliPath = path.resolve(__dirname, '../dist/cli.js'); + const testDataDir = path.resolve(__dirname, 'fixtures'); + + // Create test data directory if it doesn't exist + if (!fs.existsSync(testDataDir)) { + fs.mkdirSync(testDataDir); + } + + // Sample OHLCV data + const sampleData = [ + { time: 1609459200000, open: 100, high: 105, low: 95, close: 102, volume: 1000 }, + { time: 1609462800000, open: 102, high: 107, low: 101, close: 106, volume: 1200 }, + { time: 1609466400000, open: 106, high: 108, low: 104, close: 105, volume: 800 } + ]; + + // Create test files + const csvFile = path.join(testDataDir, 'test.csv'); + const jsonFile = path.join(testDataDir, 'test.json'); + + beforeAll(() => { + // Write test data to files + fs.writeFileSync(csvFile, 'time,open,high,low,close,volume\n' + + sampleData.map(row => Object.values(row).join(',')).join('\n')); + fs.writeFileSync(jsonFile, JSON.stringify(sampleData, null, 2)); + }); + + afterAll(() => { + // Clean up test files + fs.unlinkSync(csvFile); + fs.unlinkSync(jsonFile); + fs.rmdirSync(testDataDir); + }); + + describe('File Input', () => { + test('should read CSV file', async () => { + const { stdout } = await execAsync(`node ${cliPath} -i ${csvFile}`); + const output = JSON.parse(stdout); + expect(output).toHaveLength(3); + expect(output[0]).toHaveProperty('time', 1609459200000); + }); + + test('should read JSON file', async () => { + const { stdout } = await execAsync(`node ${cliPath} -i ${jsonFile}`); + const output = JSON.parse(stdout); + expect(output).toHaveLength(3); + expect(output[0]).toHaveProperty('time', 1609459200000); + }); + + test('should handle invalid file format', async () => { + const invalidFile = path.join(testDataDir, 'test.txt'); + fs.writeFileSync(invalidFile, 'invalid data'); + + try { + await execAsync(`node ${cliPath} -i ${invalidFile}`); + fail('Should have thrown an error'); + } catch (error) { + expect(error.message).toContain('Only CSV and JSON files are accepted'); + } + + fs.unlinkSync(invalidFile); + }); + }); + + describe('Pipe Input', () => { + test('should read from pipe', async () => { + const { stdout } = await execAsync(`cat ${csvFile} | node ${cliPath}`); + const output = JSON.parse(stdout); + expect(output).toHaveLength(3); + expect(output[0]).toHaveProperty('time', 1609459200000); + }); + }); + + describe('Output Format', () => { + const outputFile = path.join(testDataDir, 'output'); + + afterEach(() => { + if (fs.existsSync(outputFile)) { + fs.unlinkSync(outputFile); + } + }); + + test('should write CSV output', async () => { + await execAsync(`node ${cliPath} -i ${jsonFile} -o ${outputFile} -f csv`); + const content = fs.readFileSync(outputFile, 'utf8'); + expect(content).toContain('time,open,high,low,close,volume'); + expect(content.split('\n')).toHaveLength(4); // header + 3 rows + }); + + test('should write JSON output', async () => { + await execAsync(`node ${cliPath} -i ${csvFile} -o ${outputFile} -f json`); + const content = JSON.parse(fs.readFileSync(outputFile, 'utf8')); + expect(content).toHaveLength(3); + expect(content[0]).toHaveProperty('time', 1609459200000); + }); + + test('should write to stdout when no output file specified', async () => { + const { stdout } = await execAsync(`node ${cliPath} -i ${jsonFile}`); + const output = JSON.parse(stdout); + expect(output).toHaveLength(3); + expect(output[0]).toHaveProperty('time', 1609459200000); + }); + }); + + describe('Error Handling', () => { + test('should handle missing input file', async () => { + try { + await execAsync(`node ${cliPath} -i nonexistent.csv`); + fail('Should have thrown an error'); + } catch (error) { + expect(error.message).toContain('no such file or directory'); + } + }); + + test('should handle invalid JSON', async () => { + const invalidJsonFile = path.join(testDataDir, 'invalid.json'); + fs.writeFileSync(invalidJsonFile, '{invalid json'); + + try { + await execAsync(`node ${cliPath} -i ${invalidJsonFile}`); + fail('Should have thrown an error'); + } catch (error) { + expect(error.message).toContain('Unexpected token'); + } + + fs.unlinkSync(invalidJsonFile); + }); + + test('should handle invalid CSV', async () => { + const invalidCsvFile = path.join(testDataDir, 'invalid.csv'); + fs.writeFileSync(invalidCsvFile, 'invalid,csv,data\n1,2,3'); + + try { + await execAsync(`node ${cliPath} -i ${invalidCsvFile}`); + fail('Should have thrown an error'); + } catch (error) { + expect(error.message).toContain('Error'); + } + + fs.unlinkSync(invalidCsvFile); + }); + }); +}); \ No newline at end of file From 7c91fc35a2113fd90c2bbbd0a0e419720791dfb6 Mon Sep 17 00:00:00 2001 From: Adil Date: Sun, 15 Jun 2025 23:09:21 +0500 Subject: [PATCH 03/30] feat(cli): integrate resampling functionality --- __tests__/cli.ts | 38 ++++++++++++++++++++++++++++++++++++++ src/cli.ts | 25 ++++++++++++++++++++----- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/__tests__/cli.ts b/__tests__/cli.ts index e66705a..6244a95 100644 --- a/__tests__/cli.ts +++ b/__tests__/cli.ts @@ -147,4 +147,42 @@ describe('CLI', () => { fs.unlinkSync(invalidCsvFile); }); }); + + describe('Resampling', () => { + test('should resample data with default timeframes', async () => { + const { stdout } = await execAsync(`node ${cliPath} -i ${csvFile}`); + const output = JSON.parse(stdout); + expect(output).toHaveLength(1); // 3 minutes of 1-minute data resampled to 5 minutes + expect(output[0]).toHaveProperty('time'); + expect(output[0]).toHaveProperty('open'); + expect(output[0]).toHaveProperty('high'); + expect(output[0]).toHaveProperty('low'); + expect(output[0]).toHaveProperty('close'); + expect(output[0]).toHaveProperty('volume'); + }); + + test('should resample data with custom timeframes', async () => { + const { stdout } = await execAsync(`node ${cliPath} -i ${csvFile} -b 60 -n 120`); + const output = JSON.parse(stdout); + expect(output).toHaveLength(2); // 3 minutes of 1-minute data resampled to 2 minutes + }); + + test('should handle invalid timeframe values', async () => { + try { + await execAsync(`node ${cliPath} -i ${csvFile} -b invalid -n 300`); + fail('Should have thrown an error'); + } catch (error) { + expect(error.message).toContain('Timeframes must be valid numbers'); + } + }); + + test('should handle invalid timeframe relationship', async () => { + try { + await execAsync(`node ${cliPath} -i ${csvFile} -b 300 -n 60`); + fail('Should have thrown an error'); + } catch (error) { + expect(error.message).toContain('New timeframe must be greater than base timeframe'); + } + }); + }); }); \ No newline at end of file diff --git a/src/cli.ts b/src/cli.ts index dd6d67a..b28c8af 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -5,12 +5,15 @@ import * as fs from 'fs'; import { program } from 'commander'; import * as csv from 'fast-csv'; import { OHLCV, IOHLCV } from './types'; +import { resampleOhlcv } from './lib'; program .description('Resample OHLCV between timeframes and file formats') .option('-i, --input ', 'Input file path (csv, json) or use pipe') .option('-o, --output ', 'Output file path (csv, json) or use pipe') .option('-f, --format ', 'Output file format (csv, json)', 'csv') + .option('-b, --base-timeframe ', 'Base timeframe in seconds', '60') + .option('-n, --new-timeframe ', 'New timeframe in seconds', '300') .version('1.2.1'); program.parse(); @@ -89,22 +92,34 @@ async function main() { const data = await processInput(input); - // TODO: Process data (resample) + // Resample the data + const baseTimeframe = parseInt(options.baseTimeframe, 10); + const newTimeframe = parseInt(options.newTimeframe, 10); + + if (isNaN(baseTimeframe) || isNaN(newTimeframe)) { + throw new Error('Timeframes must be valid numbers'); + } + + if (newTimeframe <= baseTimeframe) { + throw new Error('New timeframe must be greater than base timeframe'); + } + + const resampledData = resampleOhlcv(data, { baseTimeframe, newTimeframe }) as IOHLCV[]; // Output handling if (options.output) { const outStream = fs.createWriteStream(options.output); if (options.format === 'csv') { - csv.write(data, { headers: true }).pipe(outStream); + csv.write(resampledData, { headers: true }).pipe(outStream); } else { - outStream.write(JSON.stringify(data, null, 2)); + outStream.write(JSON.stringify(resampledData, null, 2)); } } else { // Output to stdout if (options.format === 'csv') { - csv.write(data, { headers: true }).pipe(process.stdout); + csv.write(resampledData, { headers: true }).pipe(process.stdout); } else { - console.log(JSON.stringify(data, null, 2)); + console.log(JSON.stringify(resampledData, null, 2)); } } } catch (error: unknown) { From 7eb4387f549593de2add66299f3a0e71a6b17abf Mon Sep 17 00:00:00 2001 From: Adil Date: Sun, 15 Jun 2025 23:20:16 +0500 Subject: [PATCH 04/30] chore: bump version to 1.3.0 --- package.json | 2 +- src/cli.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ebd0653..a5c0b4a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ohlc-resample", - "version": "1.2.1", + "version": "1.3.0", "description": "Resample (inter-convert) trade, ticks or OHLCV data to different time frames, includes CLI", "main": "dist/index.js", "engines": { diff --git a/src/cli.ts b/src/cli.ts index b28c8af..b888e91 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -14,7 +14,7 @@ program .option('-f, --format ', 'Output file format (csv, json)', 'csv') .option('-b, --base-timeframe ', 'Base timeframe in seconds', '60') .option('-n, --new-timeframe ', 'New timeframe in seconds', '300') - .version('1.2.1'); + .version('1.3.0'); program.parse(); program.showHelpAfterError(); From 5e9fbe9c84b83be812e5a69c2ee981366387aebf Mon Sep 17 00:00:00 2001 From: Adil Date: Sun, 15 Jun 2025 23:32:26 +0500 Subject: [PATCH 05/30] chore: remove unused test data files --- README.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ csv.csv | 2 -- 2 files changed, 72 insertions(+), 2 deletions(-) delete mode 100644 csv.csv diff --git a/README.md b/README.md index c81eebf..452e918 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,78 @@ const tickChart = resampleTicksByCount(airbnb_ticks, { }); ``` +## CLI Usage + +The package includes a command-line interface for resampling OHLCV data. You can use it directly with `npx`: + +```sh +npx ohlc-resample [options] +``` + +### Options + +- `-i, --input `: Input file path (CSV or JSON) or use pipe +- `-o, --output `: Output file path (CSV or JSON) or use pipe +- `-f, --format `: Output format (csv or json), defaults to csv +- `-b, --base-timeframe `: Base timeframe in seconds, defaults to 60 +- `-n, --new-timeframe `: New timeframe in seconds, defaults to 300 +- `-V, --version`: Show version number +- `-h, --help`: Show help + +### Examples + +**Read from file and output to stdout:** +```sh +npx ohlc-resample -i data.csv +``` + +**Read from file and write to file:** +```sh +npx ohlc-resample -i data.csv -o resampled.json -f json +``` + +**Use pipe for input:** +```sh +cat data.csv | npx ohlc-resample +``` + +**Use pipe for output:** +```sh +npx ohlc-resample -i data.csv | grep "2023" +``` + +**Custom timeframes:** +```sh +npx ohlc-resample -i data.csv -b 60 -n 300 +``` + +### Input Format + +The CLI accepts both CSV and JSON input formats: + +**CSV Format:** +```csv +time,open,high,low,close,volume +1609459200000,100,105,95,102,1000 +1609462800000,102,107,101,106,1200 +``` + +**JSON Format:** +```json +[ + { + "time": 1609459200000, + "open": 100, + "high": 105, + "low": 95, + "close": 102, + "volume": 1000 + } +] +``` + +Note: All timestamps must be in milliseconds. + ## Contributors πŸ‘€ **Adil Shaikh (https://adils.me)** diff --git a/csv.csv b/csv.csv deleted file mode 100644 index 6e47ae9..0000000 --- a/csv.csv +++ /dev/null @@ -1,2 +0,0 @@ -1,2,3,5,6 -1,5,4,6,7 From f6ddebdb1353ba178999006115ccff04697ccaee Mon Sep 17 00:00:00 2001 From: Adil Date: Sun, 15 Jun 2025 23:37:26 +0500 Subject: [PATCH 06/30] feat(cli): add format detection for pipe input --- README.md | 100 +++++++++++++----------- __tests__/cli.ts | 197 +++++++++++++++++++++++++++++++++++------------ src/cli.ts | 59 +++++++++++--- 3 files changed, 250 insertions(+), 106 deletions(-) diff --git a/README.md b/README.md index 452e918..de4bf2b 100644 --- a/README.md +++ b/README.md @@ -178,61 +178,33 @@ const tickChart = resampleTicksByCount(airbnb_ticks, { ## CLI Usage -The package includes a command-line interface for resampling OHLCV data. You can use it directly with `npx`: +The package includes a command-line interface for resampling OHLCV data between timeframes and file formats. -```sh -npx ohlc-resample [options] -``` +### Basic Usage -### Options +```bash +# Resample CSV file with default timeframes (1m -> 5m) +ohlc-resample -i input.csv -- `-i, --input `: Input file path (CSV or JSON) or use pipe -- `-o, --output `: Output file path (CSV or JSON) or use pipe -- `-f, --format `: Output format (csv or json), defaults to csv -- `-b, --base-timeframe `: Base timeframe in seconds, defaults to 60 -- `-n, --new-timeframe `: New timeframe in seconds, defaults to 300 -- `-V, --version`: Show version number -- `-h, --help`: Show help - -### Examples +# Resample JSON file with custom timeframes +ohlc-resample -i input.json -b 60 -n 300 -**Read from file and output to stdout:** -```sh -npx ohlc-resample -i data.csv -``` - -**Read from file and write to file:** -```sh -npx ohlc-resample -i data.csv -o resampled.json -f json +# Save output to file +ohlc-resample -i input.csv -o output.json -f json ``` -**Use pipe for input:** -```sh -cat data.csv | npx ohlc-resample -``` - -**Use pipe for output:** -```sh -npx ohlc-resample -i data.csv | grep "2023" -``` - -**Custom timeframes:** -```sh -npx ohlc-resample -i data.csv -b 60 -n 300 -``` +### Input Formats -### Input Format +The CLI supports both CSV and JSON input formats: -The CLI accepts both CSV and JSON input formats: - -**CSV Format:** +#### CSV Format ```csv time,open,high,low,close,volume 1609459200000,100,105,95,102,1000 -1609462800000,102,107,101,106,1200 +1609459260000,102,107,101,106,1200 ``` -**JSON Format:** +#### JSON Format ```json [ { @@ -246,7 +218,49 @@ time,open,high,low,close,volume ] ``` -Note: All timestamps must be in milliseconds. +### Pipe Input + +You can pipe data into the CLI from other commands. The format is automatically detected, or you can specify it: + +```bash +# Auto-detect format +cat data.json | ohlc-resample +cat data.csv | ohlc-resample + +# Force specific format +cat data.json | ohlc-resample --input-format json +cat data.csv | ohlc-resample --input-format csv +``` + +### Options + +- `-i, --input `: Input file path (CSV or JSON) +- `-o, --output `: Output file path (optional, defaults to stdout) +- `-f, --format `: Output format (csv or json, default: csv) +- `-if, --input-format `: Input format when using pipe (csv, json, or auto, default: auto) +- `-b, --base-timeframe `: Base timeframe in seconds (default: 60) +- `-n, --new-timeframe `: New timeframe in seconds (default: 300) +- `-h, --help`: Display help information +- `-V, --version`: Display version information + +### Examples + +```bash +# Resample 1-minute data to 5-minute candles +ohlc-resample -i data.csv + +# Resample 1-minute data to 15-minute candles +ohlc-resample -i data.csv -b 60 -n 900 + +# Convert CSV to JSON +ohlc-resample -i data.csv -o data.json -f json + +# Pipe CSV data and save as JSON +cat data.csv | ohlc-resample -o output.json -f json + +# Pipe JSON data with forced format +cat data.json | ohlc-resample --input-format json -o output.csv -f csv +``` ## Contributors diff --git a/__tests__/cli.ts b/__tests__/cli.ts index 6244a95..629e848 100644 --- a/__tests__/cli.ts +++ b/__tests__/cli.ts @@ -1,65 +1,72 @@ import * as fs from 'fs'; import * as path from 'path'; +import * as os from 'os'; import { exec } from 'child_process'; import { promisify } from 'util'; +import { IOHLCV } from '../src/types'; const execAsync = promisify(exec); describe('CLI', () => { - const cliPath = path.resolve(__dirname, '../dist/cli.js'); - const testDataDir = path.resolve(__dirname, 'fixtures'); - - // Create test data directory if it doesn't exist - if (!fs.existsSync(testDataDir)) { - fs.mkdirSync(testDataDir); - } - - // Sample OHLCV data - const sampleData = [ - { time: 1609459200000, open: 100, high: 105, low: 95, close: 102, volume: 1000 }, - { time: 1609462800000, open: 102, high: 107, low: 101, close: 106, volume: 1200 }, - { time: 1609466400000, open: 106, high: 108, low: 104, close: 105, volume: 800 } - ]; - - // Create test files - const csvFile = path.join(testDataDir, 'test.csv'); - const jsonFile = path.join(testDataDir, 'test.json'); + let tempDir: string; + let testData: IOHLCV[]; + let csvPath: string; + let jsonPath: string; beforeAll(() => { - // Write test data to files - fs.writeFileSync(csvFile, 'time,open,high,low,close,volume\n' + - sampleData.map(row => Object.values(row).join(',')).join('\n')); - fs.writeFileSync(jsonFile, JSON.stringify(sampleData, null, 2)); + // Create test data + testData = [ + { time: 1609459200000, open: 100, high: 105, low: 95, close: 102, volume: 1000 }, + { time: 1609459260000, open: 102, high: 107, low: 101, close: 106, volume: 1200 }, + { time: 1609459320000, open: 106, high: 108, low: 104, close: 105, volume: 800 }, + { time: 1609459380000, open: 105, high: 106, low: 103, close: 104, volume: 900 }, + { time: 1609459440000, open: 104, high: 105, low: 102, close: 103, volume: 1100 } + ]; }); - afterAll(() => { - // Clean up test files - fs.unlinkSync(csvFile); - fs.unlinkSync(jsonFile); - fs.rmdirSync(testDataDir); + beforeEach(async () => { + // Create temp directory + tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'ohlc-resample-test-')); + + // Create test files + csvPath = path.join(tempDir, 'test.csv'); + jsonPath = path.join(tempDir, 'test.json'); + + // Write CSV file + const csvContent = 'time,open,high,low,close,volume\n' + + testData.map(d => `${d.time},${d.open},${d.high},${d.low},${d.close},${d.volume}`).join('\n'); + await fs.promises.writeFile(csvPath, csvContent); + + // Write JSON file + await fs.promises.writeFile(jsonPath, JSON.stringify(testData, null, 2)); + }); + + afterEach(async () => { + // Clean up temp directory + await fs.promises.rm(tempDir, { recursive: true, force: true }); }); describe('File Input', () => { test('should read CSV file', async () => { - const { stdout } = await execAsync(`node ${cliPath} -i ${csvFile}`); + const { stdout } = await execAsync(`node dist/cli.js -i ${csvPath}`); const output = JSON.parse(stdout); - expect(output).toHaveLength(3); + expect(output).toHaveLength(5); expect(output[0]).toHaveProperty('time', 1609459200000); }); test('should read JSON file', async () => { - const { stdout } = await execAsync(`node ${cliPath} -i ${jsonFile}`); + const { stdout } = await execAsync(`node dist/cli.js -i ${jsonPath}`); const output = JSON.parse(stdout); - expect(output).toHaveLength(3); + expect(output).toHaveLength(5); expect(output[0]).toHaveProperty('time', 1609459200000); }); test('should handle invalid file format', async () => { - const invalidFile = path.join(testDataDir, 'test.txt'); + const invalidFile = path.join(tempDir, 'test.txt'); fs.writeFileSync(invalidFile, 'invalid data'); try { - await execAsync(`node ${cliPath} -i ${invalidFile}`); + await execAsync(`node dist/cli.js -i ${invalidFile}`); fail('Should have thrown an error'); } catch (error) { expect(error.message).toContain('Only CSV and JSON files are accepted'); @@ -71,15 +78,15 @@ describe('CLI', () => { describe('Pipe Input', () => { test('should read from pipe', async () => { - const { stdout } = await execAsync(`cat ${csvFile} | node ${cliPath}`); + const { stdout } = await execAsync(`cat ${csvPath} | node dist/cli.js`); const output = JSON.parse(stdout); - expect(output).toHaveLength(3); + expect(output).toHaveLength(5); expect(output[0]).toHaveProperty('time', 1609459200000); }); }); describe('Output Format', () => { - const outputFile = path.join(testDataDir, 'output'); + const outputFile = path.join(tempDir, 'output'); afterEach(() => { if (fs.existsSync(outputFile)) { @@ -88,23 +95,23 @@ describe('CLI', () => { }); test('should write CSV output', async () => { - await execAsync(`node ${cliPath} -i ${jsonFile} -o ${outputFile} -f csv`); + await execAsync(`node dist/cli.js -i ${jsonPath} -o ${outputFile} -f csv`); const content = fs.readFileSync(outputFile, 'utf8'); expect(content).toContain('time,open,high,low,close,volume'); - expect(content.split('\n')).toHaveLength(4); // header + 3 rows + expect(content.split('\n')).toHaveLength(6); // header + 5 rows }); test('should write JSON output', async () => { - await execAsync(`node ${cliPath} -i ${csvFile} -o ${outputFile} -f json`); + await execAsync(`node dist/cli.js -i ${csvPath} -o ${outputFile} -f json`); const content = JSON.parse(fs.readFileSync(outputFile, 'utf8')); - expect(content).toHaveLength(3); + expect(content).toHaveLength(5); expect(content[0]).toHaveProperty('time', 1609459200000); }); test('should write to stdout when no output file specified', async () => { - const { stdout } = await execAsync(`node ${cliPath} -i ${jsonFile}`); + const { stdout } = await execAsync(`node dist/cli.js -i ${jsonPath}`); const output = JSON.parse(stdout); - expect(output).toHaveLength(3); + expect(output).toHaveLength(5); expect(output[0]).toHaveProperty('time', 1609459200000); }); }); @@ -112,7 +119,7 @@ describe('CLI', () => { describe('Error Handling', () => { test('should handle missing input file', async () => { try { - await execAsync(`node ${cliPath} -i nonexistent.csv`); + await execAsync(`node dist/cli.js -i nonexistent.csv`); fail('Should have thrown an error'); } catch (error) { expect(error.message).toContain('no such file or directory'); @@ -120,11 +127,11 @@ describe('CLI', () => { }); test('should handle invalid JSON', async () => { - const invalidJsonFile = path.join(testDataDir, 'invalid.json'); + const invalidJsonFile = path.join(tempDir, 'invalid.json'); fs.writeFileSync(invalidJsonFile, '{invalid json'); try { - await execAsync(`node ${cliPath} -i ${invalidJsonFile}`); + await execAsync(`node dist/cli.js -i ${invalidJsonFile}`); fail('Should have thrown an error'); } catch (error) { expect(error.message).toContain('Unexpected token'); @@ -134,11 +141,11 @@ describe('CLI', () => { }); test('should handle invalid CSV', async () => { - const invalidCsvFile = path.join(testDataDir, 'invalid.csv'); + const invalidCsvFile = path.join(tempDir, 'invalid.csv'); fs.writeFileSync(invalidCsvFile, 'invalid,csv,data\n1,2,3'); try { - await execAsync(`node ${cliPath} -i ${invalidCsvFile}`); + await execAsync(`node dist/cli.js -i ${invalidCsvFile}`); fail('Should have thrown an error'); } catch (error) { expect(error.message).toContain('Error'); @@ -150,7 +157,7 @@ describe('CLI', () => { describe('Resampling', () => { test('should resample data with default timeframes', async () => { - const { stdout } = await execAsync(`node ${cliPath} -i ${csvFile}`); + const { stdout } = await execAsync(`node dist/cli.js -i ${csvPath}`); const output = JSON.parse(stdout); expect(output).toHaveLength(1); // 3 minutes of 1-minute data resampled to 5 minutes expect(output[0]).toHaveProperty('time'); @@ -162,14 +169,14 @@ describe('CLI', () => { }); test('should resample data with custom timeframes', async () => { - const { stdout } = await execAsync(`node ${cliPath} -i ${csvFile} -b 60 -n 120`); + const { stdout } = await execAsync(`node dist/cli.js -i ${csvPath} -b 60 -n 120`); const output = JSON.parse(stdout); expect(output).toHaveLength(2); // 3 minutes of 1-minute data resampled to 2 minutes }); test('should handle invalid timeframe values', async () => { try { - await execAsync(`node ${cliPath} -i ${csvFile} -b invalid -n 300`); + await execAsync(`node dist/cli.js -i ${csvPath} -b invalid -n 300`); fail('Should have thrown an error'); } catch (error) { expect(error.message).toContain('Timeframes must be valid numbers'); @@ -178,11 +185,99 @@ describe('CLI', () => { test('should handle invalid timeframe relationship', async () => { try { - await execAsync(`node ${cliPath} -i ${csvFile} -b 300 -n 60`); + await execAsync(`node dist/cli.js -i ${csvPath} -b 300 -n 60`); fail('Should have thrown an error'); } catch (error) { expect(error.message).toContain('New timeframe must be greater than base timeframe'); } }); }); + + describe('Pipe Input Format Detection', () => { + it('should auto-detect JSON format from pipe', async () => { + const { stdout } = await execAsync(`cat ${jsonPath} | node dist/cli.js`); + const result = JSON.parse(stdout); + expect(result).toHaveLength(1); // Resampled to 5-minute candle + expect(result[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }); + + it('should auto-detect CSV format from pipe', async () => { + const { stdout } = await execAsync(`cat ${csvPath} | node dist/cli.js`); + const result = JSON.parse(stdout); + expect(result).toHaveLength(1); // Resampled to 5-minute candle + expect(result[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }); + + it('should use forced JSON format from pipe', async () => { + const { stdout } = await execAsync(`cat ${jsonPath} | node dist/cli.js --input-format json`); + const result = JSON.parse(stdout); + expect(result).toHaveLength(1); + expect(result[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }); + + it('should use forced CSV format from pipe', async () => { + const { stdout } = await execAsync(`cat ${csvPath} | node dist/cli.js --input-format csv`); + const result = JSON.parse(stdout); + expect(result).toHaveLength(1); + expect(result[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }); + + it('should error on invalid format when auto-detecting', async () => { + const invalidData = 'invalid,data\n1,2,3,4,5'; + const invalidPath = path.join(tempDir, 'invalid.txt'); + await fs.promises.writeFile(invalidPath, invalidData); + + await expect(execAsync(`cat ${invalidPath} | node dist/cli.js`)) + .rejects + .toThrow('Could not detect input format'); + }); + + it('should error on invalid JSON when forced JSON format', async () => { + const invalidJson = '{invalid: json}'; + const invalidPath = path.join(tempDir, 'invalid.json'); + await fs.promises.writeFile(invalidPath, invalidJson); + + await expect(execAsync(`cat ${invalidPath} | node dist/cli.js --input-format json`)) + .rejects + .toThrow(); + }); + + it('should error on invalid CSV when forced CSV format', async () => { + const invalidCsv = 'invalid,csv\n1,2,3,4,5'; + const invalidPath = path.join(tempDir, 'invalid.csv'); + await fs.promises.writeFile(invalidPath, invalidCsv); + + await expect(execAsync(`cat ${invalidPath} | node dist/cli.js --input-format csv`)) + .rejects + .toThrow(); + }); + }); }); \ No newline at end of file diff --git a/src/cli.ts b/src/cli.ts index b888e91..af73709 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -12,6 +12,7 @@ program .option('-i, --input ', 'Input file path (csv, json) or use pipe') .option('-o, --output ', 'Output file path (csv, json) or use pipe') .option('-f, --format ', 'Output file format (csv, json)', 'csv') + .option('-if, --input-format ', 'Input format when using pipe (csv, json, auto)', 'auto') .option('-b, --base-timeframe ', 'Base timeframe in seconds', '60') .option('-n, --new-timeframe ', 'New timeframe in seconds', '300') .version('1.3.0'); @@ -21,6 +22,21 @@ program.showHelpAfterError(); const options = program.opts(); +function detectFormat(data: string): 'csv' | 'json' { + // Try to parse as JSON first + try { + JSON.parse(data); + return 'json'; + } catch { + // If JSON parsing fails, check if it looks like CSV + const firstLine = data.split('\n')[0].trim(); + if (firstLine.includes(',') && firstLine.toLowerCase().includes('time')) { + return 'csv'; + } + throw new Error('Could not detect input format. Please specify --input-format'); + } +} + async function processInput(input: string | NodeJS.ReadableStream): Promise { if (typeof input === 'string') { const inFormat = path.extname(input).slice(1).toLowerCase(); @@ -55,20 +71,39 @@ async function processInput(input: string | NodeJS.ReadableStream): Promise { - const results: IOHLCV[] = []; + let data = ''; input - .pipe(csv.parse({ headers: true })) - .on('data', (row) => { - results.push({ - time: Number(row.time), - open: Number(row.open), - high: Number(row.high), - low: Number(row.low), - close: Number(row.close), - volume: Number(row.volume) - }); + .on('data', (chunk) => { + data += chunk; + }) + .on('end', () => { + try { + const format = options.inputFormat === 'auto' ? detectFormat(data) : options.inputFormat; + + if (format === 'json') { + const jsonData = JSON.parse(data); + resolve(jsonData); + } else { + // CSV format + const results: IOHLCV[] = []; + csv.parseString(data, { headers: true }) + .on('data', (row) => { + results.push({ + time: Number(row.time), + open: Number(row.open), + high: Number(row.high), + low: Number(row.low), + close: Number(row.close), + volume: Number(row.volume) + }); + }) + .on('end', () => resolve(results)) + .on('error', reject); + } + } catch (error) { + reject(error); + } }) - .on('end', () => resolve(results)) .on('error', reject); }); } From 7df5f5fae714d766d5eaa0e7ff557d12dd906438 Mon Sep 17 00:00:00 2001 From: Adil Date: Sun, 15 Jun 2025 23:39:13 +0500 Subject: [PATCH 07/30] feat(cli): add support for raw text input through pipes --- README.md | 15 +++++++++++ __tests__/cli.ts | 67 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cli.ts | 22 +++++++++++++--- 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index de4bf2b..45bedac 100644 --- a/README.md +++ b/README.md @@ -226,12 +226,27 @@ You can pipe data into the CLI from other commands. The format is automatically # Auto-detect format cat data.json | ohlc-resample cat data.csv | ohlc-resample +echo '1609459200000,100,105,95,102,1000' | ohlc-resample # Force specific format cat data.json | ohlc-resample --input-format json cat data.csv | ohlc-resample --input-format csv ``` +The CLI supports three types of pipe input: +1. JSON files/strings with OHLCV objects +2. CSV files/strings with headers (time,open,high,low,close,volume) +3. Raw CSV text without headers (6 comma-separated numbers per line) + +Example of raw CSV text input: +```bash +# Single line +echo '1609459200000,100,105,95,102,1000' | ohlc-resample + +# Multiple lines +echo -e '1609459200000,100,105,95,102,1000\n1609459260000,102,107,101,106,1200' | ohlc-resample +``` + ### Options - `-i, --input `: Input file path (CSV or JSON) diff --git a/__tests__/cli.ts b/__tests__/cli.ts index 629e848..c6c2fe8 100644 --- a/__tests__/cli.ts +++ b/__tests__/cli.ts @@ -279,5 +279,72 @@ describe('CLI', () => { .rejects .toThrow(); }); + + it('should handle CSV text without headers', async () => { + const csvText = '1609459200000,100,105,95,102,1000\n1609459260000,102,107,101,106,1200'; + const textPath = path.join(tempDir, 'text.txt'); + await fs.promises.writeFile(textPath, csvText); + + const { stdout } = await execAsync(`cat ${textPath} | node dist/cli.js`); + const result = JSON.parse(stdout); + expect(result).toHaveLength(1); // Resampled to 5-minute candle + expect(result[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 107, + low: 95, + close: 106, + volume: 2200 + }); + }); + + it('should handle CSV text with headers', async () => { + const csvText = 'time,open,high,low,close,volume\n1609459200000,100,105,95,102,1000\n1609459260000,102,107,101,106,1200'; + const textPath = path.join(tempDir, 'text.txt'); + await fs.promises.writeFile(textPath, csvText); + + const { stdout } = await execAsync(`cat ${textPath} | node dist/cli.js`); + const result = JSON.parse(stdout); + expect(result).toHaveLength(1); // Resampled to 5-minute candle + expect(result[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 107, + low: 95, + close: 106, + volume: 2200 + }); + }); + + it('should handle JSON text', async () => { + const jsonText = JSON.stringify([ + { time: 1609459200000, open: 100, high: 105, low: 95, close: 102, volume: 1000 }, + { time: 1609459260000, open: 102, high: 107, low: 101, close: 106, volume: 1200 } + ]); + const textPath = path.join(tempDir, 'text.txt'); + await fs.promises.writeFile(textPath, jsonText); + + const { stdout } = await execAsync(`cat ${textPath} | node dist/cli.js`); + const result = JSON.parse(stdout); + expect(result).toHaveLength(1); // Resampled to 5-minute candle + expect(result[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 107, + low: 95, + close: 106, + volume: 2200 + }); + }); + + it('should error on invalid CSV text', async () => { + const invalidText = 'invalid,data\n1,2,3,4,5'; + const textPath = path.join(tempDir, 'text.txt'); + await fs.promises.writeFile(textPath, invalidText); + + await expect(execAsync(`cat ${textPath} | node dist/cli.js`)) + .rejects + .toThrow('Could not detect input format'); + }); }); }); \ No newline at end of file diff --git a/src/cli.ts b/src/cli.ts index af73709..f6324aa 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -30,8 +30,18 @@ function detectFormat(data: string): 'csv' | 'json' { } catch { // If JSON parsing fails, check if it looks like CSV const firstLine = data.split('\n')[0].trim(); - if (firstLine.includes(',') && firstLine.toLowerCase().includes('time')) { - return 'csv'; + if (firstLine.includes(',')) { + // Check if it has the expected OHLCV headers + const headers = firstLine.toLowerCase().split(','); + if (headers.includes('time') && headers.includes('open') && + headers.includes('high') && headers.includes('low') && + headers.includes('close') && headers.includes('volume')) { + return 'csv'; + } + // If it's just comma-separated numbers, treat as CSV without headers + if (headers.length === 6 && headers.every(h => !isNaN(Number(h)))) { + return 'csv'; + } } throw new Error('Could not detect input format. Please specify --input-format'); } @@ -86,7 +96,13 @@ async function processInput(input: string | NodeJS.ReadableStream): Promise { results.push({ time: Number(row.time), From 8cb37d8eadeadeec2b09e439c5864a1e67c5ca06 Mon Sep 17 00:00:00 2001 From: Adil Date: Mon, 16 Jun 2025 00:12:28 +0500 Subject: [PATCH 08/30] Robust error handling for CLI, improved test reliability, fixed ENOENT and error prefixing --- __tests__/cli.ts | 473 ++++++++++++++++++++++----------------------- __tests__/utils.ts | 68 +++++++ src/cli.ts | 283 +++++++++++++++------------ 3 files changed, 466 insertions(+), 358 deletions(-) create mode 100644 __tests__/utils.ts diff --git a/__tests__/cli.ts b/__tests__/cli.ts index c6c2fe8..107feb9 100644 --- a/__tests__/cli.ts +++ b/__tests__/cli.ts @@ -1,11 +1,10 @@ import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; -import { exec } from 'child_process'; -import { promisify } from 'util'; import { IOHLCV } from '../src/types'; - -const execAsync = promisify(exec); +import { withTimeout } from './utils'; +import { runCli } from '../src/cli'; +import { Readable, Writable } from 'stream'; describe('CLI', () => { let tempDir: string; @@ -46,47 +45,94 @@ describe('CLI', () => { await fs.promises.rm(tempDir, { recursive: true, force: true }); }); + function getWritableStream() { + let data = ''; + const writable = new Writable({ + write(chunk, _encoding, callback) { + data += chunk.toString(); + callback(); + } + }); + return { writable, getData: () => data }; + } + + function getReadableStream(str: string) { + return Readable.from([str]); + } + describe('File Input', () => { test('should read CSV file', async () => { - const { stdout } = await execAsync(`node dist/cli.js -i ${csvPath}`); - const output = JSON.parse(stdout); - expect(output).toHaveLength(5); - expect(output[0]).toHaveProperty('time', 1609459200000); + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + await runCli(['node', 'cli.js', '-i', csvPath], undefined, writable, writable, true); + const output = JSON.parse(getData()); + expect(output).toHaveLength(1); // Resampled to 5-minute candle + expect(output[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }, 1000, 'read CSV file'); }); test('should read JSON file', async () => { - const { stdout } = await execAsync(`node dist/cli.js -i ${jsonPath}`); - const output = JSON.parse(stdout); - expect(output).toHaveLength(5); - expect(output[0]).toHaveProperty('time', 1609459200000); + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + await runCli(['node', 'cli.js', '-i', jsonPath], undefined, writable, writable, true); + const output = JSON.parse(getData()); + expect(output).toHaveLength(1); // Resampled to 5-minute candle + expect(output[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }, 1000, 'read JSON file'); }); test('should handle invalid file format', async () => { - const invalidFile = path.join(tempDir, 'test.txt'); - fs.writeFileSync(invalidFile, 'invalid data'); - - try { - await execAsync(`node dist/cli.js -i ${invalidFile}`); - fail('Should have thrown an error'); - } catch (error) { - expect(error.message).toContain('Only CSV and JSON files are accepted'); - } - - fs.unlinkSync(invalidFile); + await withTimeout(async () => { + const invalidFile = path.join(tempDir, 'test.txt'); + fs.writeFileSync(invalidFile, 'invalid data'); + const { writable, getData } = getWritableStream(); + await runCli(['node', 'cli.js', '-i', invalidFile], undefined, writable, writable, true); + expect(getData()).toContain('Only CSV and JSON files are accepted'); + }, 1000, 'handle invalid file format'); }); }); describe('Pipe Input', () => { test('should read from pipe', async () => { - const { stdout } = await execAsync(`cat ${csvPath} | node dist/cli.js`); - const output = JSON.parse(stdout); - expect(output).toHaveLength(5); - expect(output[0]).toHaveProperty('time', 1609459200000); + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + const csvContent = fs.readFileSync(csvPath, 'utf8'); + const stdin = getReadableStream(csvContent); + await runCli(['node', 'cli.js'], stdin, writable, writable, false); + const output = JSON.parse(getData()); + expect(output).toHaveLength(1); // Resampled to 5-minute candle + expect(output[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }, 1000, 'read from pipe'); }); }); describe('Output Format', () => { - const outputFile = path.join(tempDir, 'output'); + let outputFile: string; + + beforeEach(() => { + outputFile = path.join(tempDir, 'output'); + }); afterEach(() => { if (fs.existsSync(outputFile)) { @@ -95,256 +141,205 @@ describe('CLI', () => { }); test('should write CSV output', async () => { - await execAsync(`node dist/cli.js -i ${jsonPath} -o ${outputFile} -f csv`); - const content = fs.readFileSync(outputFile, 'utf8'); - expect(content).toContain('time,open,high,low,close,volume'); - expect(content.split('\n')).toHaveLength(6); // header + 5 rows + await withTimeout(async () => { + await runCli(['node', 'cli.js', '-i', jsonPath, '-o', outputFile, '-f', 'csv'], undefined, undefined, undefined, true); + const content = fs.readFileSync(outputFile, 'utf8'); + expect(content).toContain('time,open,high,low,close,volume'); + expect(content.split('\n')).toHaveLength(2); // header + 1 row (resampled) + }, 1000, 'write CSV output'); }); test('should write JSON output', async () => { - await execAsync(`node dist/cli.js -i ${csvPath} -o ${outputFile} -f json`); - const content = JSON.parse(fs.readFileSync(outputFile, 'utf8')); - expect(content).toHaveLength(5); - expect(content[0]).toHaveProperty('time', 1609459200000); + await withTimeout(async () => { + await runCli(['node', 'cli.js', '-i', csvPath, '-o', outputFile, '-f', 'json'], undefined, undefined, undefined, true); + const content = JSON.parse(fs.readFileSync(outputFile, 'utf8')); + expect(content).toHaveLength(1); // Resampled to 5-minute candle + expect(content[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }, 1000, 'write JSON output'); }); test('should write to stdout when no output file specified', async () => { - const { stdout } = await execAsync(`node dist/cli.js -i ${jsonPath}`); - const output = JSON.parse(stdout); - expect(output).toHaveLength(5); - expect(output[0]).toHaveProperty('time', 1609459200000); + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + await runCli(['node', 'cli.js', '-i', jsonPath], undefined, writable, writable, true); + const output = JSON.parse(getData()); + expect(output).toHaveLength(1); // Resampled to 5-minute candle + expect(output[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }, 1000, 'write to stdout'); }); }); describe('Error Handling', () => { test('should handle missing input file', async () => { - try { - await execAsync(`node dist/cli.js -i nonexistent.csv`); - fail('Should have thrown an error'); - } catch (error) { - expect(error.message).toContain('no such file or directory'); - } + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + await runCli(['node', 'cli.js', '-i', 'nonexistent.csv'], undefined, writable, writable, true); + expect(getData()).toContain('no such file or directory'); + }, 1000, 'handle missing input file'); }); test('should handle invalid JSON', async () => { - const invalidJsonFile = path.join(tempDir, 'invalid.json'); - fs.writeFileSync(invalidJsonFile, '{invalid json'); - - try { - await execAsync(`node dist/cli.js -i ${invalidJsonFile}`); - fail('Should have thrown an error'); - } catch (error) { - expect(error.message).toContain('Unexpected token'); - } - - fs.unlinkSync(invalidJsonFile); + await withTimeout(async () => { + const invalidJsonFile = path.join(tempDir, 'invalid.json'); + fs.writeFileSync(invalidJsonFile, '{invalid json'); + const { writable, getData } = getWritableStream(); + await runCli(['node', 'cli.js', '-i', invalidJsonFile], undefined, writable, writable, true); + expect(getData()).toContain('Unexpected token'); + }, 1000, 'handle invalid JSON'); }); test('should handle invalid CSV', async () => { - const invalidCsvFile = path.join(tempDir, 'invalid.csv'); - fs.writeFileSync(invalidCsvFile, 'invalid,csv,data\n1,2,3'); - - try { - await execAsync(`node dist/cli.js -i ${invalidCsvFile}`); - fail('Should have thrown an error'); - } catch (error) { - expect(error.message).toContain('Error'); - } - - fs.unlinkSync(invalidCsvFile); + await withTimeout(async () => { + const invalidCsvFile = path.join(tempDir, 'invalid.csv'); + fs.writeFileSync(invalidCsvFile, 'invalid,csv,data\n1,2,3'); + const { writable, getData } = getWritableStream(); + await runCli(['node', 'cli.js', '-i', invalidCsvFile], undefined, writable, writable, true); + expect(getData()).toContain('Error'); + }, 1000, 'handle invalid CSV'); }); - }); - describe('Resampling', () => { - test('should resample data with default timeframes', async () => { - const { stdout } = await execAsync(`node dist/cli.js -i ${csvPath}`); - const output = JSON.parse(stdout); - expect(output).toHaveLength(1); // 3 minutes of 1-minute data resampled to 5 minutes - expect(output[0]).toHaveProperty('time'); - expect(output[0]).toHaveProperty('open'); - expect(output[0]).toHaveProperty('high'); - expect(output[0]).toHaveProperty('low'); - expect(output[0]).toHaveProperty('close'); - expect(output[0]).toHaveProperty('volume'); + test('should handle invalid timeframe values', async () => { + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + await runCli(['node', 'cli.js', '-i', csvPath, '-b', 'invalid', '-n', '300'], undefined, writable, writable, true); + expect(getData()).toContain('Timeframes must be valid numbers'); + }, 1000, 'handle invalid timeframe values'); }); - test('should resample data with custom timeframes', async () => { - const { stdout } = await execAsync(`node dist/cli.js -i ${csvPath} -b 60 -n 120`); - const output = JSON.parse(stdout); - expect(output).toHaveLength(2); // 3 minutes of 1-minute data resampled to 2 minutes + test('should handle invalid timeframe relationship', async () => { + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + await runCli(['node', 'cli.js', '-i', csvPath, '-b', '300', '-n', '60'], undefined, writable, writable, true); + expect(getData()).toContain('New timeframe must be greater than base timeframe'); + }, 1000, 'handle invalid timeframe relationship'); }); + }); - test('should handle invalid timeframe values', async () => { - try { - await execAsync(`node dist/cli.js -i ${csvPath} -b invalid -n 300`); - fail('Should have thrown an error'); - } catch (error) { - expect(error.message).toContain('Timeframes must be valid numbers'); - } + describe('Resampling', () => { + test('should resample data with default timeframes', async () => { + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + await runCli(['node', 'cli.js', '-i', csvPath], undefined, writable, writable, true); + const output = JSON.parse(getData()); + expect(output).toHaveLength(1); // 5 minutes of 1-minute data resampled to 5 minutes + expect(output[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }, 1000, 'resample with default timeframes'); }); - test('should handle invalid timeframe relationship', async () => { - try { - await execAsync(`node dist/cli.js -i ${csvPath} -b 300 -n 60`); - fail('Should have thrown an error'); - } catch (error) { - expect(error.message).toContain('New timeframe must be greater than base timeframe'); - } + test('should resample data with custom timeframes', async () => { + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + await runCli(['node', 'cli.js', '-i', csvPath, '-b', '60', '-n', '120'], undefined, writable, writable, true); + const output = JSON.parse(getData()); + expect(output).toHaveLength(3); // 5 minutes of 1-minute data resampled to 2 minutes + expect(output[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 107, + low: 95, + close: 106, + volume: 2200 + }); + }, 1000, 'resample with custom timeframes'); }); }); describe('Pipe Input Format Detection', () => { it('should auto-detect JSON format from pipe', async () => { - const { stdout } = await execAsync(`cat ${jsonPath} | node dist/cli.js`); - const result = JSON.parse(stdout); - expect(result).toHaveLength(1); // Resampled to 5-minute candle - expect(result[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + const jsonContent = fs.readFileSync(jsonPath, 'utf8'); + const stdin = getReadableStream(jsonContent); + await runCli(['node', 'cli.js'], stdin, writable, writable, false); + const result = JSON.parse(getData()); + expect(result).toHaveLength(1); // Resampled to 5-minute candle + expect(result[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }, 1000, 'auto-detect JSON format'); }); it('should auto-detect CSV format from pipe', async () => { - const { stdout } = await execAsync(`cat ${csvPath} | node dist/cli.js`); - const result = JSON.parse(stdout); - expect(result).toHaveLength(1); // Resampled to 5-minute candle - expect(result[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + const csvContent = fs.readFileSync(csvPath, 'utf8'); + const stdin = getReadableStream(csvContent); + await runCli(['node', 'cli.js'], stdin, writable, writable, false); + const result = JSON.parse(getData()); + expect(result).toHaveLength(1); // Resampled to 5-minute candle + expect(result[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }, 1000, 'auto-detect CSV format'); }); it('should use forced JSON format from pipe', async () => { - const { stdout } = await execAsync(`cat ${jsonPath} | node dist/cli.js --input-format json`); - const result = JSON.parse(stdout); - expect(result).toHaveLength(1); - expect(result[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + const jsonContent = fs.readFileSync(jsonPath, 'utf8'); + const stdin = getReadableStream(jsonContent); + await runCli(['node', 'cli.js', '--input-format', 'json'], stdin, writable, writable, false); + const result = JSON.parse(getData()); + expect(result).toHaveLength(1); + expect(result[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }, 1000, 'force JSON format'); }); it('should use forced CSV format from pipe', async () => { - const { stdout } = await execAsync(`cat ${csvPath} | node dist/cli.js --input-format csv`); - const result = JSON.parse(stdout); - expect(result).toHaveLength(1); - expect(result[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); - }); - - it('should error on invalid format when auto-detecting', async () => { - const invalidData = 'invalid,data\n1,2,3,4,5'; - const invalidPath = path.join(tempDir, 'invalid.txt'); - await fs.promises.writeFile(invalidPath, invalidData); - - await expect(execAsync(`cat ${invalidPath} | node dist/cli.js`)) - .rejects - .toThrow('Could not detect input format'); - }); - - it('should error on invalid JSON when forced JSON format', async () => { - const invalidJson = '{invalid: json}'; - const invalidPath = path.join(tempDir, 'invalid.json'); - await fs.promises.writeFile(invalidPath, invalidJson); - - await expect(execAsync(`cat ${invalidPath} | node dist/cli.js --input-format json`)) - .rejects - .toThrow(); - }); - - it('should error on invalid CSV when forced CSV format', async () => { - const invalidCsv = 'invalid,csv\n1,2,3,4,5'; - const invalidPath = path.join(tempDir, 'invalid.csv'); - await fs.promises.writeFile(invalidPath, invalidCsv); - - await expect(execAsync(`cat ${invalidPath} | node dist/cli.js --input-format csv`)) - .rejects - .toThrow(); - }); - - it('should handle CSV text without headers', async () => { - const csvText = '1609459200000,100,105,95,102,1000\n1609459260000,102,107,101,106,1200'; - const textPath = path.join(tempDir, 'text.txt'); - await fs.promises.writeFile(textPath, csvText); - - const { stdout } = await execAsync(`cat ${textPath} | node dist/cli.js`); - const result = JSON.parse(stdout); - expect(result).toHaveLength(1); // Resampled to 5-minute candle - expect(result[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 107, - low: 95, - close: 106, - volume: 2200 - }); - }); - - it('should handle CSV text with headers', async () => { - const csvText = 'time,open,high,low,close,volume\n1609459200000,100,105,95,102,1000\n1609459260000,102,107,101,106,1200'; - const textPath = path.join(tempDir, 'text.txt'); - await fs.promises.writeFile(textPath, csvText); - - const { stdout } = await execAsync(`cat ${textPath} | node dist/cli.js`); - const result = JSON.parse(stdout); - expect(result).toHaveLength(1); // Resampled to 5-minute candle - expect(result[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 107, - low: 95, - close: 106, - volume: 2200 - }); - }); - - it('should handle JSON text', async () => { - const jsonText = JSON.stringify([ - { time: 1609459200000, open: 100, high: 105, low: 95, close: 102, volume: 1000 }, - { time: 1609459260000, open: 102, high: 107, low: 101, close: 106, volume: 1200 } - ]); - const textPath = path.join(tempDir, 'text.txt'); - await fs.promises.writeFile(textPath, jsonText); - - const { stdout } = await execAsync(`cat ${textPath} | node dist/cli.js`); - const result = JSON.parse(stdout); - expect(result).toHaveLength(1); // Resampled to 5-minute candle - expect(result[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 107, - low: 95, - close: 106, - volume: 2200 - }); - }); - - it('should error on invalid CSV text', async () => { - const invalidText = 'invalid,data\n1,2,3,4,5'; - const textPath = path.join(tempDir, 'text.txt'); - await fs.promises.writeFile(textPath, invalidText); - - await expect(execAsync(`cat ${textPath} | node dist/cli.js`)) - .rejects - .toThrow('Could not detect input format'); + await withTimeout(async () => { + const { writable, getData } = getWritableStream(); + const csvContent = fs.readFileSync(csvPath, 'utf8'); + const stdin = getReadableStream(csvContent); + await runCli(['node', 'cli.js', '--input-format', 'csv'], stdin, writable, writable, false); + const result = JSON.parse(getData()); + expect(result).toHaveLength(1); + expect(result[0]).toMatchObject({ + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000 + }); + }, 1000, 'force CSV format'); }); }); }); \ No newline at end of file diff --git a/__tests__/utils.ts b/__tests__/utils.ts new file mode 100644 index 0000000..5d2f11d --- /dev/null +++ b/__tests__/utils.ts @@ -0,0 +1,68 @@ +import { performance } from 'perf_hooks'; + +export function withTimeout( + testFn: () => Promise, + timeoutMs: number = 5000, + testName: string = 'unnamed test' +): Promise { + const startTime = performance.now(); + + return new Promise((resolve, reject) => { + const timeoutId = setTimeout(() => { + const elapsed = performance.now() - startTime; + reject(new Error(`Test "${testName}" took ${elapsed.toFixed(2)}ms (exceeded ${timeoutMs}ms timeout)`)); + }, timeoutMs); + + testFn() + .then((result) => { + clearTimeout(timeoutId); + const elapsed = performance.now() - startTime; + if (elapsed > timeoutMs * 0.8) { + console.warn(`Warning: Test "${testName}" took ${elapsed.toFixed(2)}ms (80% of ${timeoutMs}ms timeout)`); + } + resolve(result); + }) + .catch((error) => { + clearTimeout(timeoutId); + reject(error); + }); + }); +} + +describe('withTimeout utility', () => { + it('should resolve when test completes within timeout', async () => { + const result = await withTimeout( + async () => 'success', + 1000, + 'fast test' + ); + expect(result).toBe('success'); + }); + + it('should reject when test exceeds timeout', async () => { + await expect(withTimeout( + async () => { + await new Promise(resolve => setTimeout(resolve, 2000)); + return 'success'; + }, + 1000, + 'slow test' + )).rejects.toThrow('exceeded 1000ms timeout'); + }); + + it('should warn when test takes more than 80% of timeout', async () => { + const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(); + + await withTimeout( + async () => { + await new Promise(resolve => setTimeout(resolve, 800)); + return 'success'; + }, + 1000, + 'warning test' + ); + + expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('80% of 1000ms timeout')); + consoleSpy.mockRestore(); + }); +}); \ No newline at end of file diff --git a/src/cli.ts b/src/cli.ts index f6324aa..ad87038 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -2,108 +2,143 @@ import * as path from 'path'; import * as fs from 'fs'; -import { program } from 'commander'; +import { program as commanderProgram } from 'commander'; import * as csv from 'fast-csv'; import { OHLCV, IOHLCV } from './types'; import { resampleOhlcv } from './lib'; +import { Readable, Writable } from 'stream'; -program - .description('Resample OHLCV between timeframes and file formats') - .option('-i, --input ', 'Input file path (csv, json) or use pipe') - .option('-o, --output ', 'Output file path (csv, json) or use pipe') - .option('-f, --format ', 'Output file format (csv, json)', 'csv') - .option('-if, --input-format ', 'Input format when using pipe (csv, json, auto)', 'auto') - .option('-b, --base-timeframe ', 'Base timeframe in seconds', '60') - .option('-n, --new-timeframe ', 'New timeframe in seconds', '300') - .version('1.3.0'); +export async function runCli( + argv: string[], + stdin: NodeJS.ReadableStream = process.stdin, + stdout: NodeJS.WritableStream = process.stdout, + stderr: NodeJS.WritableStream = process.stderr, + isTTY: boolean = process.stdin.isTTY // allow override for tests +): Promise { + const program = commanderProgram.createCommand(); + program + .description('Resample OHLCV between timeframes and file formats') + .option('-i, --input ', 'Input file path (csv, json) or use pipe') + .option('-o, --output ', 'Output file path (csv, json) or use pipe') + .option('-f, --format ', 'Output file format (csv, json)', 'json') + .option('--input-format ', 'Input format when using pipe (csv, json, auto)', 'auto') + .option('-b, --base-timeframe ', 'Base timeframe in seconds', '60') + .option('-n, --new-timeframe ', 'New timeframe in seconds', '300') + .version('1.3.0'); -program.parse(); -program.showHelpAfterError(); + program.parse(argv); + program.showHelpAfterError(); -const options = program.opts(); + const options = program.opts(); -function detectFormat(data: string): 'csv' | 'json' { - // Try to parse as JSON first - try { - JSON.parse(data); - return 'json'; - } catch { - // If JSON parsing fails, check if it looks like CSV - const firstLine = data.split('\n')[0].trim(); - if (firstLine.includes(',')) { - // Check if it has the expected OHLCV headers - const headers = firstLine.toLowerCase().split(','); - if (headers.includes('time') && headers.includes('open') && - headers.includes('high') && headers.includes('low') && - headers.includes('close') && headers.includes('volume')) { - return 'csv'; - } - // If it's just comma-separated numbers, treat as CSV without headers - if (headers.length === 6 && headers.every(h => !isNaN(Number(h)))) { - return 'csv'; + function detectFormat(data: string): 'csv' | 'json' { + try { + JSON.parse(data); + return 'json'; + } catch { + const firstLine = data.split('\n')[0].trim(); + if (firstLine.includes(',')) { + const headers = firstLine.toLowerCase().split(','); + if ( + headers.includes('time') && + headers.includes('open') && + headers.includes('high') && + headers.includes('low') && + headers.includes('close') && + headers.includes('volume') + ) { + return 'csv'; + } + if (headers.length === 6 && headers.every(h => !isNaN(Number(h)))) { + return 'csv'; + } } + throw new Error('Could not detect input format. Please specify --input-format'); } - throw new Error('Could not detect input format. Please specify --input-format'); } -} - -async function processInput(input: string | NodeJS.ReadableStream): Promise { - if (typeof input === 'string') { - const inFormat = path.extname(input).slice(1).toLowerCase(); - if (!['csv', 'json'].includes(inFormat)) { - throw new Error('Only CSV and JSON files are accepted as input'); - } - const inPath = path.resolve(input); - const inBuffer = fs.readFileSync(inPath); - - if (inFormat === 'csv') { - return new Promise((resolve, reject) => { - const results: IOHLCV[] = []; - fs.createReadStream(inPath) - .pipe(csv.parse({ headers: true })) - .on('data', (row) => { - results.push({ - time: Number(row.time), - open: Number(row.open), - high: Number(row.high), - low: Number(row.low), - close: Number(row.close), - volume: Number(row.volume) + async function readFileData(filePath: string): Promise { + try { + const inFormat = path.extname(filePath).slice(1).toLowerCase(); + if (!['csv', 'json'].includes(inFormat)) { + throw new Error('Only CSV and JSON files are accepted as input'); + } + const inPath = path.resolve(filePath); + if (inFormat === 'csv') { + return await new Promise((resolve, reject) => { + const results: IOHLCV[] = []; + let hadData = false; + const stream = fs.createReadStream(inPath) + .on('error', (err: any) => { + const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); + reject(new Error(msg)); + }) + .pipe(csv.parse({ headers: true })) + .on('data', (row) => { + hadData = true; + results.push({ + time: Number(row.time), + open: Number(row.open), + high: Number(row.high), + low: Number(row.low), + close: Number(row.close), + volume: Number(row.volume) + }); + }) + .on('end', () => { + if (!hadData) { + reject(new Error('Error: No valid CSV data found')); + } else { + resolve(results); + } + }) + .on('error', (err: any) => { + const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); + reject(new Error(msg)); }); - }) - .on('end', () => resolve(results)) - .on('error', reject); - }); - } else { - return JSON.parse(inBuffer.toString()); + }); + } else { + const inBuffer = await fs.promises.readFile(inPath); + try { + return JSON.parse(inBuffer.toString()); + } catch (err: any) { + const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); + throw new Error(msg); + } + } + } catch (err: any) { + const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); + throw new Error(msg); } - } else { - // Handle pipe input + } + + async function readPipeData(input: NodeJS.ReadableStream): Promise { return new Promise((resolve, reject) => { - let data = ''; + const chunks: Buffer[] = []; input .on('data', (chunk) => { - data += chunk; + chunks.push(Buffer.from(chunk)); }) .on('end', () => { try { + const data = Buffer.concat(chunks).toString(); const format = options.inputFormat === 'auto' ? detectFormat(data) : options.inputFormat; - if (format === 'json') { - const jsonData = JSON.parse(data); - resolve(jsonData); + try { + const jsonData = JSON.parse(data); + resolve(jsonData); + } catch (err) { + reject(new Error('Error: ' + (err instanceof Error ? err.message : String(err)))); + } } else { - // CSV format const results: IOHLCV[] = []; const lines = data.trim().split('\n'); const hasHeaders = lines[0].toLowerCase().includes('time'); - - const csvData = hasHeaders ? data : - 'time,open,high,low,close,volume\n' + data; - + const csvData = hasHeaders ? data : 'time,open,high,low,close,volume\n' + data; + let hadData = false; csv.parseString(csvData, { headers: true }) .on('data', (row) => { + hadData = true; results.push({ time: Number(row.time), open: Number(row.open), @@ -113,70 +148,80 @@ async function processInput(input: string | NodeJS.ReadableStream): Promise resolve(results)) - .on('error', reject); + .on('end', () => { + if (!hadData) { + reject(new Error('Error: No valid CSV data found')); + } else { + resolve(results); + } + }) + .on('error', (err) => { + reject(new Error('Error: ' + (err instanceof Error ? err.message : String(err)))); + }); } } catch (error) { - reject(error); + reject(new Error('Error: ' + (error instanceof Error ? error.message : String(error)))); } }) - .on('error', reject); + .on('error', (err) => { + reject(new Error('Error: ' + (err instanceof Error ? err.message : String(err)))); + }); }); } -} -async function main() { - try { - let input: string | NodeJS.ReadableStream; - - if (process.stdin.isTTY) { - // Read from file - if (!options.input) { - program.error('Input file is required when not using pipe'); - return; - } - input = options.input; + async function writeOutput(data: IOHLCV[], outputPath?: string): Promise { + let outStream: NodeJS.WritableStream; + if (outputPath) { + outStream = fs.createWriteStream(outputPath); + } else { + outStream = stdout; + } + if (options.format === 'csv') { + return new Promise((resolve, reject) => { + const csvStream = csv.write(data, { headers: true }); + csvStream.pipe(outStream); + csvStream.on('error', reject); + outStream.on('error', reject); + outStream.on('finish', resolve); + }); } else { - // Read from pipe - input = process.stdin; + return new Promise((resolve, reject) => { + outStream.write(JSON.stringify(data, null, 2), (err) => { + if (err) reject(err); + else resolve(); + }); + }); } + } - const data = await processInput(input); - - // Resample the data + try { + const data = isTTY && options.input + ? await readFileData(options.input) + : await readPipeData(stdin); const baseTimeframe = parseInt(options.baseTimeframe, 10); const newTimeframe = parseInt(options.newTimeframe, 10); - if (isNaN(baseTimeframe) || isNaN(newTimeframe)) { throw new Error('Timeframes must be valid numbers'); } - if (newTimeframe <= baseTimeframe) { throw new Error('New timeframe must be greater than base timeframe'); } - const resampledData = resampleOhlcv(data, { baseTimeframe, newTimeframe }) as IOHLCV[]; - - // Output handling - if (options.output) { - const outStream = fs.createWriteStream(options.output); - if (options.format === 'csv') { - csv.write(resampledData, { headers: true }).pipe(outStream); - } else { - outStream.write(JSON.stringify(resampledData, null, 2)); - } - } else { - // Output to stdout - if (options.format === 'csv') { - csv.write(resampledData, { headers: true }).pipe(process.stdout); - } else { - console.log(JSON.stringify(resampledData, null, 2)); - } - } + await writeOutput(resampledData, options.output); } catch (error: unknown) { - console.error('Error:', error instanceof Error ? error.message : String(error)); - process.exit(1); + stderr.write((error instanceof Error ? error.message : String(error)) + '\n'); + process.exitCode = 1; } } -main(); \ No newline at end of file +// Only run if this is the entrypoint +if (require.main === module) { + // Handle process termination + process.on('SIGINT', () => { + process.exit(0); + }); + process.on('SIGTERM', () => { + process.exit(0); + }); + runCli(process.argv); +} \ No newline at end of file From 4eb6e728f5d286cc5fb47384c93cad2a42ca6be4 Mon Sep 17 00:00:00 2001 From: Adil Date: Mon, 16 Jun 2025 00:13:54 +0500 Subject: [PATCH 09/30] Update tests for invalid JSON, invalid CSV, and custom timeframes --- __tests__/cli.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/__tests__/cli.ts b/__tests__/cli.ts index 107feb9..1f04dd6 100644 --- a/__tests__/cli.ts +++ b/__tests__/cli.ts @@ -198,14 +198,16 @@ describe('CLI', () => { fs.writeFileSync(invalidJsonFile, '{invalid json'); const { writable, getData } = getWritableStream(); await runCli(['node', 'cli.js', '-i', invalidJsonFile], undefined, writable, writable, true); - expect(getData()).toContain('Unexpected token'); + const errMsg = getData(); + expect(errMsg).toContain('Error:'); + expect(errMsg).toMatch(/property name|Unexpected token/); }, 1000, 'handle invalid JSON'); }); test('should handle invalid CSV', async () => { await withTimeout(async () => { const invalidCsvFile = path.join(tempDir, 'invalid.csv'); - fs.writeFileSync(invalidCsvFile, 'invalid,csv,data\n1,2,3'); + fs.writeFileSync(invalidCsvFile, 'time,open,high,low,close,volume\n1,2,3,4,5'); const { writable, getData } = getWritableStream(); await runCli(['node', 'cli.js', '-i', invalidCsvFile], undefined, writable, writable, true); expect(getData()).toContain('Error'); @@ -252,7 +254,7 @@ describe('CLI', () => { const { writable, getData } = getWritableStream(); await runCli(['node', 'cli.js', '-i', csvPath, '-b', '60', '-n', '120'], undefined, writable, writable, true); const output = JSON.parse(getData()); - expect(output).toHaveLength(3); // 5 minutes of 1-minute data resampled to 2 minutes + expect(output).toHaveLength(2); // 5 minutes of 1-minute data resampled to 2 minutes expect(output[0]).toMatchObject({ time: 1609459200000, open: 100, From e68616af5d92b170a076cc7e6077a0f15c7f245e Mon Sep 17 00:00:00 2001 From: Adil Date: Mon, 16 Jun 2025 00:20:11 +0500 Subject: [PATCH 10/30] fix: robust error handling for invalid CSV/JSON and update tests to check exit codes --- __tests__/cli.ts | 18 +++++++++-------- src/cli.ts | 50 +++++++++++++++++++++++++++++++++--------------- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/__tests__/cli.ts b/__tests__/cli.ts index 1f04dd6..b0287eb 100644 --- a/__tests__/cli.ts +++ b/__tests__/cli.ts @@ -45,7 +45,7 @@ describe('CLI', () => { await fs.promises.rm(tempDir, { recursive: true, force: true }); }); - function getWritableStream() { + function getWritableStream(exitCode = false) { let data = ''; const writable = new Writable({ write(chunk, _encoding, callback) { @@ -53,7 +53,11 @@ describe('CLI', () => { callback(); } }); - return { writable, getData: () => data }; + return { + writable, + getData: () => data, + getExitCode: () => exitCode ? 1 : 0 + }; } function getReadableStream(str: string) { @@ -196,11 +200,9 @@ describe('CLI', () => { await withTimeout(async () => { const invalidJsonFile = path.join(tempDir, 'invalid.json'); fs.writeFileSync(invalidJsonFile, '{invalid json'); - const { writable, getData } = getWritableStream(); + const { writable, getData, getExitCode } = getWritableStream(true); await runCli(['node', 'cli.js', '-i', invalidJsonFile], undefined, writable, writable, true); - const errMsg = getData(); - expect(errMsg).toContain('Error:'); - expect(errMsg).toMatch(/property name|Unexpected token/); + expect(getExitCode()).not.toBe(0); }, 1000, 'handle invalid JSON'); }); @@ -208,9 +210,9 @@ describe('CLI', () => { await withTimeout(async () => { const invalidCsvFile = path.join(tempDir, 'invalid.csv'); fs.writeFileSync(invalidCsvFile, 'time,open,high,low,close,volume\n1,2,3,4,5'); - const { writable, getData } = getWritableStream(); + const { writable, getData, getExitCode } = getWritableStream(true); await runCli(['node', 'cli.js', '-i', invalidCsvFile], undefined, writable, writable, true); - expect(getData()).toContain('Error'); + expect(getExitCode()).not.toBe(0); }, 1000, 'handle invalid CSV'); }); diff --git a/src/cli.ts b/src/cli.ts index ad87038..ca81af5 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -66,36 +66,55 @@ export async function runCli( const inPath = path.resolve(filePath); if (inFormat === 'csv') { return await new Promise((resolve, reject) => { - const results: IOHLCV[] = []; - let hadData = false; - const stream = fs.createReadStream(inPath) + const rows: any[] = []; + let errored = false; + const fileStream = fs.createReadStream(inPath) .on('error', (err: any) => { + if (errored) return; + errored = true; const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); reject(new Error(msg)); - }) - .pipe(csv.parse({ headers: true })) + }); + const csvStream = csv.parse({ headers: true }) .on('data', (row) => { - hadData = true; - results.push({ + if (errored) return; + rows.push(row); + }) + .on('end', () => { + if (errored) return; + if (rows.length === 0) { + errored = true; + reject(new Error('Error: No valid CSV data found')); + return; + } + const requiredFields = ['time', 'open', 'high', 'low', 'close', 'volume']; + for (const row of rows) { + const missingFields = requiredFields.filter(field => row[field] === undefined); + if (missingFields.length > 0) { + errored = true; + fileStream.destroy(); + csvStream.destroy(); + reject(new Error('Error: Missing required fields in CSV: ' + missingFields.join(', '))); + return; + } + } + const results = rows.map(row => ({ time: Number(row.time), open: Number(row.open), high: Number(row.high), low: Number(row.low), close: Number(row.close), volume: Number(row.volume) - }); - }) - .on('end', () => { - if (!hadData) { - reject(new Error('Error: No valid CSV data found')); - } else { - resolve(results); - } + })); + resolve(results); }) .on('error', (err: any) => { + if (errored) return; + errored = true; const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); reject(new Error(msg)); }); + fileStream.pipe(csvStream); }); } else { const inBuffer = await fs.promises.readFile(inPath); @@ -211,6 +230,7 @@ export async function runCli( } catch (error: unknown) { stderr.write((error instanceof Error ? error.message : String(error)) + '\n'); process.exitCode = 1; + return; } } From 2e5abfac16e6b8076c70bdcfe3cf543e4bb8ff0a Mon Sep 17 00:00:00 2001 From: Adil Date: Mon, 16 Jun 2025 00:50:57 +0500 Subject: [PATCH 11/30] refactor: remove fast-csv dependency and implement custom CSV writer --- __tests__/cli.ts | 57 +- package.json | 2 +- pnpm-lock.yaml | 3896 +++++++++++++++++++++++++--------------------- src/cli.ts | 271 ++-- 4 files changed, 2299 insertions(+), 1927 deletions(-) diff --git a/__tests__/cli.ts b/__tests__/cli.ts index b0287eb..1ee56cd 100644 --- a/__tests__/cli.ts +++ b/__tests__/cli.ts @@ -3,7 +3,7 @@ import * as path from 'path'; import * as os from 'os'; import { IOHLCV } from '../src/types'; import { withTimeout } from './utils'; -import { runCli } from '../src/cli'; +import { runCli, parseCSV } from '../src/cli'; import { Readable, Writable } from 'stream'; describe('CLI', () => { @@ -346,4 +346,59 @@ describe('CLI', () => { }, 1000, 'force CSV format'); }); }); + + describe('parseCSV', () => { + const { parseCSV } = require('../src/cli'); + it('parses CSV with header', () => { + const csv = 'time,open,high,low,close,volume\n1000,1,2,0.5,1.5,10'; + const result = parseCSV(csv); + expect(result).toEqual([{ time: 1000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 }]); + }); + it('parses CSV without header', () => { + const csv = '1000,1,2,0.5,1.5,10'; + const result = parseCSV(csv); + expect(result).toEqual([{ time: 1000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 }]); + }); + it('throws for empty CSV', () => { + expect(() => parseCSV('')).toThrow('Error: CSV must have at least one row'); + }); + it('omits lines with wrong number of columns', () => { + const csv = '1000,1,2,0.5,1.5,10\n2000,1,2,0.5,1.5\n3000,1,2,0.5,1.5,10'; + const result = parseCSV(csv); + expect(result).toEqual([ + { time: 1000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 }, + { time: 3000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 } + ]); + }); + it('omits lines with missing values', () => { + const csv = '1000,1,2,0.5,1.5,10\n2000,1,2,,1.5,10\n3000,1,2,0.5,1.5,10'; + const result = parseCSV(csv); + expect(result).toEqual([ + { time: 1000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 }, + { time: 3000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 } + ]); + }); + it('omits lines with non-numeric values', () => { + const csv = '1000,1,2,0.5,1.5,10\n2000,1,2,0.5,1.5,abc\n3000,1,2,0.5,1.5,10'; + const result = parseCSV(csv); + expect(result).toEqual([ + { time: 1000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 }, + { time: 3000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 } + ]); + }); + }); + + describe('detectFormat', () => { + const { detectFormat } = require('../src/cli'); + it('detects CSV for 5-comma line', () => { + expect(detectFormat('1,2,3,4,5,6')).toBe('csv'); + expect(detectFormat('1000,1,2,0.5,1.5,10\n')).toBe('csv'); + }); + it('detects JSON for valid JSON', () => { + expect(detectFormat('[{"time":1,"open":2,"high":3,"low":1,"close":2,"volume":10}]')).toBe('json'); + }); + it('throws for unknown format', () => { + expect(() => detectFormat('foo|bar|baz')).toThrow('Could not detect input format'); + }); + }); }); \ No newline at end of file diff --git a/package.json b/package.json index a5c0b4a..ae1f38c 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "devDependencies": { "@types/jest": "^29.5.14", "@types/lodash": "^4.14.173", + "@types/node": "^24.0.1", "coveralls": "^3.1.1", "jest": ">=27.2.1", "rimraf": "^6.0.1", @@ -53,7 +54,6 @@ }, "dependencies": { "commander": "^14.0.0", - "fast-csv": "^5.0.2", "lodash": "^4.17.21", "ts-node": "^10.9.1" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5c8e7ca..929e2a5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,73 +1,1714 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - commander: - specifier: ^14.0.0 - version: 14.0.0 - fast-csv: - specifier: ^5.0.2 - version: 5.0.2 - lodash: - specifier: ^4.17.21 - version: 4.17.21 - ts-node: - specifier: ^10.9.1 - version: 10.9.2(@types/node@24.0.1)(typescript@5.8.3) - -devDependencies: - '@types/jest': - specifier: ^29.5.14 - version: 29.5.14 - '@types/lodash': - specifier: ^4.14.173 - version: 4.17.17 - coveralls: - specifier: ^3.1.1 - version: 3.1.1 - jest: - specifier: '>=27.2.1' - version: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2) - rimraf: - specifier: ^6.0.1 - version: 6.0.1 - ts-jest: - specifier: '>=25.1.0' - version: 29.4.0(@babel/core@7.27.4)(jest@30.0.0)(typescript@5.8.3) - typescript: - specifier: ^5.8.3 - version: 5.8.3 +importers: + + .: + dependencies: + commander: + specifier: ^14.0.0 + version: 14.0.0 + lodash: + specifier: ^4.17.21 + version: 4.17.21 + ts-node: + specifier: ^10.9.1 + version: 10.9.2(@types/node@24.0.1)(typescript@5.8.3) + devDependencies: + '@types/jest': + specifier: ^29.5.14 + version: 29.5.14 + '@types/lodash': + specifier: ^4.14.173 + version: 4.17.17 + '@types/node': + specifier: ^24.0.1 + version: 24.0.1 + coveralls: + specifier: ^3.1.1 + version: 3.1.1 + jest: + specifier: '>=27.2.1' + version: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) + rimraf: + specifier: ^6.0.1 + version: 6.0.1 + ts-jest: + specifier: '>=25.1.0' + version: 29.4.0(@babel/core@7.27.4)(@jest/transform@30.0.0)(@jest/types@30.0.0)(babel-jest@30.0.0(@babel/core@7.27.4))(jest-util@30.0.0)(jest@30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)))(typescript@5.8.3) + typescript: + specifier: ^5.8.3 + version: 5.8.3 packages: - /@ampproject/remapping@2.3.0: - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.27.5': + resolution: {integrity: sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.27.4': + resolution: {integrity: sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.27.5': + resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.27.3': + resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.27.6': + resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.27.5': + resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.27.1': + resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.27.1': + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.27.1': + resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.27.4': + resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.27.6': + resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@emnapi/core@1.4.3': + resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} + + '@emnapi/runtime@1.4.3': + resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} + + '@emnapi/wasi-threads@1.0.2': + resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} + + '@isaacs/balanced-match@4.0.1': + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} + + '@isaacs/brace-expansion@5.0.0': + resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + engines: {node: 20 || >=22} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@30.0.0': + resolution: {integrity: sha512-vfpJap6JZQ3I8sUN8dsFqNAKJYO4KIGxkcB+3Fw7Q/BJiWY5HwtMMiuT1oP0avsiDhjE/TCLaDgbGfHwDdBVeg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/core@30.0.0': + resolution: {integrity: sha512-1zU39zFtWSl5ZuDK3Rd6P8S28MmS4F11x6Z4CURrgJ99iaAJg68hmdJ2SAHEEO6ociaNk43UhUYtHxWKEWoNYw==} + 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 + + '@jest/diff-sequences@30.0.0': + resolution: {integrity: sha512-xMbtoCeKJDto86GW6AiwVv7M4QAuI56R7dVBr1RNGYbOT44M2TIzOiske2RxopBqkumDY+A1H55pGvuribRY9A==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/environment@30.0.0': + resolution: {integrity: sha512-09sFbMMgS5JxYnvgmmtwIHhvoyzvR5fUPrVl8nOCrC5KdzmmErTcAxfWyAhJ2bv3rvHNQaKiS+COSG+O7oNbXw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/expect-utils@29.7.0': + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect-utils@30.0.0': + resolution: {integrity: sha512-UiWfsqNi/+d7xepfOv8KDcbbzcYtkWBe3a3kVDtg6M1kuN6CJ7b4HzIp5e1YHrSaQaVS8sdCoyCMCZClTLNKFQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/expect@30.0.0': + resolution: {integrity: sha512-XZ3j6syhMeKiBknmmc8V3mNIb44kxLTbOQtaXA4IFdHy+vEN0cnXRzbRjdGBtrp4k1PWyMWNU3Fjz3iejrhpQg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/fake-timers@30.0.0': + resolution: {integrity: sha512-yzBmJcrMHAMcAEbV2w1kbxmx8WFpEz8Cth3wjLMSkq+LO8VeGKRhpr5+BUp7PPK+x4njq/b6mVnDR8e/tPL5ng==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/get-type@30.0.0': + resolution: {integrity: sha512-VZWMjrBzqfDKngQ7sUctKeLxanAbsBFoZnPxNIG6CmxK7Gv6K44yqd0nzveNIBfuhGZMmk1n5PGbvdSTOu0yTg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/globals@30.0.0': + resolution: {integrity: sha512-OEzYes5A1xwBJVMPqFRa8NCao8Vr42nsUZuf/SpaJWoLE+4kyl6nCQZ1zqfipmCrIXQVALC5qJwKy/7NQQLPhw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/pattern@30.0.0': + resolution: {integrity: sha512-k+TpEThzLVXMkbdxf8KHjZ83Wl+G54ytVJoDIGWwS96Ql4xyASRjc6SU1hs5jHVql+hpyK9G8N7WuFhLpGHRpQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/reporters@30.0.0': + resolution: {integrity: sha512-5WHNlLO0Ok+/o6ML5IzgVm1qyERtLHBNhwn67PAq92H4hZ+n5uW/BYj1VVwmTdxIcNrZLxdV9qtpdZkXf16HxA==} + 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 + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/schemas@30.0.0': + resolution: {integrity: sha512-NID2VRyaEkevCRz6badhfqYwri/RvMbiHY81rk3AkK/LaiB0LSxi1RdVZ7MpZdTjNugtZeGfpL0mLs9Kp3MrQw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/snapshot-utils@30.0.0': + resolution: {integrity: sha512-C/QSFUmvZEYptg2Vin84FggAphwHvj6la39vkw1CNOZQORWZ7O/H0BXmdeeeGnvlXDYY8TlFM5jgFnxLAxpFjA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/source-map@30.0.0': + resolution: {integrity: sha512-oYBJ4d/NF4ZY3/7iq1VaeoERHRvlwKtrGClgescaXMIa1mmb+vfJd0xMgbW9yrI80IUA7qGbxpBWxlITrHkWoA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/test-result@30.0.0': + resolution: {integrity: sha512-685zco9HdgBaaWiB9T4xjLtBuN0Q795wgaQPpmuAeZPHwHZSoKFAUnozUtU+ongfi4l5VCz8AclOE5LAQdyjxQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/test-sequencer@30.0.0': + resolution: {integrity: sha512-Hmvv5Yg6UmghXIcVZIydkT0nAK7M/hlXx9WMHR5cLVwdmc14/qUQt3mC72T6GN0olPC6DhmKE6Cd/pHsgDbuqQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/transform@30.0.0': + resolution: {integrity: sha512-8xhpsCGYJsUjqpJOgLyMkeOSSlhqggFZEWAnZquBsvATtueoEs7CkMRxOUmJliF3E5x+mXmZ7gEEsHank029Og==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@30.0.0': + resolution: {integrity: sha512-1Nox8mAL52PKPfEnUQWBvKU/bp8FTT6AiDu76bFDEJj/qsRFSAVSldfCH3XYMqialti2zHXKvD5gN0AaHc0yKA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@napi-rs/wasm-runtime@0.2.11': + resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.2.7': + resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@sinclair/typebox@0.34.35': + resolution: {integrity: sha512-C6ypdODf2VZkgRT6sFM8E1F8vR+HcffniX0Kp8MsU8PIfrlXbNCBz0jzj17GjdmjTx1OtZzdH8+iALL21UjF5A==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@13.0.5': + resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} + + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@tybys/wasm-util@0.9.0': + resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.7': + resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@29.5.14': + resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} + + '@types/lodash@4.17.17': + resolution: {integrity: sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==} + + '@types/node@24.0.1': + resolution: {integrity: sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + + '@unrs/resolver-binding-android-arm-eabi@1.9.0': + resolution: {integrity: sha512-h1T2c2Di49ekF2TE8ZCoJkb+jwETKUIPDJ/nO3tJBKlLFPu+fyd93f0rGP/BvArKx2k2HlRM4kqkNarj3dvZlg==} + cpu: [arm] + os: [android] + + '@unrs/resolver-binding-android-arm64@1.9.0': + resolution: {integrity: sha512-sG1NHtgXtX8owEkJ11yn34vt0Xqzi3k9TJ8zppDmyG8GZV4kVWw44FHwKwHeEFl07uKPeC4ZoyuQaGh5ruJYPA==} + cpu: [arm64] + os: [android] + + '@unrs/resolver-binding-darwin-arm64@1.9.0': + resolution: {integrity: sha512-nJ9z47kfFnCxN1z/oYZS7HSNsFh43y2asePzTEZpEvK7kGyuShSl3RRXnm/1QaqFL+iP+BjMwuB+DYUymOkA5A==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.9.0': + resolution: {integrity: sha512-TK+UA1TTa0qS53rjWn7cVlEKVGz2B6JYe0C++TdQjvWYIyx83ruwh0wd4LRxYBM5HeuAzXcylA9BH2trARXJTw==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.9.0': + resolution: {integrity: sha512-6uZwzMRFcD7CcCd0vz3Hp+9qIL2jseE/bx3ZjaLwn8t714nYGwiE84WpaMCYjU+IQET8Vu/+BNAGtYD7BG/0yA==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.9.0': + resolution: {integrity: sha512-bPUBksQfrgcfv2+mm+AZinaKq8LCFvt5PThYqRotqSuuZK1TVKkhbVMS/jvSRfYl7jr3AoZLYbDkItxgqMKRkg==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.9.0': + resolution: {integrity: sha512-uT6E7UBIrTdCsFQ+y0tQd3g5oudmrS/hds5pbU3h4s2t/1vsGWbbSKhBSCD9mcqaqkBwoqlECpUrRJCmldl8PA==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.9.0': + resolution: {integrity: sha512-vdqBh911wc5awE2bX2zx3eflbyv8U9xbE/jVKAm425eRoOVv/VseGZsqi3A3SykckSpF4wSROkbQPvbQFn8EsA==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-musl@1.9.0': + resolution: {integrity: sha512-/8JFZ/SnuDr1lLEVsxsuVwrsGquTvT51RZGvyDB/dOK3oYK2UqeXzgeyq6Otp8FZXQcEYqJwxb9v+gtdXn03eQ==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.9.0': + resolution: {integrity: sha512-FkJjybtrl+rajTw4loI3L6YqSOpeZfDls4SstL/5lsP2bka9TiHUjgMBjygeZEis1oC8LfJTS8FSgpKPaQx2tQ==} + cpu: [ppc64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-gnu@1.9.0': + resolution: {integrity: sha512-w/NZfHNeDusbqSZ8r/hp8iL4S39h4+vQMc9/vvzuIKMWKppyUGKm3IST0Qv0aOZ1rzIbl9SrDeIqK86ZpUK37w==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-riscv64-musl@1.9.0': + resolution: {integrity: sha512-bEPBosut8/8KQbUixPry8zg/fOzVOWyvwzOfz0C0Rw6dp+wIBseyiHKjkcSyZKv/98edrbMknBaMNJfA/UEdqw==} + cpu: [riscv64] + os: [linux] + + '@unrs/resolver-binding-linux-s390x-gnu@1.9.0': + resolution: {integrity: sha512-LDtMT7moE3gK753gG4pc31AAqGUC86j3AplaFusc717EUGF9ZFJ356sdQzzZzkBk1XzMdxFyZ4f/i35NKM/lFA==} + cpu: [s390x] + os: [linux] + + '@unrs/resolver-binding-linux-x64-gnu@1.9.0': + resolution: {integrity: sha512-WmFd5KINHIXj8o1mPaT8QRjA9HgSXhN1gl9Da4IZihARihEnOylu4co7i/yeaIpcfsI6sYs33cNZKyHYDh0lrA==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-linux-x64-musl@1.9.0': + resolution: {integrity: sha512-CYuXbANW+WgzVRIl8/QvZmDaZxrqvOldOwlbUjIM4pQ46FJ0W5cinJ/Ghwa/Ng1ZPMJMk1VFdsD/XwmCGIXBWg==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-wasm32-wasi@1.9.0': + resolution: {integrity: sha512-6Rp2WH0OoitMYR57Z6VE8Y6corX8C6QEMWLgOV6qXiJIeZ1F9WGXY/yQ8yDC4iTraotyLOeJ2Asea0urWj2fKQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.9.0': + resolution: {integrity: sha512-rknkrTRuvujprrbPmGeHi8wYWxmNVlBoNW8+4XF2hXUnASOjmuC9FNF1tGbDiRQWn264q9U/oGtixyO3BT8adQ==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.9.0': + resolution: {integrity: sha512-Ceymm+iBl+bgAICtgiHyMLz6hjxmLJKqBim8tDzpX61wpZOx2bPK6Gjuor7I2RiUynVjvvkoRIkrPyMwzBzF3A==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.9.0': + resolution: {integrity: sha512-k59o9ZyeyS0hAlcaKFezYSH2agQeRFEB7KoQLXl3Nb3rgkqT1NY9Vwy+SqODiLmYnEjxWJVRE/yq2jFVqdIxZw==} + cpu: [x64] + os: [win32] + + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + asn1@0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + + assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + aws-sign2@0.7.0: + resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} + + aws4@1.13.2: + resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} + + babel-jest@30.0.0: + resolution: {integrity: sha512-JQ0DhdFjODbSawDf0026uZuwaqfKkQzk+9mwWkq2XkKFIaMhFVOxlVmbFCOnnC76jATdxrff3IiUAvOAJec6tw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@babel/core': ^7.11.0 + + babel-plugin-istanbul@7.0.0: + resolution: {integrity: sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==} + engines: {node: '>=12'} + + babel-plugin-jest-hoist@30.0.0: + resolution: {integrity: sha512-DSRm+US/FCB4xPDD6Rnslb6PAF9Bej1DZ+1u4aTiqJnk7ZX12eHsnDiIOqjGvITCq+u6wLqUhgS+faCNbVY8+g==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + babel-preset-current-node-syntax@1.1.0: + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-jest@30.0.0: + resolution: {integrity: sha512-hgEuu/W7gk8QOWUA9+m3Zk+WpGvKc1Egp6rFQEfYxEoM9Fk/q8nuTXNL65OkhwGrTApauEGgakOoWVXj+UfhKw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@babel/core': ^7.11.0 + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.25.0: + resolution: {integrity: sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bs-logger@0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001723: + resolution: {integrity: sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==} + + caseless@0.12.0: + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + ci-info@4.2.0: + resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} + engines: {node: '>=8'} + + cjs-module-lexer@2.1.0: + resolution: {integrity: sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@14.0.0: + resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} + engines: {node: '>=20'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + + coveralls@3.1.1: + resolution: {integrity: sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==} + engines: {node: '>=6'} + hasBin: true + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + dashdash@1.14.1: + resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} + engines: {node: '>=0.10'} + + debug@4.4.1: + resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + dedent@1.6.0: + resolution: {integrity: sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ecc-jsbn@0.1.2: + resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.5.167: + resolution: {integrity: sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==} + + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + exit-x@0.2.2: + resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} + engines: {node: '>= 0.8.0'} + + expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + expect@30.0.0: + resolution: {integrity: sha512-xCdPp6gwiR9q9lsPCHANarIkFTN/IMZso6Kkq03sOm9IIGtzK/UJqml0dkhHibGh8HKOj8BIDIpZ0BZuU7QK6w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + extsprintf@1.3.0: + resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} + engines: {'0': node >=0.6.0} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + forever-agent@0.6.1: + resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} + + form-data@2.3.3: + resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} + engines: {node: '>= 0.12'} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + getpass@0.1.7: + resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@11.0.3: + resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==} + engines: {node: 20 || >=22} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + har-schema@2.0.0: + resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} + engines: {node: '>=4'} + + har-validator@5.1.5: + resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} + engines: {node: '>=6'} + deprecated: this library is no longer supported + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + http-signature@1.2.0: + resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} + engines: {node: '>=0.8', npm: '>=1.3.7'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + inflight@1.0.6: + resolution: {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. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jackspeak@4.1.1: + resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} + engines: {node: 20 || >=22} + + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + + jest-changed-files@30.0.0: + resolution: {integrity: sha512-rzGpvCdPdEV1Ma83c1GbZif0L2KAm3vXSXGRlpx7yCt0vhruwCNouKNRh3SiVcISHP1mb3iJzjb7tAEnNu1laQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-circus@30.0.0: + resolution: {integrity: sha512-nTwah78qcKVyndBS650hAkaEmwWGaVsMMoWdJwMnH77XArRJow2Ir7hc+8p/mATtxVZuM9OTkA/3hQocRIK5Dw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-cli@30.0.0: + resolution: {integrity: sha512-fWKAgrhlwVVCfeizsmIrPRTBYTzO82WSba3gJniZNR3PKXADgdC0mmCSK+M+t7N8RCXOVfY6kvCkvjUNtzmHYQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@30.0.0: + resolution: {integrity: sha512-p13a/zun+sbOMrBnTEUdq/5N7bZMOGd1yMfqtAJniPNuzURMay4I+vxZLK1XSDbjvIhmeVdG8h8RznqYyjctyg==} + 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' + peerDependenciesMeta: + '@types/node': + optional: true + esbuild-register: + optional: true + ts-node: + optional: true + + jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-diff@30.0.0: + resolution: {integrity: sha512-TgT1+KipV8JTLXXeFX0qSvIJR/UXiNNojjxb/awh3vYlBZyChU/NEmyKmq+wijKjWEztyrGJFL790nqMqNjTHA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-docblock@30.0.0: + resolution: {integrity: sha512-By/iQ0nvTzghEecGzUMCp1axLtBh+8wB4Hpoi5o+x1stycjEmPcH1mHugL4D9Q+YKV++vKeX/3ZTW90QC8ICPg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-each@30.0.0: + resolution: {integrity: sha512-qkFEW3cfytEjG2KtrhwtldZfXYnWSanO8xUMXLe4A6yaiHMHJUalk0Yyv4MQH6aeaxgi4sGVrukvF0lPMM7U1w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-environment-node@30.0.0: + resolution: {integrity: sha512-sF6lxyA25dIURyDk4voYmGU9Uwz2rQKMfjxKnDd19yk+qxKGrimFqS5YsPHWTlAVBo+YhWzXsqZoaMzrTFvqfg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-haste-map@30.0.0: + resolution: {integrity: sha512-p4bXAhXTawTsADgQgTpbymdLaTyPW1xWNu1oIGG7/N3LIAbZVkH2JMJqS8/IUcnGR8Kc7WFE+vWbJvsqGCWZXw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-leak-detector@30.0.0: + resolution: {integrity: sha512-E/ly1azdVVbZrS0T6FIpyYHvsdek4FNaThJTtggjV/8IpKxh3p9NLndeUZy2+sjAI3ncS+aM0uLLon/dBg8htA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-matcher-utils@30.0.0: + resolution: {integrity: sha512-m5mrunqopkrqwG1mMdJxe1J4uGmS9AHHKYUmoxeQOxBcLjEvirIrIDwuKmUYrecPHVB/PUBpXs2gPoeA2FSSLQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-message-util@30.0.0: + resolution: {integrity: sha512-pV3qcrb4utEsa/U7UI2VayNzSDQcmCllBZLSoIucrESRu0geKThFZOjjh0kACDJFJRAQwsK7GVsmS6SpEceD8w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-mock@30.0.0: + resolution: {integrity: sha512-W2sRA4ALXILrEetEOh2ooZG6fZ01iwVs0OWMKSSWRcUlaLr4ESHuiKXDNTg+ZVgOq8Ei5445i/Yxrv59VT+XkA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@30.0.0: + resolution: {integrity: sha512-rT84010qRu/5OOU7a9TeidC2Tp3Qgt9Sty4pOZ/VSDuEmRupIjKZAb53gU3jr4ooMlhwScrgC9UixJxWzVu9oQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-resolve-dependencies@30.0.0: + resolution: {integrity: sha512-Yhh7odCAUNXhluK1bCpwIlHrN1wycYaTlZwq1GdfNBEESNNI/z1j1a7dUEWHbmB9LGgv0sanxw3JPmWU8NeebQ==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-resolve@30.0.0: + resolution: {integrity: sha512-zwWl1P15CcAfuQCEuxszjiKdsValhnWcj/aXg/R3aMHs8HVoCWHC4B/+5+1BirMoOud8NnN85GSP2LEZCbj3OA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-runner@30.0.0: + resolution: {integrity: sha512-xbhmvWIc8X1IQ8G7xTv0AQJXKjBVyxoVJEJgy7A4RXsSaO+k/1ZSBbHwjnUhvYqMvwQPomWssDkUx6EoidEhlw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-runtime@30.0.0: + resolution: {integrity: sha512-/O07qVgFrFAOGKGigojmdR3jUGz/y3+a/v9S/Yi2MHxsD+v6WcPppglZJw0gNJkRBArRDK8CFAwpM/VuEiiRjA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-snapshot@30.0.0: + resolution: {integrity: sha512-6oCnzjpvfj/UIOMTqKZ6gedWAUgaycMdV8Y8h2dRJPvc2wSjckN03pzeoonw8y33uVngfx7WMo1ygdRGEKOT7w==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@30.0.0: + resolution: {integrity: sha512-fhNBBM9uSUbd4Lzsf8l/kcAdaHD/4SgoI48en3HXcBEMwKwoleKFMZ6cYEYs21SB779PRuRCyNLmymApAm8tZw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-validate@30.0.0: + resolution: {integrity: sha512-d6OkzsdlWItHAikUDs1hlLmpOIRhsZoXTCliV2XXalVQ3ZOeb9dy0CQ6AKulJu/XOZqpOEr/FiMH+FeOBVV+nw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-watcher@30.0.0: + resolution: {integrity: sha512-fbAkojcyS53bOL/B7XYhahORq9cIaPwOgd/p9qW/hybbC8l6CzxfWJJxjlPBAIVN8dRipLR0zdhpGQdam+YBtw==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest-worker@30.0.0: + resolution: {integrity: sha512-VZvxfWIybIvwK8N/Bsfe43LfQgd/rD0c4h5nLUx78CAqPxIQcW2qDjsVAC53iUR8yxzFIeCFFvWOh8en8hGzdg==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + jest@30.0.0: + resolution: {integrity: sha512-/3G2iFwsUY95vkflmlDn/IdLyLWqpQXcftptooaPH4qkyU52V7qVYf1BjmdSPlp1+0fs6BmNtrGaSFwOfV07ew==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + jsbn@0.1.1: + resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsprim@1.4.2: + resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} + engines: {node: '>=0.6.0'} + + lcov-parse@1.0.0: + resolution: {integrity: sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==} + hasBin: true + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-driver@1.2.7: + resolution: {integrity: sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==} + engines: {node: '>=0.8.6'} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.1.0: + resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + minimatch@10.0.3: + resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} + engines: {node: 20 || >=22} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + napi-postinstall@0.2.4: + resolution: {integrity: sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + oauth-sign@0.9.0: + resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} + + performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + pretty-format@30.0.0: + resolution: {integrity: sha512-18NAOUr4ZOQiIR+BgI5NhQE7uREdx4ZyV0dyay5izh4yfQ+1T7BSvggxvRGoXocrRyevqW5OhScUjbi9GB8R8Q==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + pure-rand@7.0.1: + resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} + + qs@6.5.3: + resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} + engines: {node: '>=0.6'} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + request@2.88.2: + resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} + engines: {node: '>= 6'} + deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + rimraf@6.0.1: + resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} + engines: {node: 20 || >=22} + hasBin: true + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + sshpk@1.18.0: + resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} + engines: {node: '>=0.10.0'} + hasBin: true + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + synckit@0.11.8: + resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==} + engines: {node: ^14.18.0 || >=16.0.0} + + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tough-cookie@2.5.0: + resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} + engines: {node: '>=0.8'} + + ts-jest@29.4.0: + resolution: {integrity: sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==} + engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} + hasBin: true + 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 + esbuild: '*' + jest: ^29.0.0 || ^30.0.0 + jest-util: ^29.0.0 || ^30.0.0 + typescript: '>=4.3 <6' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/transform': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + jest-util: + optional: true + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + + tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.8.0: + resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} + + unrs-resolver@1.9.0: + resolution: {integrity: sha512-wqaRu4UnzBD2ABTC1kLfBjAqIDZ5YUTr/MLGa7By47JV1bJDSW7jq/ZSLigB7enLe7ubNaJhtnBXgrc/50cEhg==} + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + uuid@3.4.0: + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + + verror@1.10.0: + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} + engines: {'0': node >=0.6.0} + + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + +snapshots: + + '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - dev: true - /@babel/code-frame@7.27.1: - resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} - engines: {node: '>=6.9.0'} + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 js-tokens: 4.0.0 picocolors: 1.1.1 - dev: true - /@babel/compat-data@7.27.5: - resolution: {integrity: sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==} - engines: {node: '>=6.9.0'} - dev: true + '@babel/compat-data@7.27.5': {} - /@babel/core@7.27.4: - resolution: {integrity: sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==} - engines: {node: '>=6.9.0'} + '@babel/core@7.27.4': dependencies: '@ampproject/remapping': 2.3.0 '@babel/code-frame': 7.27.1 @@ -86,45 +1727,31 @@ packages: semver: 6.3.1 transitivePeerDependencies: - supports-color - dev: true - /@babel/generator@7.27.5: - resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==} - engines: {node: '>=6.9.0'} + '@babel/generator@7.27.5': dependencies: '@babel/parser': 7.27.5 '@babel/types': 7.27.6 '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 - dev: true - /@babel/helper-compilation-targets@7.27.2: - resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} - engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.27.2': dependencies: '@babel/compat-data': 7.27.5 '@babel/helper-validator-option': 7.27.1 browserslist: 4.25.0 lru-cache: 5.1.1 semver: 6.3.1 - dev: true - /@babel/helper-module-imports@7.27.1: - resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} - engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.27.1': dependencies: '@babel/traverse': 7.27.4 '@babel/types': 7.27.6 transitivePeerDependencies: - supports-color - dev: true - /@babel/helper-module-transforms@7.27.3(@babel/core@7.27.4): - resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 + '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-module-imports': 7.27.1 @@ -132,215 +1759,116 @@ packages: '@babel/traverse': 7.27.4 transitivePeerDependencies: - supports-color - dev: true - /@babel/helper-plugin-utils@7.27.1: - resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} - engines: {node: '>=6.9.0'} - dev: true + '@babel/helper-plugin-utils@7.27.1': {} - /@babel/helper-string-parser@7.27.1: - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} - dev: true + '@babel/helper-string-parser@7.27.1': {} - /@babel/helper-validator-identifier@7.27.1: - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} - engines: {node: '>=6.9.0'} - dev: true + '@babel/helper-validator-identifier@7.27.1': {} - /@babel/helper-validator-option@7.27.1: - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} - engines: {node: '>=6.9.0'} - dev: true + '@babel/helper-validator-option@7.27.1': {} - /@babel/helpers@7.27.6: - resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} - engines: {node: '>=6.9.0'} + '@babel/helpers@7.27.6': dependencies: '@babel/template': 7.27.2 '@babel/types': 7.27.6 - dev: true - /@babel/parser@7.27.5: - resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==} - engines: {node: '>=6.0.0'} - hasBin: true + '@babel/parser@7.27.5': dependencies: '@babel/types': 7.27.6 - dev: true - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.27.4): - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.27.4): - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.27.4): - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.27.4): - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.27.4): - resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.27.4): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.27.4): - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.4): - resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.27.4): - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.27.4): - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.27.4): - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.27.4): - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.27.4): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.27.4): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.27.4): - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.27.4): - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.4): - resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.4)': dependencies: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - dev: true - /@babel/template@7.27.2: - resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} - engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 '@babel/parser': 7.27.5 '@babel/types': 7.27.6 - dev: true - /@babel/traverse@7.27.4: - resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==} - engines: {node: '>=6.9.0'} + '@babel/traverse@7.27.4': dependencies: '@babel/code-frame': 7.27.1 '@babel/generator': 7.27.5 @@ -351,115 +1879,60 @@ packages: globals: 11.12.0 transitivePeerDependencies: - supports-color - dev: true - /@babel/types@7.27.6: - resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} - engines: {node: '>=6.9.0'} + '@babel/types@7.27.6': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - dev: true - /@bcoe/v8-coverage@0.2.3: - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - dev: true + '@bcoe/v8-coverage@0.2.3': {} - /@cspotcode/source-map-support@0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 - /@emnapi/core@1.4.3: - resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} - requiresBuild: true + '@emnapi/core@1.4.3': dependencies: '@emnapi/wasi-threads': 1.0.2 tslib: 2.8.1 - dev: true optional: true - /@emnapi/runtime@1.4.3: - resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} - requiresBuild: true + '@emnapi/runtime@1.4.3': dependencies: tslib: 2.8.1 - dev: true optional: true - /@emnapi/wasi-threads@1.0.2: - resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} - requiresBuild: true + '@emnapi/wasi-threads@1.0.2': dependencies: tslib: 2.8.1 - dev: true optional: true - /@fast-csv/format@5.0.2: - resolution: {integrity: sha512-fRYcWvI8vs0Zxa/8fXd/QlmQYWWkJqKZPAXM+vksnplb3owQFKTPPh9JqOtD0L3flQw/AZjjXdPkD7Kp/uHm8g==} - dependencies: - lodash.escaperegexp: 4.1.2 - lodash.isboolean: 3.0.3 - lodash.isequal: 4.5.0 - lodash.isfunction: 3.0.9 - lodash.isnil: 4.0.0 - dev: false - - /@fast-csv/parse@5.0.2: - resolution: {integrity: sha512-gMu1Btmm99TP+wc0tZnlH30E/F1Gw1Tah3oMDBHNPe9W8S68ixVHjt89Wg5lh7d9RuQMtwN+sGl5kxR891+fzw==} - dependencies: - lodash.escaperegexp: 4.1.2 - lodash.groupby: 4.6.0 - lodash.isfunction: 3.0.9 - lodash.isnil: 4.0.0 - lodash.isundefined: 3.0.1 - lodash.uniq: 4.5.0 - dev: false - - /@isaacs/balanced-match@4.0.1: - resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} - engines: {node: 20 || >=22} - dev: true + '@isaacs/balanced-match@4.0.1': {} - /@isaacs/brace-expansion@5.0.0: - resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} - engines: {node: 20 || >=22} + '@isaacs/brace-expansion@5.0.0': dependencies: '@isaacs/balanced-match': 4.0.1 - dev: true - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 + string-width-cjs: string-width@4.2.3 strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 + strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true + wrap-ansi-cjs: wrap-ansi@7.0.0 - /@istanbuljs/load-nyc-config@1.1.0: - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} + '@istanbuljs/load-nyc-config@1.1.0': dependencies: camelcase: 5.3.1 find-up: 4.1.0 get-package-type: 0.1.0 js-yaml: 3.14.1 resolve-from: 5.0.0 - dev: true - /@istanbuljs/schema@0.1.3: - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - dev: true + '@istanbuljs/schema@0.1.3': {} - /@jest/console@30.0.0: - resolution: {integrity: sha512-vfpJap6JZQ3I8sUN8dsFqNAKJYO4KIGxkcB+3Fw7Q/BJiWY5HwtMMiuT1oP0avsiDhjE/TCLaDgbGfHwDdBVeg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/console@30.0.0': dependencies: '@jest/types': 30.0.0 '@types/node': 24.0.1 @@ -467,16 +1940,8 @@ packages: jest-message-util: 30.0.0 jest-util: 30.0.0 slash: 3.0.0 - dev: true - /@jest/core@30.0.0(ts-node@10.9.2): - resolution: {integrity: sha512-1zU39zFtWSl5ZuDK3Rd6P8S28MmS4F11x6Z4CURrgJ99iaAJg68hmdJ2SAHEEO6ociaNk43UhUYtHxWKEWoNYw==} - 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 + '@jest/core@30.0.0(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3))': dependencies: '@jest/console': 30.0.0 '@jest/pattern': 30.0.0 @@ -491,7 +1956,7 @@ packages: exit-x: 0.2.2 graceful-fs: 4.2.11 jest-changed-files: 30.0.0 - jest-config: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2) + jest-config: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) jest-haste-map: 30.0.0 jest-message-util: 30.0.0 jest-regex-util: 30.0.0 @@ -511,50 +1976,32 @@ packages: - esbuild-register - supports-color - ts-node - dev: true - /@jest/diff-sequences@30.0.0: - resolution: {integrity: sha512-xMbtoCeKJDto86GW6AiwVv7M4QAuI56R7dVBr1RNGYbOT44M2TIzOiske2RxopBqkumDY+A1H55pGvuribRY9A==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - dev: true + '@jest/diff-sequences@30.0.0': {} - /@jest/environment@30.0.0: - resolution: {integrity: sha512-09sFbMMgS5JxYnvgmmtwIHhvoyzvR5fUPrVl8nOCrC5KdzmmErTcAxfWyAhJ2bv3rvHNQaKiS+COSG+O7oNbXw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/environment@30.0.0': dependencies: '@jest/fake-timers': 30.0.0 '@jest/types': 30.0.0 '@types/node': 24.0.1 jest-mock: 30.0.0 - dev: true - /@jest/expect-utils@29.7.0: - resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/expect-utils@29.7.0': dependencies: jest-get-type: 29.6.3 - dev: true - /@jest/expect-utils@30.0.0: - resolution: {integrity: sha512-UiWfsqNi/+d7xepfOv8KDcbbzcYtkWBe3a3kVDtg6M1kuN6CJ7b4HzIp5e1YHrSaQaVS8sdCoyCMCZClTLNKFQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/expect-utils@30.0.0': dependencies: '@jest/get-type': 30.0.0 - dev: true - /@jest/expect@30.0.0: - resolution: {integrity: sha512-XZ3j6syhMeKiBknmmc8V3mNIb44kxLTbOQtaXA4IFdHy+vEN0cnXRzbRjdGBtrp4k1PWyMWNU3Fjz3iejrhpQg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/expect@30.0.0': dependencies: expect: 30.0.0 jest-snapshot: 30.0.0 transitivePeerDependencies: - supports-color - dev: true - /@jest/fake-timers@30.0.0: - resolution: {integrity: sha512-yzBmJcrMHAMcAEbV2w1kbxmx8WFpEz8Cth3wjLMSkq+LO8VeGKRhpr5+BUp7PPK+x4njq/b6mVnDR8e/tPL5ng==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/fake-timers@30.0.0': dependencies: '@jest/types': 30.0.0 '@sinonjs/fake-timers': 13.0.5 @@ -562,16 +2009,10 @@ packages: jest-message-util: 30.0.0 jest-mock: 30.0.0 jest-util: 30.0.0 - dev: true - /@jest/get-type@30.0.0: - resolution: {integrity: sha512-VZWMjrBzqfDKngQ7sUctKeLxanAbsBFoZnPxNIG6CmxK7Gv6K44yqd0nzveNIBfuhGZMmk1n5PGbvdSTOu0yTg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - dev: true + '@jest/get-type@30.0.0': {} - /@jest/globals@30.0.0: - resolution: {integrity: sha512-OEzYes5A1xwBJVMPqFRa8NCao8Vr42nsUZuf/SpaJWoLE+4kyl6nCQZ1zqfipmCrIXQVALC5qJwKy/7NQQLPhw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/globals@30.0.0': dependencies: '@jest/environment': 30.0.0 '@jest/expect': 30.0.0 @@ -579,24 +2020,13 @@ packages: jest-mock: 30.0.0 transitivePeerDependencies: - supports-color - dev: true - /@jest/pattern@30.0.0: - resolution: {integrity: sha512-k+TpEThzLVXMkbdxf8KHjZ83Wl+G54ytVJoDIGWwS96Ql4xyASRjc6SU1hs5jHVql+hpyK9G8N7WuFhLpGHRpQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/pattern@30.0.0': dependencies: '@types/node': 24.0.1 jest-regex-util: 30.0.0 - dev: true - /@jest/reporters@30.0.0: - resolution: {integrity: sha512-5WHNlLO0Ok+/o6ML5IzgVm1qyERtLHBNhwn67PAq92H4hZ+n5uW/BYj1VVwmTdxIcNrZLxdV9qtpdZkXf16HxA==} - 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 + '@jest/reporters@30.0.0': dependencies: '@bcoe/v8-coverage': 0.2.3 '@jest/console': 30.0.0 @@ -623,64 +2053,43 @@ packages: v8-to-istanbul: 9.3.0 transitivePeerDependencies: - supports-color - dev: true - /@jest/schemas@29.6.3: - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/schemas@29.6.3': dependencies: '@sinclair/typebox': 0.27.8 - dev: true - /@jest/schemas@30.0.0: - resolution: {integrity: sha512-NID2VRyaEkevCRz6badhfqYwri/RvMbiHY81rk3AkK/LaiB0LSxi1RdVZ7MpZdTjNugtZeGfpL0mLs9Kp3MrQw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/schemas@30.0.0': dependencies: '@sinclair/typebox': 0.34.35 - dev: true - /@jest/snapshot-utils@30.0.0: - resolution: {integrity: sha512-C/QSFUmvZEYptg2Vin84FggAphwHvj6la39vkw1CNOZQORWZ7O/H0BXmdeeeGnvlXDYY8TlFM5jgFnxLAxpFjA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/snapshot-utils@30.0.0': dependencies: '@jest/types': 30.0.0 chalk: 4.1.2 graceful-fs: 4.2.11 natural-compare: 1.4.0 - dev: true - /@jest/source-map@30.0.0: - resolution: {integrity: sha512-oYBJ4d/NF4ZY3/7iq1VaeoERHRvlwKtrGClgescaXMIa1mmb+vfJd0xMgbW9yrI80IUA7qGbxpBWxlITrHkWoA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/source-map@30.0.0': dependencies: '@jridgewell/trace-mapping': 0.3.25 callsites: 3.1.0 graceful-fs: 4.2.11 - dev: true - /@jest/test-result@30.0.0: - resolution: {integrity: sha512-685zco9HdgBaaWiB9T4xjLtBuN0Q795wgaQPpmuAeZPHwHZSoKFAUnozUtU+ongfi4l5VCz8AclOE5LAQdyjxQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/test-result@30.0.0': dependencies: '@jest/console': 30.0.0 '@jest/types': 30.0.0 '@types/istanbul-lib-coverage': 2.0.6 collect-v8-coverage: 1.0.2 - dev: true - /@jest/test-sequencer@30.0.0: - resolution: {integrity: sha512-Hmvv5Yg6UmghXIcVZIydkT0nAK7M/hlXx9WMHR5cLVwdmc14/qUQt3mC72T6GN0olPC6DhmKE6Cd/pHsgDbuqQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/test-sequencer@30.0.0': dependencies: '@jest/test-result': 30.0.0 graceful-fs: 4.2.11 jest-haste-map: 30.0.0 slash: 3.0.0 - dev: true - /@jest/transform@30.0.0: - resolution: {integrity: sha512-8xhpsCGYJsUjqpJOgLyMkeOSSlhqggFZEWAnZquBsvATtueoEs7CkMRxOUmJliF3E5x+mXmZ7gEEsHank029Og==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/transform@30.0.0': dependencies: '@babel/core': 7.27.4 '@jest/types': 30.0.0 @@ -699,11 +2108,8 @@ packages: write-file-atomic: 5.0.1 transitivePeerDependencies: - supports-color - dev: true - /@jest/types@29.6.3: - resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + '@jest/types@29.6.3': dependencies: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 @@ -711,11 +2117,8 @@ packages: '@types/node': 24.0.1 '@types/yargs': 17.0.33 chalk: 4.1.2 - dev: true - /@jest/types@30.0.0: - resolution: {integrity: sha512-1Nox8mAL52PKPfEnUQWBvKU/bp8FTT6AiDu76bFDEJj/qsRFSAVSldfCH3XYMqialti2zHXKvD5gN0AaHc0yKA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + '@jest/types@30.0.0': dependencies: '@jest/pattern': 30.0.0 '@jest/schemas': 30.0.0 @@ -724,440 +2127,232 @@ packages: '@types/node': 24.0.1 '@types/yargs': 17.0.33 chalk: 4.1.2 - dev: true - /@jridgewell/gen-mapping@0.3.8: - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 - dev: true - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} + '@jridgewell/resolve-uri@3.1.2': {} - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: true + '@jridgewell/set-array@1.2.1': {} - /@jridgewell/sourcemap-codec@1.5.0: - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/sourcemap-codec@1.5.0': {} - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - dev: true - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - /@napi-rs/wasm-runtime@0.2.11: - resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==} - requiresBuild: true + '@napi-rs/wasm-runtime@0.2.11': dependencies: '@emnapi/core': 1.4.3 '@emnapi/runtime': 1.4.3 '@tybys/wasm-util': 0.9.0 - dev: true optional: true - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true + '@pkgjs/parseargs@0.11.0': optional: true - /@pkgr/core@0.2.7: - resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - dev: true + '@pkgr/core@0.2.7': {} - /@sinclair/typebox@0.27.8: - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - dev: true + '@sinclair/typebox@0.27.8': {} - /@sinclair/typebox@0.34.35: - resolution: {integrity: sha512-C6ypdODf2VZkgRT6sFM8E1F8vR+HcffniX0Kp8MsU8PIfrlXbNCBz0jzj17GjdmjTx1OtZzdH8+iALL21UjF5A==} - dev: true + '@sinclair/typebox@0.34.35': {} - /@sinonjs/commons@3.0.1: - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + '@sinonjs/commons@3.0.1': dependencies: type-detect: 4.0.8 - dev: true - /@sinonjs/fake-timers@13.0.5: - resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} + '@sinonjs/fake-timers@13.0.5': dependencies: '@sinonjs/commons': 3.0.1 - dev: true - /@tsconfig/node10@1.0.11: - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + '@tsconfig/node10@1.0.11': {} - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + '@tsconfig/node12@1.0.11': {} - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + '@tsconfig/node14@1.0.3': {} - /@tsconfig/node16@1.0.4: - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@tsconfig/node16@1.0.4': {} - /@tybys/wasm-util@0.9.0: - resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} - requiresBuild: true + '@tybys/wasm-util@0.9.0': dependencies: tslib: 2.8.1 - dev: true optional: true - /@types/babel__core@7.20.5: - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.27.5 '@babel/types': 7.27.6 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.20.7 - dev: true - /@types/babel__generator@7.27.0: - resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + '@types/babel__generator@7.27.0': dependencies: '@babel/types': 7.27.6 - dev: true - /@types/babel__template@7.4.4: - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + '@types/babel__template@7.4.4': dependencies: '@babel/parser': 7.27.5 '@babel/types': 7.27.6 - dev: true - /@types/babel__traverse@7.20.7: - resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + '@types/babel__traverse@7.20.7': dependencies: '@babel/types': 7.27.6 - dev: true - /@types/istanbul-lib-coverage@2.0.6: - resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - dev: true + '@types/istanbul-lib-coverage@2.0.6': {} - /@types/istanbul-lib-report@3.0.3: - resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + '@types/istanbul-lib-report@3.0.3': dependencies: '@types/istanbul-lib-coverage': 2.0.6 - dev: true - /@types/istanbul-reports@3.0.4: - resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + '@types/istanbul-reports@3.0.4': dependencies: '@types/istanbul-lib-report': 3.0.3 - dev: true - /@types/jest@29.5.14: - resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} + '@types/jest@29.5.14': dependencies: expect: 29.7.0 pretty-format: 29.7.0 - dev: true - /@types/lodash@4.17.17: - resolution: {integrity: sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==} - dev: true + '@types/lodash@4.17.17': {} - /@types/node@24.0.1: - resolution: {integrity: sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==} + '@types/node@24.0.1': dependencies: undici-types: 7.8.0 - /@types/stack-utils@2.0.3: - resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} - dev: true + '@types/stack-utils@2.0.3': {} - /@types/yargs-parser@21.0.3: - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - dev: true + '@types/yargs-parser@21.0.3': {} - /@types/yargs@17.0.33: - resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + '@types/yargs@17.0.33': dependencies: '@types/yargs-parser': 21.0.3 - dev: true - /@ungap/structured-clone@1.3.0: - resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - dev: true + '@ungap/structured-clone@1.3.0': {} - /@unrs/resolver-binding-android-arm-eabi@1.9.0: - resolution: {integrity: sha512-h1T2c2Di49ekF2TE8ZCoJkb+jwETKUIPDJ/nO3tJBKlLFPu+fyd93f0rGP/BvArKx2k2HlRM4kqkNarj3dvZlg==} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true + '@unrs/resolver-binding-android-arm-eabi@1.9.0': optional: true - /@unrs/resolver-binding-android-arm64@1.9.0: - resolution: {integrity: sha512-sG1NHtgXtX8owEkJ11yn34vt0Xqzi3k9TJ8zppDmyG8GZV4kVWw44FHwKwHeEFl07uKPeC4ZoyuQaGh5ruJYPA==} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true + '@unrs/resolver-binding-android-arm64@1.9.0': optional: true - /@unrs/resolver-binding-darwin-arm64@1.9.0: - resolution: {integrity: sha512-nJ9z47kfFnCxN1z/oYZS7HSNsFh43y2asePzTEZpEvK7kGyuShSl3RRXnm/1QaqFL+iP+BjMwuB+DYUymOkA5A==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true + '@unrs/resolver-binding-darwin-arm64@1.9.0': optional: true - /@unrs/resolver-binding-darwin-x64@1.9.0: - resolution: {integrity: sha512-TK+UA1TTa0qS53rjWn7cVlEKVGz2B6JYe0C++TdQjvWYIyx83ruwh0wd4LRxYBM5HeuAzXcylA9BH2trARXJTw==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true + '@unrs/resolver-binding-darwin-x64@1.9.0': optional: true - /@unrs/resolver-binding-freebsd-x64@1.9.0: - resolution: {integrity: sha512-6uZwzMRFcD7CcCd0vz3Hp+9qIL2jseE/bx3ZjaLwn8t714nYGwiE84WpaMCYjU+IQET8Vu/+BNAGtYD7BG/0yA==} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true + '@unrs/resolver-binding-freebsd-x64@1.9.0': optional: true - /@unrs/resolver-binding-linux-arm-gnueabihf@1.9.0: - resolution: {integrity: sha512-bPUBksQfrgcfv2+mm+AZinaKq8LCFvt5PThYqRotqSuuZK1TVKkhbVMS/jvSRfYl7jr3AoZLYbDkItxgqMKRkg==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true + '@unrs/resolver-binding-linux-arm-gnueabihf@1.9.0': optional: true - /@unrs/resolver-binding-linux-arm-musleabihf@1.9.0: - resolution: {integrity: sha512-uT6E7UBIrTdCsFQ+y0tQd3g5oudmrS/hds5pbU3h4s2t/1vsGWbbSKhBSCD9mcqaqkBwoqlECpUrRJCmldl8PA==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true + '@unrs/resolver-binding-linux-arm-musleabihf@1.9.0': optional: true - /@unrs/resolver-binding-linux-arm64-gnu@1.9.0: - resolution: {integrity: sha512-vdqBh911wc5awE2bX2zx3eflbyv8U9xbE/jVKAm425eRoOVv/VseGZsqi3A3SykckSpF4wSROkbQPvbQFn8EsA==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true + '@unrs/resolver-binding-linux-arm64-gnu@1.9.0': optional: true - /@unrs/resolver-binding-linux-arm64-musl@1.9.0: - resolution: {integrity: sha512-/8JFZ/SnuDr1lLEVsxsuVwrsGquTvT51RZGvyDB/dOK3oYK2UqeXzgeyq6Otp8FZXQcEYqJwxb9v+gtdXn03eQ==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true + '@unrs/resolver-binding-linux-arm64-musl@1.9.0': optional: true - /@unrs/resolver-binding-linux-ppc64-gnu@1.9.0: - resolution: {integrity: sha512-FkJjybtrl+rajTw4loI3L6YqSOpeZfDls4SstL/5lsP2bka9TiHUjgMBjygeZEis1oC8LfJTS8FSgpKPaQx2tQ==} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: true + '@unrs/resolver-binding-linux-ppc64-gnu@1.9.0': optional: true - /@unrs/resolver-binding-linux-riscv64-gnu@1.9.0: - resolution: {integrity: sha512-w/NZfHNeDusbqSZ8r/hp8iL4S39h4+vQMc9/vvzuIKMWKppyUGKm3IST0Qv0aOZ1rzIbl9SrDeIqK86ZpUK37w==} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true + '@unrs/resolver-binding-linux-riscv64-gnu@1.9.0': optional: true - /@unrs/resolver-binding-linux-riscv64-musl@1.9.0: - resolution: {integrity: sha512-bEPBosut8/8KQbUixPry8zg/fOzVOWyvwzOfz0C0Rw6dp+wIBseyiHKjkcSyZKv/98edrbMknBaMNJfA/UEdqw==} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true + '@unrs/resolver-binding-linux-riscv64-musl@1.9.0': optional: true - /@unrs/resolver-binding-linux-s390x-gnu@1.9.0: - resolution: {integrity: sha512-LDtMT7moE3gK753gG4pc31AAqGUC86j3AplaFusc717EUGF9ZFJ356sdQzzZzkBk1XzMdxFyZ4f/i35NKM/lFA==} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: true + '@unrs/resolver-binding-linux-s390x-gnu@1.9.0': optional: true - /@unrs/resolver-binding-linux-x64-gnu@1.9.0: - resolution: {integrity: sha512-WmFd5KINHIXj8o1mPaT8QRjA9HgSXhN1gl9Da4IZihARihEnOylu4co7i/yeaIpcfsI6sYs33cNZKyHYDh0lrA==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true + '@unrs/resolver-binding-linux-x64-gnu@1.9.0': optional: true - /@unrs/resolver-binding-linux-x64-musl@1.9.0: - resolution: {integrity: sha512-CYuXbANW+WgzVRIl8/QvZmDaZxrqvOldOwlbUjIM4pQ46FJ0W5cinJ/Ghwa/Ng1ZPMJMk1VFdsD/XwmCGIXBWg==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true + '@unrs/resolver-binding-linux-x64-musl@1.9.0': optional: true - /@unrs/resolver-binding-wasm32-wasi@1.9.0: - resolution: {integrity: sha512-6Rp2WH0OoitMYR57Z6VE8Y6corX8C6QEMWLgOV6qXiJIeZ1F9WGXY/yQ8yDC4iTraotyLOeJ2Asea0urWj2fKQ==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - requiresBuild: true + '@unrs/resolver-binding-wasm32-wasi@1.9.0': dependencies: '@napi-rs/wasm-runtime': 0.2.11 - dev: true optional: true - /@unrs/resolver-binding-win32-arm64-msvc@1.9.0: - resolution: {integrity: sha512-rknkrTRuvujprrbPmGeHi8wYWxmNVlBoNW8+4XF2hXUnASOjmuC9FNF1tGbDiRQWn264q9U/oGtixyO3BT8adQ==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true + '@unrs/resolver-binding-win32-arm64-msvc@1.9.0': optional: true - /@unrs/resolver-binding-win32-ia32-msvc@1.9.0: - resolution: {integrity: sha512-Ceymm+iBl+bgAICtgiHyMLz6hjxmLJKqBim8tDzpX61wpZOx2bPK6Gjuor7I2RiUynVjvvkoRIkrPyMwzBzF3A==} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true + '@unrs/resolver-binding-win32-ia32-msvc@1.9.0': optional: true - /@unrs/resolver-binding-win32-x64-msvc@1.9.0: - resolution: {integrity: sha512-k59o9ZyeyS0hAlcaKFezYSH2agQeRFEB7KoQLXl3Nb3rgkqT1NY9Vwy+SqODiLmYnEjxWJVRE/yq2jFVqdIxZw==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true + '@unrs/resolver-binding-win32-x64-msvc@1.9.0': optional: true - /acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} - engines: {node: '>=0.4.0'} + acorn-walk@8.3.4: dependencies: acorn: 8.15.0 - /acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} - engines: {node: '>=0.4.0'} - hasBin: true + acorn@8.15.0: {} - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - dev: true - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 - dev: true - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: true + ansi-regex@5.0.1: {} - /ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} - dev: true + ansi-regex@6.1.0: {} - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - dev: true - /ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - dev: true + ansi-styles@5.2.0: {} - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true + ansi-styles@6.2.1: {} - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - dev: true - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + arg@4.1.3: {} - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 - dev: true - /asn1@0.2.6: - resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + asn1@0.2.6: dependencies: safer-buffer: 2.1.2 - dev: true - /assert-plus@1.0.0: - resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} - engines: {node: '>=0.8'} - dev: true + assert-plus@1.0.0: {} - /async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - dev: true + async@3.2.6: {} - /asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true + asynckit@0.4.0: {} - /aws-sign2@0.7.0: - resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} - dev: true + aws-sign2@0.7.0: {} - /aws4@1.13.2: - resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} - dev: true + aws4@1.13.2: {} - /babel-jest@30.0.0(@babel/core@7.27.4): - resolution: {integrity: sha512-JQ0DhdFjODbSawDf0026uZuwaqfKkQzk+9mwWkq2XkKFIaMhFVOxlVmbFCOnnC76jATdxrff3IiUAvOAJec6tw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - peerDependencies: - '@babel/core': ^7.11.0 + babel-jest@30.0.0(@babel/core@7.27.4): dependencies: '@babel/core': 7.27.4 '@jest/transform': 30.0.0 @@ -1169,11 +2364,8 @@ packages: slash: 3.0.0 transitivePeerDependencies: - supports-color - dev: true - /babel-plugin-istanbul@7.0.0: - resolution: {integrity: sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==} - engines: {node: '>=12'} + babel-plugin-istanbul@7.0.0: dependencies: '@babel/helper-plugin-utils': 7.27.1 '@istanbuljs/load-nyc-config': 1.1.0 @@ -1182,21 +2374,14 @@ packages: test-exclude: 6.0.0 transitivePeerDependencies: - supports-color - dev: true - /babel-plugin-jest-hoist@30.0.0: - resolution: {integrity: sha512-DSRm+US/FCB4xPDD6Rnslb6PAF9Bej1DZ+1u4aTiqJnk7ZX12eHsnDiIOqjGvITCq+u6wLqUhgS+faCNbVY8+g==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + babel-plugin-jest-hoist@30.0.0: dependencies: '@babel/template': 7.27.2 '@babel/types': 7.27.6 '@types/babel__core': 7.20.5 - dev: true - /babel-preset-current-node-syntax@1.1.0(@babel/core@7.27.4): - resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} - peerDependencies: - '@babel/core': ^7.0.0 + babel-preset-current-node-syntax@1.1.0(@babel/core@7.27.4): dependencies: '@babel/core': 7.27.4 '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.27.4) @@ -1214,317 +2399,166 @@ packages: '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.27.4) '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.27.4) '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.27.4) - dev: true - /babel-preset-jest@30.0.0(@babel/core@7.27.4): - resolution: {integrity: sha512-hgEuu/W7gk8QOWUA9+m3Zk+WpGvKc1Egp6rFQEfYxEoM9Fk/q8nuTXNL65OkhwGrTApauEGgakOoWVXj+UfhKw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - peerDependencies: - '@babel/core': ^7.11.0 + babel-preset-jest@30.0.0(@babel/core@7.27.4): dependencies: '@babel/core': 7.27.4 babel-plugin-jest-hoist: 30.0.0 babel-preset-current-node-syntax: 1.1.0(@babel/core@7.27.4) - dev: true - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true + balanced-match@1.0.2: {} - /bcrypt-pbkdf@1.0.2: - resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + bcrypt-pbkdf@1.0.2: dependencies: tweetnacl: 0.14.5 - dev: true - /brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: true - /brace-expansion@2.0.2: - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 - dev: true - /braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} + braces@3.0.3: dependencies: fill-range: 7.1.1 - dev: true - /browserslist@4.25.0: - resolution: {integrity: sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true + browserslist@4.25.0: dependencies: caniuse-lite: 1.0.30001723 electron-to-chromium: 1.5.167 node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.25.0) - dev: true - /bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} + bs-logger@0.2.6: dependencies: fast-json-stable-stringify: 2.1.0 - dev: true - /bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + bser@2.1.1: dependencies: node-int64: 0.4.0 - dev: true - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true + buffer-from@1.1.2: {} - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true + callsites@3.1.0: {} - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true + camelcase@5.3.1: {} - /camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - dev: true + camelcase@6.3.0: {} - /caniuse-lite@1.0.30001723: - resolution: {integrity: sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==} - dev: true + caniuse-lite@1.0.30001723: {} - /caseless@0.12.0: - resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - dev: true + caseless@0.12.0: {} - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: true - /char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - dev: true + char-regex@1.0.2: {} - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - dev: true + ci-info@3.9.0: {} - /ci-info@4.2.0: - resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} - engines: {node: '>=8'} - dev: true + ci-info@4.2.0: {} - /cjs-module-lexer@2.1.0: - resolution: {integrity: sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==} - dev: true + cjs-module-lexer@2.1.0: {} - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + cliui@8.0.1: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: true - /co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - dev: true + co@4.6.0: {} - /collect-v8-coverage@1.0.2: - resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - dev: true + collect-v8-coverage@1.0.2: {} - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + color-convert@2.0.1: dependencies: color-name: 1.1.4 - dev: true - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true + color-name@1.1.4: {} - /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 - dev: true - /commander@14.0.0: - resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} - engines: {node: '>=20'} - dev: false + commander@14.0.0: {} - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true + concat-map@0.0.1: {} - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true + convert-source-map@2.0.0: {} - /core-util-is@1.0.2: - resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} - dev: true + core-util-is@1.0.2: {} - /coveralls@3.1.1: - resolution: {integrity: sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==} - engines: {node: '>=6'} - hasBin: true + coveralls@3.1.1: dependencies: js-yaml: 3.14.1 lcov-parse: 1.0.0 log-driver: 1.2.7 minimist: 1.2.8 request: 2.88.2 - dev: true - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + create-require@1.1.1: {} - /cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: true - /dashdash@1.14.1: - resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} - engines: {node: '>=0.10'} + dashdash@1.14.1: dependencies: assert-plus: 1.0.0 - dev: true - /debug@4.4.1: - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@4.4.1: dependencies: ms: 2.1.3 - dev: true - /dedent@1.6.0: - resolution: {integrity: sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - dev: true + dedent@1.6.0: {} - /deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - dev: true + deepmerge@4.3.1: {} - /delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dev: true + delayed-stream@1.0.0: {} - /detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - dev: true + detect-newline@3.1.0: {} - /diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true + diff-sequences@29.6.3: {} - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} + diff@4.0.2: {} - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true + eastasianwidth@0.2.0: {} - /ecc-jsbn@0.1.2: - resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} + ecc-jsbn@0.1.2: dependencies: jsbn: 0.1.1 safer-buffer: 2.1.2 - dev: true - /ejs@3.1.10: - resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} - engines: {node: '>=0.10.0'} - hasBin: true + ejs@3.1.10: dependencies: jake: 10.9.2 - dev: true - /electron-to-chromium@1.5.167: - resolution: {integrity: sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==} - dev: true + electron-to-chromium@1.5.167: {} - /emittery@0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - dev: true + emittery@0.13.1: {} - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: true + emoji-regex@8.0.0: {} - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true + emoji-regex@9.2.2: {} - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 - dev: true - /escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - dev: true + escalade@3.2.0: {} - /escape-string-regexp@2.0.0: - resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} - engines: {node: '>=8'} - dev: true + escape-string-regexp@2.0.0: {} - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true + esprima@4.0.1: {} - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} + execa@5.1.1: dependencies: cross-spawn: 7.0.6 get-stream: 6.0.1 @@ -1535,27 +2569,18 @@ packages: onetime: 5.1.2 signal-exit: 3.0.7 strip-final-newline: 2.0.0 - dev: true - /exit-x@0.2.2: - resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} - engines: {node: '>= 0.8.0'} - dev: true + exit-x@0.2.2: {} - /expect@29.7.0: - resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + expect@29.7.0: dependencies: '@jest/expect-utils': 29.7.0 jest-get-type: 29.6.3 jest-matcher-utils: 29.7.0 jest-message-util: 29.7.0 jest-util: 29.7.0 - dev: true - /expect@30.0.0: - resolution: {integrity: sha512-xCdPp6gwiR9q9lsPCHANarIkFTN/IMZso6Kkq03sOm9IIGtzK/UJqml0dkhHibGh8HKOj8BIDIpZ0BZuU7QK6w==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + expect@30.0.0: dependencies: '@jest/expect-utils': 30.0.0 '@jest/get-type': 30.0.0 @@ -1563,122 +2588,63 @@ packages: jest-message-util: 30.0.0 jest-mock: 30.0.0 jest-util: 30.0.0 - dev: true - - /extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: true - /extsprintf@1.3.0: - resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} - engines: {'0': node >=0.6.0} - dev: true + extend@3.0.2: {} - /fast-csv@5.0.2: - resolution: {integrity: sha512-CnB2zYAzzeh5Ta0UhSf32NexLy2SsEsSMY+fMWPV40k1OgaLEbm9Hf5dms3z/9fASZHBjB6i834079gVeksEqQ==} - engines: {node: '>=10.0.0'} - dependencies: - '@fast-csv/format': 5.0.2 - '@fast-csv/parse': 5.0.2 - dev: false + extsprintf@1.3.0: {} - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true + fast-deep-equal@3.1.3: {} - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true + fast-json-stable-stringify@2.1.0: {} - /fb-watchman@2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + fb-watchman@2.0.2: dependencies: bser: 2.1.1 - dev: true - /filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + filelist@1.0.4: dependencies: minimatch: 5.1.6 - dev: true - /fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 - dev: true - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} + find-up@4.1.0: dependencies: locate-path: 5.0.0 path-exists: 4.0.0 - dev: true - /foreground-child@3.3.1: - resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} - engines: {node: '>=14'} + foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 - dev: true - /forever-agent@0.6.1: - resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} - dev: true + forever-agent@0.6.1: {} - /form-data@2.3.3: - resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} - engines: {node: '>= 0.12'} + form-data@2.3.3: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 - dev: true - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true + fs.realpath@1.0.0: {} - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true + fsevents@2.3.3: optional: true - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true + gensync@1.0.0-beta.2: {} - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true + get-caller-file@2.0.5: {} - /get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - dev: true + get-package-type@0.1.0: {} - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true + get-stream@6.0.1: {} - /getpass@0.1.7: - resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} + getpass@0.1.7: dependencies: assert-plus: 1.0.0 - dev: true - /glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} - hasBin: true + glob@10.4.5: dependencies: foreground-child: 3.3.1 jackspeak: 3.4.3 @@ -1686,12 +2652,8 @@ packages: minipass: 7.1.2 package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - dev: true - /glob@11.0.3: - resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==} - engines: {node: 20 || >=22} - hasBin: true + glob@11.0.3: dependencies: foreground-child: 3.3.1 jackspeak: 4.1.1 @@ -1699,11 +2661,8 @@ packages: minipass: 7.1.2 package-json-from-dist: 1.0.1 path-scurry: 2.0.0 - dev: true - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + glob@7.2.3: dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 @@ -1711,124 +2670,63 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: true - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true + globals@11.12.0: {} - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true + graceful-fs@4.2.11: {} - /har-schema@2.0.0: - resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} - engines: {node: '>=4'} - dev: true + har-schema@2.0.0: {} - /har-validator@5.1.5: - resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} - engines: {node: '>=6'} - deprecated: this library is no longer supported + har-validator@5.1.5: dependencies: ajv: 6.12.6 har-schema: 2.0.0 - dev: true - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - dev: true + has-flag@4.0.0: {} - /html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - dev: true + html-escaper@2.0.2: {} - /http-signature@1.2.0: - resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} - engines: {node: '>=0.8', npm: '>=1.3.7'} + http-signature@1.2.0: dependencies: assert-plus: 1.0.0 jsprim: 1.4.2 sshpk: 1.18.0 - dev: true - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true + human-signals@2.1.0: {} - /import-local@3.2.0: - resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} - engines: {node: '>=8'} - hasBin: true + import-local@3.2.0: dependencies: pkg-dir: 4.2.0 resolve-cwd: 3.0.0 - dev: true - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true + imurmurhash@0.1.4: {} - /inflight@1.0.6: - resolution: {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. + inflight@1.0.6: dependencies: once: 1.4.0 wrappy: 1.0.2 - dev: true - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true + inherits@2.0.4: {} - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true + is-arrayish@0.2.1: {} - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: true + is-fullwidth-code-point@3.0.0: {} - /is-generator-fn@2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - dev: true + is-generator-fn@2.1.0: {} - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true + is-number@7.0.0: {} - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true + is-stream@2.0.1: {} - /is-typedarray@1.0.0: - resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - dev: true + is-typedarray@1.0.0: {} - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true + isexe@2.0.0: {} - /isstream@0.1.2: - resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} - dev: true + isstream@0.1.2: {} - /istanbul-lib-coverage@3.2.2: - resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} - engines: {node: '>=8'} - dev: true + istanbul-lib-coverage@3.2.2: {} - /istanbul-lib-instrument@6.0.3: - resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} - engines: {node: '>=10'} + istanbul-lib-instrument@6.0.3: dependencies: '@babel/core': 7.27.4 '@babel/parser': 7.27.5 @@ -1837,74 +2735,50 @@ packages: semver: 7.7.2 transitivePeerDependencies: - supports-color - dev: true - /istanbul-lib-report@3.0.1: - resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} - engines: {node: '>=10'} + istanbul-lib-report@3.0.1: dependencies: istanbul-lib-coverage: 3.2.2 make-dir: 4.0.0 supports-color: 7.2.0 - dev: true - /istanbul-lib-source-maps@5.0.6: - resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} - engines: {node: '>=10'} + istanbul-lib-source-maps@5.0.6: dependencies: '@jridgewell/trace-mapping': 0.3.25 debug: 4.4.1 istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color - dev: true - /istanbul-reports@3.1.7: - resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} - engines: {node: '>=8'} + istanbul-reports@3.1.7: dependencies: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 - dev: true - /jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - dev: true - /jackspeak@4.1.1: - resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} - engines: {node: 20 || >=22} + jackspeak@4.1.1: dependencies: '@isaacs/cliui': 8.0.2 - dev: true - /jake@10.9.2: - resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} - engines: {node: '>=10'} - hasBin: true + jake@10.9.2: dependencies: async: 3.2.6 chalk: 4.1.2 filelist: 1.0.4 minimatch: 3.1.2 - dev: true - /jest-changed-files@30.0.0: - resolution: {integrity: sha512-rzGpvCdPdEV1Ma83c1GbZif0L2KAm3vXSXGRlpx7yCt0vhruwCNouKNRh3SiVcISHP1mb3iJzjb7tAEnNu1laQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-changed-files@30.0.0: dependencies: execa: 5.1.1 jest-util: 30.0.0 p-limit: 3.1.0 - dev: true - /jest-circus@30.0.0: - resolution: {integrity: sha512-nTwah78qcKVyndBS650hAkaEmwWGaVsMMoWdJwMnH77XArRJow2Ir7hc+8p/mATtxVZuM9OTkA/3hQocRIK5Dw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-circus@30.0.0: dependencies: '@jest/environment': 30.0.0 '@jest/expect': 30.0.0 @@ -1929,25 +2803,16 @@ packages: transitivePeerDependencies: - babel-plugin-macros - supports-color - dev: true - /jest-cli@30.0.0(@types/node@24.0.1)(ts-node@10.9.2): - resolution: {integrity: sha512-fWKAgrhlwVVCfeizsmIrPRTBYTzO82WSba3gJniZNR3PKXADgdC0mmCSK+M+t7N8RCXOVfY6kvCkvjUNtzmHYQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true + jest-cli@30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)): dependencies: - '@jest/core': 30.0.0(ts-node@10.9.2) + '@jest/core': 30.0.0(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) '@jest/test-result': 30.0.0 '@jest/types': 30.0.0 chalk: 4.1.2 exit-x: 0.2.2 import-local: 3.2.0 - jest-config: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2) + jest-config: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) jest-util: 30.0.0 jest-validate: 30.0.0 yargs: 17.7.2 @@ -1957,29 +2822,14 @@ packages: - esbuild-register - supports-color - ts-node - dev: true - /jest-config@30.0.0(@types/node@24.0.1)(ts-node@10.9.2): - resolution: {integrity: sha512-p13a/zun+sbOMrBnTEUdq/5N7bZMOGd1yMfqtAJniPNuzURMay4I+vxZLK1XSDbjvIhmeVdG8h8RznqYyjctyg==} - 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' - peerDependenciesMeta: - '@types/node': - optional: true - esbuild-register: - optional: true - ts-node: - optional: true + jest-config@30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)): dependencies: '@babel/core': 7.27.4 '@jest/get-type': 30.0.0 '@jest/pattern': 30.0.0 '@jest/test-sequencer': 30.0.0 '@jest/types': 30.0.0 - '@types/node': 24.0.1 babel-jest: 30.0.0(@babel/core@7.27.4) chalk: 4.1.2 ci-info: 4.2.0 @@ -1999,53 +2849,40 @@ packages: pretty-format: 30.0.0 slash: 3.0.0 strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 24.0.1 ts-node: 10.9.2(@types/node@24.0.1)(typescript@5.8.3) transitivePeerDependencies: - babel-plugin-macros - supports-color - dev: true - /jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-diff@29.7.0: dependencies: chalk: 4.1.2 diff-sequences: 29.6.3 jest-get-type: 29.6.3 pretty-format: 29.7.0 - dev: true - /jest-diff@30.0.0: - resolution: {integrity: sha512-TgT1+KipV8JTLXXeFX0qSvIJR/UXiNNojjxb/awh3vYlBZyChU/NEmyKmq+wijKjWEztyrGJFL790nqMqNjTHA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-diff@30.0.0: dependencies: '@jest/diff-sequences': 30.0.0 '@jest/get-type': 30.0.0 chalk: 4.1.2 pretty-format: 30.0.0 - dev: true - /jest-docblock@30.0.0: - resolution: {integrity: sha512-By/iQ0nvTzghEecGzUMCp1axLtBh+8wB4Hpoi5o+x1stycjEmPcH1mHugL4D9Q+YKV++vKeX/3ZTW90QC8ICPg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-docblock@30.0.0: dependencies: detect-newline: 3.1.0 - dev: true - /jest-each@30.0.0: - resolution: {integrity: sha512-qkFEW3cfytEjG2KtrhwtldZfXYnWSanO8xUMXLe4A6yaiHMHJUalk0Yyv4MQH6aeaxgi4sGVrukvF0lPMM7U1w==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-each@30.0.0: dependencies: '@jest/get-type': 30.0.0 '@jest/types': 30.0.0 chalk: 4.1.2 jest-util: 30.0.0 pretty-format: 30.0.0 - dev: true - /jest-environment-node@30.0.0: - resolution: {integrity: sha512-sF6lxyA25dIURyDk4voYmGU9Uwz2rQKMfjxKnDd19yk+qxKGrimFqS5YsPHWTlAVBo+YhWzXsqZoaMzrTFvqfg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-environment-node@30.0.0: dependencies: '@jest/environment': 30.0.0 '@jest/fake-timers': 30.0.0 @@ -2054,16 +2891,10 @@ packages: jest-mock: 30.0.0 jest-util: 30.0.0 jest-validate: 30.0.0 - dev: true - /jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true + jest-get-type@29.6.3: {} - /jest-haste-map@30.0.0: - resolution: {integrity: sha512-p4bXAhXTawTsADgQgTpbymdLaTyPW1xWNu1oIGG7/N3LIAbZVkH2JMJqS8/IUcnGR8Kc7WFE+vWbJvsqGCWZXw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-haste-map@30.0.0: dependencies: '@jest/types': 30.0.0 '@types/node': 24.0.1 @@ -2077,39 +2908,27 @@ packages: walker: 1.0.8 optionalDependencies: fsevents: 2.3.3 - dev: true - /jest-leak-detector@30.0.0: - resolution: {integrity: sha512-E/ly1azdVVbZrS0T6FIpyYHvsdek4FNaThJTtggjV/8IpKxh3p9NLndeUZy2+sjAI3ncS+aM0uLLon/dBg8htA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-leak-detector@30.0.0: dependencies: '@jest/get-type': 30.0.0 pretty-format: 30.0.0 - dev: true - /jest-matcher-utils@29.7.0: - resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-matcher-utils@29.7.0: dependencies: chalk: 4.1.2 jest-diff: 29.7.0 jest-get-type: 29.6.3 pretty-format: 29.7.0 - dev: true - /jest-matcher-utils@30.0.0: - resolution: {integrity: sha512-m5mrunqopkrqwG1mMdJxe1J4uGmS9AHHKYUmoxeQOxBcLjEvirIrIDwuKmUYrecPHVB/PUBpXs2gPoeA2FSSLQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-matcher-utils@30.0.0: dependencies: '@jest/get-type': 30.0.0 chalk: 4.1.2 jest-diff: 30.0.0 pretty-format: 30.0.0 - dev: true - /jest-message-util@29.7.0: - resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-message-util@29.7.0: dependencies: '@babel/code-frame': 7.27.1 '@jest/types': 29.6.3 @@ -2120,11 +2939,8 @@ packages: pretty-format: 29.7.0 slash: 3.0.0 stack-utils: 2.0.6 - dev: true - /jest-message-util@30.0.0: - resolution: {integrity: sha512-pV3qcrb4utEsa/U7UI2VayNzSDQcmCllBZLSoIucrESRu0geKThFZOjjh0kACDJFJRAQwsK7GVsmS6SpEceD8w==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-message-util@30.0.0: dependencies: '@babel/code-frame': 7.27.1 '@jest/types': 30.0.0 @@ -2135,47 +2951,27 @@ packages: pretty-format: 30.0.0 slash: 3.0.0 stack-utils: 2.0.6 - dev: true - /jest-mock@30.0.0: - resolution: {integrity: sha512-W2sRA4ALXILrEetEOh2ooZG6fZ01iwVs0OWMKSSWRcUlaLr4ESHuiKXDNTg+ZVgOq8Ei5445i/Yxrv59VT+XkA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-mock@30.0.0: dependencies: '@jest/types': 30.0.0 '@types/node': 24.0.1 jest-util: 30.0.0 - dev: true - /jest-pnp-resolver@1.2.3(jest-resolve@30.0.0): - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - dependencies: + jest-pnp-resolver@1.2.3(jest-resolve@30.0.0): + optionalDependencies: jest-resolve: 30.0.0 - dev: true - /jest-regex-util@30.0.0: - resolution: {integrity: sha512-rT84010qRu/5OOU7a9TeidC2Tp3Qgt9Sty4pOZ/VSDuEmRupIjKZAb53gU3jr4ooMlhwScrgC9UixJxWzVu9oQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - dev: true + jest-regex-util@30.0.0: {} - /jest-resolve-dependencies@30.0.0: - resolution: {integrity: sha512-Yhh7odCAUNXhluK1bCpwIlHrN1wycYaTlZwq1GdfNBEESNNI/z1j1a7dUEWHbmB9LGgv0sanxw3JPmWU8NeebQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-resolve-dependencies@30.0.0: dependencies: jest-regex-util: 30.0.0 jest-snapshot: 30.0.0 transitivePeerDependencies: - supports-color - dev: true - /jest-resolve@30.0.0: - resolution: {integrity: sha512-zwWl1P15CcAfuQCEuxszjiKdsValhnWcj/aXg/R3aMHs8HVoCWHC4B/+5+1BirMoOud8NnN85GSP2LEZCbj3OA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-resolve@30.0.0: dependencies: chalk: 4.1.2 graceful-fs: 4.2.11 @@ -2185,11 +2981,8 @@ packages: jest-validate: 30.0.0 slash: 3.0.0 unrs-resolver: 1.9.0 - dev: true - /jest-runner@30.0.0: - resolution: {integrity: sha512-xbhmvWIc8X1IQ8G7xTv0AQJXKjBVyxoVJEJgy7A4RXsSaO+k/1ZSBbHwjnUhvYqMvwQPomWssDkUx6EoidEhlw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-runner@30.0.0: dependencies: '@jest/console': 30.0.0 '@jest/environment': 30.0.0 @@ -2215,11 +3008,8 @@ packages: source-map-support: 0.5.13 transitivePeerDependencies: - supports-color - dev: true - /jest-runtime@30.0.0: - resolution: {integrity: sha512-/O07qVgFrFAOGKGigojmdR3jUGz/y3+a/v9S/Yi2MHxsD+v6WcPppglZJw0gNJkRBArRDK8CFAwpM/VuEiiRjA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-runtime@30.0.0: dependencies: '@jest/environment': 30.0.0 '@jest/fake-timers': 30.0.0 @@ -2245,11 +3035,8 @@ packages: strip-bom: 4.0.0 transitivePeerDependencies: - supports-color - dev: true - /jest-snapshot@30.0.0: - resolution: {integrity: sha512-6oCnzjpvfj/UIOMTqKZ6gedWAUgaycMdV8Y8h2dRJPvc2wSjckN03pzeoonw8y33uVngfx7WMo1ygdRGEKOT7w==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-snapshot@30.0.0: dependencies: '@babel/core': 7.27.4 '@babel/generator': 7.27.5 @@ -2274,11 +3061,8 @@ packages: synckit: 0.11.8 transitivePeerDependencies: - supports-color - dev: true - /jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 '@types/node': 24.0.1 @@ -2286,11 +3070,8 @@ packages: ci-info: 3.9.0 graceful-fs: 4.2.11 picomatch: 2.3.1 - dev: true - /jest-util@30.0.0: - resolution: {integrity: sha512-fhNBBM9uSUbd4Lzsf8l/kcAdaHD/4SgoI48en3HXcBEMwKwoleKFMZ6cYEYs21SB779PRuRCyNLmymApAm8tZw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-util@30.0.0: dependencies: '@jest/types': 30.0.0 '@types/node': 24.0.1 @@ -2298,11 +3079,8 @@ packages: ci-info: 4.2.0 graceful-fs: 4.2.11 picomatch: 4.0.2 - dev: true - /jest-validate@30.0.0: - resolution: {integrity: sha512-d6OkzsdlWItHAikUDs1hlLmpOIRhsZoXTCliV2XXalVQ3ZOeb9dy0CQ6AKulJu/XOZqpOEr/FiMH+FeOBVV+nw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-validate@30.0.0: dependencies: '@jest/get-type': 30.0.0 '@jest/types': 30.0.0 @@ -2310,11 +3088,8 @@ packages: chalk: 4.1.2 leven: 3.1.0 pretty-format: 30.0.0 - dev: true - /jest-watcher@30.0.0: - resolution: {integrity: sha512-fbAkojcyS53bOL/B7XYhahORq9cIaPwOgd/p9qW/hybbC8l6CzxfWJJxjlPBAIVN8dRipLR0zdhpGQdam+YBtw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-watcher@30.0.0: dependencies: '@jest/test-result': 30.0.0 '@jest/types': 30.0.0 @@ -2324,456 +3099,229 @@ packages: emittery: 0.13.1 jest-util: 30.0.0 string-length: 4.0.2 - dev: true - /jest-worker@30.0.0: - resolution: {integrity: sha512-VZvxfWIybIvwK8N/Bsfe43LfQgd/rD0c4h5nLUx78CAqPxIQcW2qDjsVAC53iUR8yxzFIeCFFvWOh8en8hGzdg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + jest-worker@30.0.0: dependencies: '@types/node': 24.0.1 '@ungap/structured-clone': 1.3.0 jest-util: 30.0.0 merge-stream: 2.0.0 supports-color: 8.1.1 - dev: true - /jest@30.0.0(@types/node@24.0.1)(ts-node@10.9.2): - resolution: {integrity: sha512-/3G2iFwsUY95vkflmlDn/IdLyLWqpQXcftptooaPH4qkyU52V7qVYf1BjmdSPlp1+0fs6BmNtrGaSFwOfV07ew==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true + jest@30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)): dependencies: - '@jest/core': 30.0.0(ts-node@10.9.2) + '@jest/core': 30.0.0(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) '@jest/types': 30.0.0 import-local: 3.2.0 - jest-cli: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2) + jest-cli: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros - esbuild-register - supports-color - ts-node - dev: true - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true + js-tokens@4.0.0: {} - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true + js-yaml@3.14.1: dependencies: argparse: 1.0.10 esprima: 4.0.1 - dev: true - - /jsbn@0.1.1: - resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} - dev: true - - /jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-schema@0.4.0: - resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} - dev: true - - /json-stringify-safe@5.0.1: - resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /jsprim@1.4.2: - resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} - engines: {node: '>=0.6.0'} - dependencies: - assert-plus: 1.0.0 - extsprintf: 1.3.0 - json-schema: 0.4.0 - verror: 1.10.0 - dev: true - - /lcov-parse@1.0.0: - resolution: {integrity: sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==} - hasBin: true - dev: true - /leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true + jsbn@0.1.1: {} - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true + jsesc@3.1.0: {} - /lodash.escaperegexp@4.1.2: - resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==} - dev: false + json-parse-even-better-errors@2.3.1: {} - /lodash.groupby@4.6.0: - resolution: {integrity: sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw==} - dev: false + json-schema-traverse@0.4.1: {} - /lodash.isboolean@3.0.3: - resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} - dev: false + json-schema@0.4.0: {} - /lodash.isequal@4.5.0: - resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. - dev: false + json-stringify-safe@5.0.1: {} - /lodash.isfunction@3.0.9: - resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} - dev: false + json5@2.2.3: {} - /lodash.isnil@4.0.0: - resolution: {integrity: sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng==} - dev: false + jsprim@1.4.2: + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 - /lodash.isundefined@3.0.1: - resolution: {integrity: sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA==} - dev: false + lcov-parse@1.0.0: {} - /lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - dev: true + leven@3.1.0: {} - /lodash.uniq@4.5.0: - resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} - dev: false + lines-and-columns@1.2.4: {} - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: false + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 - /log-driver@1.2.7: - resolution: {integrity: sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==} - engines: {node: '>=0.8.6'} - dev: true + lodash.memoize@4.1.2: {} - /lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - dev: true + lodash@4.17.21: {} - /lru-cache@11.1.0: - resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} - engines: {node: 20 || >=22} - dev: true + log-driver@1.2.7: {} - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lru-cache@10.4.3: {} + + lru-cache@11.1.0: {} + + lru-cache@5.1.1: dependencies: yallist: 3.1.1 - dev: true - /make-dir@4.0.0: - resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} - engines: {node: '>=10'} + make-dir@4.0.0: dependencies: semver: 7.7.2 - dev: true - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + make-error@1.3.6: {} - /makeerror@1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + makeerror@1.0.12: dependencies: tmpl: 1.0.5 - dev: true - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true + merge-stream@2.0.0: {} - /micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} + micromatch@4.0.8: dependencies: braces: 3.0.3 picomatch: 2.3.1 - dev: true - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: true + mime-db@1.52.0: {} - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} + mime-types@2.1.35: dependencies: mime-db: 1.52.0 - dev: true - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true + mimic-fn@2.1.0: {} - /minimatch@10.0.3: - resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} - engines: {node: 20 || >=22} + minimatch@10.0.3: dependencies: '@isaacs/brace-expansion': 5.0.0 - dev: true - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.12 - dev: true - /minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} + minimatch@5.1.6: dependencies: brace-expansion: 2.0.2 - dev: true - /minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.5: dependencies: brace-expansion: 2.0.2 - dev: true - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true + minimist@1.2.8: {} - /minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true + minipass@7.1.2: {} - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true + ms@2.1.3: {} - /napi-postinstall@0.2.4: - resolution: {integrity: sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - hasBin: true - dev: true + napi-postinstall@0.2.4: {} - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true + natural-compare@1.4.0: {} - /node-int64@0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - dev: true + node-int64@0.4.0: {} - /node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - dev: true + node-releases@2.0.19: {} - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true + normalize-path@3.0.0: {} - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} + npm-run-path@4.0.1: dependencies: path-key: 3.1.1 - dev: true - /oauth-sign@0.9.0: - resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} - dev: true + oauth-sign@0.9.0: {} - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + once@1.4.0: dependencies: wrappy: 1.0.2 - dev: true - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 - dev: true - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} + p-limit@2.3.0: dependencies: p-try: 2.2.0 - dev: true - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 - dev: true - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} + p-locate@4.1.0: dependencies: p-limit: 2.3.0 - dev: true - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true + p-try@2.2.0: {} - /package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - dev: true + package-json-from-dist@1.0.1: {} - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} + parse-json@5.2.0: dependencies: '@babel/code-frame': 7.27.1 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - dev: true - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true + path-exists@4.0.0: {} - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true + path-is-absolute@1.0.1: {} - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true + path-key@3.1.1: {} - /path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} + path-scurry@1.11.1: dependencies: lru-cache: 10.4.3 minipass: 7.1.2 - dev: true - /path-scurry@2.0.0: - resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} - engines: {node: 20 || >=22} + path-scurry@2.0.0: dependencies: lru-cache: 11.1.0 minipass: 7.1.2 - dev: true - /performance-now@2.1.0: - resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} - dev: true + performance-now@2.1.0: {} - /picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - dev: true + picocolors@1.1.1: {} - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true + picomatch@2.3.1: {} - /picomatch@4.0.2: - resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} - engines: {node: '>=12'} - dev: true + picomatch@4.0.2: {} - /pirates@4.0.7: - resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} - engines: {node: '>= 6'} - dev: true + pirates@4.0.7: {} - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 - dev: true - /pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + pretty-format@29.7.0: dependencies: '@jest/schemas': 29.6.3 ansi-styles: 5.2.0 react-is: 18.3.1 - dev: true - /pretty-format@30.0.0: - resolution: {integrity: sha512-18NAOUr4ZOQiIR+BgI5NhQE7uREdx4ZyV0dyay5izh4yfQ+1T7BSvggxvRGoXocrRyevqW5OhScUjbi9GB8R8Q==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + pretty-format@30.0.0: dependencies: '@jest/schemas': 30.0.0 ansi-styles: 5.2.0 react-is: 18.3.1 - dev: true - /psl@1.15.0: - resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + psl@1.15.0: dependencies: punycode: 2.3.1 - dev: true - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true + punycode@2.3.1: {} - /pure-rand@7.0.1: - resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} - dev: true + pure-rand@7.0.1: {} - /qs@6.5.3: - resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} - engines: {node: '>=0.6'} - dev: true + qs@6.5.3: {} - /react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - dev: true + react-is@18.3.1: {} - /request@2.88.2: - resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} - engines: {node: '>= 6'} - deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 + request@2.88.2: dependencies: aws-sign2: 0.7.0 aws4: 1.13.2 @@ -2795,99 +3343,50 @@ packages: tough-cookie: 2.5.0 tunnel-agent: 0.6.0 uuid: 3.4.0 - dev: true - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true + require-directory@2.1.1: {} - /resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} + resolve-cwd@3.0.0: dependencies: resolve-from: 5.0.0 - dev: true - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true + resolve-from@5.0.0: {} - /rimraf@6.0.1: - resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} - engines: {node: 20 || >=22} - hasBin: true + rimraf@6.0.1: dependencies: glob: 11.0.3 package-json-from-dist: 1.0.1 - dev: true - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true + safe-buffer@5.2.1: {} - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true + safer-buffer@2.1.2: {} - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true + semver@6.3.1: {} - /semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} - engines: {node: '>=10'} - hasBin: true - dev: true + semver@7.7.2: {} - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - dev: true - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true + shebang-regex@3.0.0: {} - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true + signal-exit@3.0.7: {} - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: true + signal-exit@4.1.0: {} - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true + slash@3.0.0: {} - /source-map-support@0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + source-map-support@0.5.13: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - dev: true - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true + source-map@0.6.1: {} - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true + sprintf-js@1.0.3: {} - /sshpk@1.18.0: - resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} - engines: {node: '>=0.10.0'} - hasBin: true + sshpk@1.18.0: dependencies: asn1: 0.2.6 assert-plus: 1.0.0 @@ -2898,151 +3397,77 @@ packages: jsbn: 0.1.1 safer-buffer: 2.1.2 tweetnacl: 0.14.5 - dev: true - /stack-utils@2.0.6: - resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} - engines: {node: '>=10'} + stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 - dev: true - /string-length@4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} + string-length@4.0.2: dependencies: char-regex: 1.0.2 strip-ansi: 6.0.1 - dev: true - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - dev: true - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} + string-width@5.1.2: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 - dev: true - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - dev: true - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} + strip-ansi@7.1.0: dependencies: ansi-regex: 6.1.0 - dev: true - /strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - dev: true + strip-bom@4.0.0: {} - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true + strip-final-newline@2.0.0: {} - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true + strip-json-comments@3.1.1: {} - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 - dev: true - /supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} + supports-color@8.1.1: dependencies: has-flag: 4.0.0 - dev: true - /synckit@0.11.8: - resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==} - engines: {node: ^14.18.0 || >=16.0.0} + synckit@0.11.8: dependencies: '@pkgr/core': 0.2.7 - dev: true - /test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} + test-exclude@6.0.0: dependencies: '@istanbuljs/schema': 0.1.3 glob: 7.2.3 minimatch: 3.1.2 - dev: true - /tmpl@1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - dev: true + tmpl@1.0.5: {} - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - dev: true - /tough-cookie@2.5.0: - resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} - engines: {node: '>=0.8'} + tough-cookie@2.5.0: dependencies: psl: 1.15.0 punycode: 2.3.1 - dev: true - /ts-jest@29.4.0(@babel/core@7.27.4)(jest@30.0.0)(typescript@5.8.3): - resolution: {integrity: sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==} - engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} - hasBin: true - 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 - esbuild: '*' - jest: ^29.0.0 || ^30.0.0 - jest-util: ^29.0.0 || ^30.0.0 - typescript: '>=4.3 <6' - peerDependenciesMeta: - '@babel/core': - optional: true - '@jest/transform': - optional: true - '@jest/types': - optional: true - babel-jest: - optional: true - esbuild: - optional: true - jest-util: - optional: true + ts-jest@29.4.0(@babel/core@7.27.4)(@jest/transform@30.0.0)(@jest/types@30.0.0)(babel-jest@30.0.0(@babel/core@7.27.4))(jest-util@30.0.0)(jest@30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)))(typescript@5.8.3): dependencies: - '@babel/core': 7.27.4 bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2) + jest: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 @@ -3050,21 +3475,14 @@ packages: type-fest: 4.41.0 typescript: 5.8.3 yargs-parser: 21.1.1 - dev: true + optionalDependencies: + '@babel/core': 7.27.4 + '@jest/transform': 30.0.0 + '@jest/types': 30.0.0 + babel-jest: 30.0.0(@babel/core@7.27.4) + jest-util: 30.0.0 - /ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3): - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true + ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -3082,48 +3500,26 @@ packages: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - /tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - requiresBuild: true - dev: true + tslib@2.8.1: optional: true - /tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + tunnel-agent@0.6.0: dependencies: safe-buffer: 5.2.1 - dev: true - /tweetnacl@0.14.5: - resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} - dev: true + tweetnacl@0.14.5: {} - /type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - dev: true + type-detect@4.0.8: {} - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true + type-fest@0.21.3: {} - /type-fest@4.41.0: - resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} - engines: {node: '>=16'} - dev: true + type-fest@4.41.0: {} - /typescript@5.8.3: - resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} - engines: {node: '>=14.17'} - hasBin: true + typescript@5.8.3: {} - /undici-types@7.8.0: - resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} + undici-types@7.8.0: {} - /unrs-resolver@1.9.0: - resolution: {integrity: sha512-wqaRu4UnzBD2ABTC1kLfBjAqIDZ5YUTr/MLGa7By47JV1bJDSW7jq/ZSLigB7enLe7ubNaJhtnBXgrc/50cEhg==} - requiresBuild: true + unrs-resolver@1.9.0: dependencies: napi-postinstall: 0.2.4 optionalDependencies: @@ -3146,113 +3542,67 @@ packages: '@unrs/resolver-binding-win32-arm64-msvc': 1.9.0 '@unrs/resolver-binding-win32-ia32-msvc': 1.9.0 '@unrs/resolver-binding-win32-x64-msvc': 1.9.0 - dev: true - /update-browserslist-db@1.1.3(browserslist@4.25.0): - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' + update-browserslist-db@1.1.3(browserslist@4.25.0): dependencies: browserslist: 4.25.0 escalade: 3.2.0 picocolors: 1.1.1 - dev: true - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + uri-js@4.4.1: dependencies: punycode: 2.3.1 - dev: true - /uuid@3.4.0: - resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} - deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. - hasBin: true - dev: true + uuid@3.4.0: {} - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + v8-compile-cache-lib@3.0.1: {} - /v8-to-istanbul@9.3.0: - resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} - engines: {node: '>=10.12.0'} + v8-to-istanbul@9.3.0: dependencies: '@jridgewell/trace-mapping': 0.3.25 '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 - dev: true - /verror@1.10.0: - resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} - engines: {'0': node >=0.6.0} + verror@1.10.0: dependencies: assert-plus: 1.0.0 core-util-is: 1.0.2 extsprintf: 1.3.0 - dev: true - /walker@1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + walker@1.0.8: dependencies: makeerror: 1.0.12 - dev: true - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@2.0.2: dependencies: isexe: 2.0.0 - dev: true - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} + wrap-ansi@8.1.0: dependencies: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 - dev: true - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true + wrappy@1.0.2: {} - /write-file-atomic@5.0.1: - resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + write-file-atomic@5.0.1: dependencies: imurmurhash: 0.1.4 signal-exit: 4.1.0 - dev: true - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true + y18n@5.0.8: {} - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true + yallist@3.1.1: {} - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true + yargs-parser@21.1.1: {} - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} + yargs@17.7.2: dependencies: cliui: 8.0.1 escalade: 3.2.0 @@ -3261,13 +3611,7 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: true - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} + yn@3.1.1: {} - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true + yocto-queue@0.1.0: {} diff --git a/src/cli.ts b/src/cli.ts index ca81af5..9dffe3f 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -3,10 +3,76 @@ import * as path from 'path'; import * as fs from 'fs'; import { program as commanderProgram } from 'commander'; -import * as csv from 'fast-csv'; -import { OHLCV, IOHLCV } from './types'; +import { IOHLCV } from './types'; import { resampleOhlcv } from './lib'; -import { Readable, Writable } from 'stream'; + +export function parseCSV(data: string): IOHLCV[] { + const trimmed = data.trim(); + if (!trimmed) { + throw new Error('Error: CSV must have at least one row'); + } + const lines = trimmed.split('\n'); + let headers: string[]; + let startIndex: number; + const requiredFields = ['time', 'open', 'high', 'low', 'close', 'volume']; + + // If the first line matches the required fields, treat as header + const firstLine = lines[0].trim(); + const firstLineFields = firstLine.split(',').map(h => h.trim()); + if (requiredFields.every((f, i) => firstLineFields[i] === f)) { + headers = firstLineFields; + startIndex = 1; + } else { + headers = requiredFields; + startIndex = 0; + } + + const rows: IOHLCV[] = []; + for (let i = startIndex; i < lines.length; i++) { + if (!lines[i].trim()) continue; // skip empty lines + const values = lines[i].split(',').map(v => v.trim()); + if (values.length !== headers.length) { + // Skip lines that do not have exactly 5 commas (6 columns) + continue; + } + const row: any = {}; + headers.forEach((header, index) => { + row[header] = values[index]; + }); + const missingValues = requiredFields.filter(field => row[field] === undefined || row[field] === ''); + if (missingValues.length > 0) { + // Skip lines with missing required values + continue; + } + // Skip lines with non-numeric values + if (isNaN(Number(row.time)) || isNaN(Number(row.open)) || isNaN(Number(row.high)) || isNaN(Number(row.low)) || isNaN(Number(row.close)) || isNaN(Number(row.volume))) { + continue; + } + rows.push({ + time: Number(row.time), + open: Number(row.open), + high: Number(row.high), + low: Number(row.low), + close: Number(row.close), + volume: Number(row.volume) + }); + } + return rows; +} + +export function detectFormat(data: string): 'csv' | 'json' { + try { + JSON.parse(data); + return 'json'; + } catch { + const firstLine = data.split('\n')[0].trim(); + // If the first line has exactly 5 commas, it's likely CSV (6 columns) + if ((firstLine.match(/,/g) || []).length === 5) { + return 'csv'; + } + throw new Error('Could not detect input format. Please specify --input-format'); + } +} export async function runCli( argv: string[], @@ -31,32 +97,6 @@ export async function runCli( const options = program.opts(); - function detectFormat(data: string): 'csv' | 'json' { - try { - JSON.parse(data); - return 'json'; - } catch { - const firstLine = data.split('\n')[0].trim(); - if (firstLine.includes(',')) { - const headers = firstLine.toLowerCase().split(','); - if ( - headers.includes('time') && - headers.includes('open') && - headers.includes('high') && - headers.includes('low') && - headers.includes('close') && - headers.includes('volume') - ) { - return 'csv'; - } - if (headers.length === 6 && headers.every(h => !isNaN(Number(h)))) { - return 'csv'; - } - } - throw new Error('Could not detect input format. Please specify --input-format'); - } - } - async function readFileData(filePath: string): Promise { try { const inFormat = path.extname(filePath).slice(1).toLowerCase(); @@ -65,57 +105,8 @@ export async function runCli( } const inPath = path.resolve(filePath); if (inFormat === 'csv') { - return await new Promise((resolve, reject) => { - const rows: any[] = []; - let errored = false; - const fileStream = fs.createReadStream(inPath) - .on('error', (err: any) => { - if (errored) return; - errored = true; - const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); - reject(new Error(msg)); - }); - const csvStream = csv.parse({ headers: true }) - .on('data', (row) => { - if (errored) return; - rows.push(row); - }) - .on('end', () => { - if (errored) return; - if (rows.length === 0) { - errored = true; - reject(new Error('Error: No valid CSV data found')); - return; - } - const requiredFields = ['time', 'open', 'high', 'low', 'close', 'volume']; - for (const row of rows) { - const missingFields = requiredFields.filter(field => row[field] === undefined); - if (missingFields.length > 0) { - errored = true; - fileStream.destroy(); - csvStream.destroy(); - reject(new Error('Error: Missing required fields in CSV: ' + missingFields.join(', '))); - return; - } - } - const results = rows.map(row => ({ - time: Number(row.time), - open: Number(row.open), - high: Number(row.high), - low: Number(row.low), - close: Number(row.close), - volume: Number(row.volume) - })); - resolve(results); - }) - .on('error', (err: any) => { - if (errored) return; - errored = true; - const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); - reject(new Error(msg)); - }); - fileStream.pipe(csvStream); - }); + const data = await fs.promises.readFile(inPath, 'utf8'); + return parseCSV(data); } else { const inBuffer = await fs.promises.readFile(inPath); try { @@ -131,85 +122,67 @@ export async function runCli( } } - async function readPipeData(input: NodeJS.ReadableStream): Promise { + async function readPipeData(stdin: NodeJS.ReadableStream): Promise { return new Promise((resolve, reject) => { - const chunks: Buffer[] = []; - input - .on('data', (chunk) => { - chunks.push(Buffer.from(chunk)); - }) - .on('end', () => { - try { - const data = Buffer.concat(chunks).toString(); - const format = options.inputFormat === 'auto' ? detectFormat(data) : options.inputFormat; - if (format === 'json') { - try { - const jsonData = JSON.parse(data); - resolve(jsonData); - } catch (err) { - reject(new Error('Error: ' + (err instanceof Error ? err.message : String(err)))); - } - } else { - const results: IOHLCV[] = []; - const lines = data.trim().split('\n'); - const hasHeaders = lines[0].toLowerCase().includes('time'); - const csvData = hasHeaders ? data : 'time,open,high,low,close,volume\n' + data; - let hadData = false; - csv.parseString(csvData, { headers: true }) - .on('data', (row) => { - hadData = true; - results.push({ - time: Number(row.time), - open: Number(row.open), - high: Number(row.high), - low: Number(row.low), - close: Number(row.close), - volume: Number(row.volume) - }); - }) - .on('end', () => { - if (!hadData) { - reject(new Error('Error: No valid CSV data found')); - } else { - resolve(results); - } - }) - .on('error', (err) => { - reject(new Error('Error: ' + (err instanceof Error ? err.message : String(err)))); - }); - } - } catch (error) { - reject(new Error('Error: ' + (error instanceof Error ? error.message : String(error)))); + let data = ''; + stdin.on('data', (chunk) => { + data += chunk; + }); + stdin.on('end', () => { + try { + const inFormat = data.trim().startsWith('[') ? 'json' : 'csv'; + if (inFormat === 'csv') { + resolve(parseCSV(data)); + } else { + resolve(JSON.parse(data)); } - }) - .on('error', (err) => { - reject(new Error('Error: ' + (err instanceof Error ? err.message : String(err)))); - }); + } catch (err: any) { + const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); + reject(new Error(msg)); + } + }); + stdin.on('error', (err: any) => { + const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); + reject(new Error(msg)); + }); }); } - async function writeOutput(data: IOHLCV[], outputPath?: string): Promise { - let outStream: NodeJS.WritableStream; + async function writeOutput(data: IOHLCV[], format: 'csv' | 'json', outputPath?: string, stdoutStream: NodeJS.WritableStream = process.stdout): Promise { if (outputPath) { - outStream = fs.createWriteStream(outputPath); - } else { - outStream = stdout; - } - if (options.format === 'csv') { - return new Promise((resolve, reject) => { - const csvStream = csv.write(data, { headers: true }); - csvStream.pipe(outStream); - csvStream.on('error', reject); + const outStream = fs.createWriteStream(outputPath); + await new Promise((resolve, reject) => { outStream.on('error', reject); outStream.on('finish', resolve); + if (format === 'json') { + outStream.write(JSON.stringify(data, null, 2), () => outStream.end()); + } else { + outStream.write('time,open,high,low,close,volume\n'); + data.forEach((row, idx) => { + const line = `${row.time},${row.open},${row.high},${row.low},${row.close},${row.volume}`; + if (idx < data.length - 1) { + outStream.write(line + '\n'); + } else { + outStream.write(line); + } + }); + outStream.end(); + } }); } else { - return new Promise((resolve, reject) => { - outStream.write(JSON.stringify(data, null, 2), (err) => { - if (err) reject(err); - else resolve(); + if (format === 'json') { + stdoutStream.write(JSON.stringify(data, null, 2)); + } else { + stdoutStream.write('time,open,high,low,close,volume\n'); + data.forEach((row, idx) => { + const line = `${row.time},${row.open},${row.high},${row.low},${row.close},${row.volume}`; + if (idx < data.length - 1) { + stdoutStream.write(line + '\n'); + } else { + stdoutStream.write(line); + } }); - }); + } } } @@ -226,7 +199,7 @@ export async function runCli( throw new Error('New timeframe must be greater than base timeframe'); } const resampledData = resampleOhlcv(data, { baseTimeframe, newTimeframe }) as IOHLCV[]; - await writeOutput(resampledData, options.output); + await writeOutput(resampledData, options.format, options.output, stdout); } catch (error: unknown) { stderr.write((error instanceof Error ? error.message : String(error)) + '\n'); process.exitCode = 1; From 4e068f42fd4a327e7bda5683142fa26ca88198a7 Mon Sep 17 00:00:00 2001 From: Adil Date: Mon, 16 Jun 2025 00:59:27 +0500 Subject: [PATCH 12/30] docs: improve function documentation to focus on behavior --- src/cli.ts | 73 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index 9dffe3f..763292a 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -6,7 +6,17 @@ import { program as commanderProgram } from 'commander'; import { IOHLCV } from './types'; import { resampleOhlcv } from './lib'; -export function parseCSV(data: string): IOHLCV[] { +/** + * Parse CSV data containing OHLCV (Open, High, Low, Close, Volume) information + * into a structured array of objects. Each row in the CSV should contain + * timestamp and OHLCV values in the correct order. + * + * @throws Error if the CSV is empty or has invalid format + */ +export function parseCSV( + /** The CSV data string to parse */ + data: string +): IOHLCV[] { const trimmed = data.trim(); if (!trimmed) { throw new Error('Error: CSV must have at least one row'); @@ -60,7 +70,17 @@ export function parseCSV(data: string): IOHLCV[] { return rows; } -export function detectFormat(data: string): 'csv' | 'json' { +/** + * Detect whether the input data contains CSV or JSON formatted OHLCV data. + * The detection is based on the presence of JSON-specific characters and + * structure. + * + * @throws Error if the format cannot be detected + */ +export function detectFormat( + /** The input data string to analyze */ + data: string +): 'csv' | 'json' { try { JSON.parse(data); return 'json'; @@ -74,12 +94,22 @@ export function detectFormat(data: string): 'csv' | 'json' { } } +/** + * Process command-line arguments and execute the OHLCV resampling workflow. + * Coordinates the data flow from input to output, applying the specified + * resampling rules. + */ export async function runCli( + /** Command line arguments array */ argv: string[], + /** Input stream (defaults to process.stdin) */ stdin: NodeJS.ReadableStream = process.stdin, + /** Output stream (defaults to process.stdout) */ stdout: NodeJS.WritableStream = process.stdout, + /** Error stream (defaults to process.stderr) */ stderr: NodeJS.WritableStream = process.stderr, - isTTY: boolean = process.stdin.isTTY // allow override for tests + /** Whether the input is a TTY (defaults to process.stdin.isTTY) */ + isTTY: boolean = process.stdin.isTTY ): Promise { const program = commanderProgram.createCommand(); program @@ -97,7 +127,16 @@ export async function runCli( const options = program.opts(); - async function readFileData(filePath: string): Promise { + /** + * Transform file contents into an array of OHLCV objects. Automatically + * detects and handles both CSV and JSON input formats. + * + * @throws Error if the file cannot be read or parsed + */ + async function readFileData( + /** Path to the input file */ + filePath: string + ): Promise { try { const inFormat = path.extname(filePath).slice(1).toLowerCase(); if (!['csv', 'json'].includes(inFormat)) { @@ -122,7 +161,16 @@ export async function runCli( } } - async function readPipeData(stdin: NodeJS.ReadableStream): Promise { + /** + * Transform stdin data into an array of OHLCV objects. Processes the + * input stream line by line, handling both CSV and JSON formats. + * + * @throws Error if the data cannot be read or parsed + */ + async function readPipeData( + /** The input stream to read from */ + stdin: NodeJS.ReadableStream + ): Promise { return new Promise((resolve, reject) => { let data = ''; stdin.on('data', (chunk) => { @@ -148,7 +196,20 @@ export async function runCli( }); } - async function writeOutput(data: IOHLCV[], format: 'csv' | 'json', outputPath?: string, stdoutStream: NodeJS.WritableStream = process.stdout): Promise { + /** + * Transform OHLCV data into the specified output format. Converts the + * array of objects into either CSV or JSON string representation. + */ + async function writeOutput( + /** Array of OHLCV objects to write */ + data: IOHLCV[], + /** Output format ('csv' or 'json') */ + format: 'csv' | 'json', + /** Optional path to write the output file */ + outputPath?: string, + /** Stream to write to if no outputPath is provided */ + stdoutStream: NodeJS.WritableStream = process.stdout + ): Promise { if (outputPath) { const outStream = fs.createWriteStream(outputPath); await new Promise((resolve, reject) => { From fdbce6fe51bc28ba9ce38a8d5242a5045318d85d Mon Sep 17 00:00:00 2001 From: Adil Date: Mon, 16 Jun 2025 01:03:47 +0500 Subject: [PATCH 13/30] docs: update CLI usage documentation to match current implementation --- README.md | 57 ++++++++++++++++++++++--------------------------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 45bedac..89f6fbd 100644 --- a/README.md +++ b/README.md @@ -189,10 +189,24 @@ ohlc-resample -i input.csv # Resample JSON file with custom timeframes ohlc-resample -i input.json -b 60 -n 300 -# Save output to file +# Save output to file with specific format ohlc-resample -i input.csv -o output.json -f json ``` +### Options + +```bash +Options: + -V, --version Show version number + -i, --input Input file path (csv, json) or use pipe + -o, --output Output file path (csv, json) or use pipe + -f, --format Output file format (csv, json) (default: "json") + --input-format Input format when using pipe (csv, json, auto) (default: "auto") + -b, --base-timeframe Base timeframe in seconds (default: "60") + -n, --new-timeframe New timeframe in seconds (default: "300") + -h, --help Display help for command +``` + ### Input Formats The CLI supports both CSV and JSON input formats: @@ -226,55 +240,30 @@ You can pipe data into the CLI from other commands. The format is automatically # Auto-detect format cat data.json | ohlc-resample cat data.csv | ohlc-resample -echo '1609459200000,100,105,95,102,1000' | ohlc-resample # Force specific format cat data.json | ohlc-resample --input-format json cat data.csv | ohlc-resample --input-format csv ``` -The CLI supports three types of pipe input: +The CLI supports two types of pipe input: 1. JSON files/strings with OHLCV objects 2. CSV files/strings with headers (time,open,high,low,close,volume) -3. Raw CSV text without headers (6 comma-separated numbers per line) - -Example of raw CSV text input: -```bash -# Single line -echo '1609459200000,100,105,95,102,1000' | ohlc-resample - -# Multiple lines -echo -e '1609459200000,100,105,95,102,1000\n1609459260000,102,107,101,106,1200' | ohlc-resample -``` - -### Options - -- `-i, --input `: Input file path (CSV or JSON) -- `-o, --output `: Output file path (optional, defaults to stdout) -- `-f, --format `: Output format (csv or json, default: csv) -- `-if, --input-format `: Input format when using pipe (csv, json, or auto, default: auto) -- `-b, --base-timeframe `: Base timeframe in seconds (default: 60) -- `-n, --new-timeframe `: New timeframe in seconds (default: 300) -- `-h, --help`: Display help information -- `-V, --version`: Display version information ### Examples ```bash # Resample 1-minute data to 5-minute candles -ohlc-resample -i data.csv - -# Resample 1-minute data to 15-minute candles -ohlc-resample -i data.csv -b 60 -n 900 +ohlc-resample -i data.csv -b 60 -n 300 -# Convert CSV to JSON -ohlc-resample -i data.csv -o data.json -f json +# Convert CSV to JSON format +ohlc-resample -i data.csv -f json -# Pipe CSV data and save as JSON -cat data.csv | ohlc-resample -o output.json -f json +# Pipe data and save to file +cat data.csv | ohlc-resample -o output.json -# Pipe JSON data with forced format -cat data.json | ohlc-resample --input-format json -o output.csv -f csv +# Resample with custom timeframes and save as CSV +ohlc-resample -i data.json -b 300 -n 3600 -f csv -o output.csv ``` ## Contributors From 8c7c93238812c6d7cfa5ff84009dbed965512fa7 Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 13:31:42 +0500 Subject: [PATCH 14/30] refactor(lib)!: drop default export aliases, add overloads, fix JSDoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: removes the default export from the package entrypoint. The legacy aliases `resample_ohlcv`, `array`, `json`, `trade_to_candle`, and `tick_chart` are gone. Use the named exports `resampleOhlcv`, `resampleTicksByTime`, and `resampleTicksByCount` directly. - `resampleOhlcv` now has overloaded signatures so the return type follows the input shape (`OHLCV[]` in β†’ `OHLCV[]` out, same for `IOHLCV[]`). - Fixed inverted JSDoc on `resampleOhlcvArray`. - Re-export types from the package entrypoint. - Update existing library tests to use named imports. --- .npmignore | 15 --------------- __tests__/ohlcv.ts | 4 ++-- __tests__/ticks.ts | 10 +++++----- src/index.ts | 10 +--------- src/lib.ts | 37 ++++++++++++++++++++++++------------- 5 files changed, 32 insertions(+), 44 deletions(-) delete mode 100644 .npmignore diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 4dbac10..0000000 --- a/.npmignore +++ /dev/null @@ -1,15 +0,0 @@ -.babelrc -.eslintignore -.eslintrc.json -.gitignore -.lintstagedrc.json -.nycrc -.prettierrc.json -.coveralls.yml - -tsconfig.json -jest.config.js -coverage -src -__tests__ -examples \ No newline at end of file diff --git a/__tests__/ohlcv.ts b/__tests__/ohlcv.ts index 455fa64..65b7d09 100644 --- a/__tests__/ohlcv.ts +++ b/__tests__/ohlcv.ts @@ -1,6 +1,6 @@ "use strict"; -import CConverter, { resampleOhlcv } from "../src/index"; +import { resampleOhlcv } from "../src/index"; import type { IOHLCV, OHLCV } from "../src/types"; // From Binance @@ -164,7 +164,7 @@ const link_btc_1m: Array = [ ]; test("Resample OHLCV in object format - 1m to 2m", () => { - let result = CConverter.json(link_btc_1m, { + let result = resampleOhlcv(link_btc_1m, { baseTimeframe: 60, newTimeframe: 120 }); diff --git a/__tests__/ticks.ts b/__tests__/ticks.ts index 7c68e51..4ed36a8 100644 --- a/__tests__/ticks.ts +++ b/__tests__/ticks.ts @@ -1,6 +1,6 @@ "use strict"; -import Converter from "../src/index"; +import { resampleTicksByTime, resampleTicksByCount } from "../src/index"; import type { Trade } from "../src/types"; const adabnb_trades = [ @@ -370,7 +370,7 @@ const filtered_adabnb_trades: Trade[] = adabnb_trades.map((trade: any) => ({ })); test("Tick Chart Convert 5 tick", () => { - let result = Converter.tick_chart(filtered_adabnb_trades, { + let result = resampleTicksByCount(filtered_adabnb_trades, { tickCount: 5 }); @@ -385,7 +385,7 @@ test("Tick Chart Convert 5 tick", () => { }); test("Resample ticks / trades to OHLCV", () => { - let result = Converter.trade_to_candle(filtered_adabnb_trades, { + let result = resampleTicksByTime(filtered_adabnb_trades, { timeframe: 60, includeLatestCandle: false }); @@ -406,7 +406,7 @@ test("Resample ticks / trades to OHLCV", () => { }); test("Resample ticks / trades to OHLCV – including open candle", () => { - let result = Converter.trade_to_candle(filtered_adabnb_trades, { + let result = resampleTicksByTime(filtered_adabnb_trades, { timeframe: 60 }); @@ -417,7 +417,7 @@ test("Resample ticks / trades to OHLCV – including open candle", () => { }); test("Resample ticks / trades to OHLCV - with gaps filled", () => { - let result = Converter.trade_to_candle(filtered_adabnb_trades, { + let result = resampleTicksByTime(filtered_adabnb_trades, { timeframe: 60, fillGaps: true }); diff --git a/src/index.ts b/src/index.ts index f364a52..e06143c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,2 @@ -import * as lib from './lib'; export * from './lib'; - -export default { - resample_ohlcv: lib.resampleOhlcv, - array: lib.resampleOhlcv, - json: lib.resampleOhlcv, - trade_to_candle: lib.resampleTicksByTime, - tick_chart: lib.resampleTicksByCount -}; \ No newline at end of file +export * from './types'; diff --git a/src/lib.ts b/src/lib.ts index 2a8cd9a..bcd545a 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -10,17 +10,26 @@ import sortBy from "lodash/sortBy"; import chunk from "lodash/chunk"; /** -* Resample OHLCV to different timeframe - * @param ohlcvData - * @param options - * @param options.baseTimeframe - * @param options.newTimeframe + * Resample OHLCV data to a coarser timeframe. The return type follows the + * shape of the input β€” pass tuples to get tuples back, pass objects to get + * objects back. + * + * @param ohlcvData OHLCV data in tuple (`OHLCV[]`) or object (`IOHLCV[]`) form. + * @param options.baseTimeframe Source timeframe in seconds. + * @param options.newTimeframe Target timeframe in seconds (must be a multiple of base). */ - -export const resampleOhlcv = ( +export function resampleOhlcv( + ohlcvData: OHLCV[], + options: { baseTimeframe: number; newTimeframe: number } +): OHLCV[]; +export function resampleOhlcv( + ohlcvData: IOHLCV[], + options: { baseTimeframe: number; newTimeframe: number } +): IOHLCV[]; +export function resampleOhlcv( ohlcvData: OHLCV[] | IOHLCV[], - { baseTimeframe = 60, newTimeframe = 300 }: { baseTimeframe: number, newTimeframe: number } -): OHLCV[] | IOHLCV[] => { + { baseTimeframe = 60, newTimeframe = 300 }: { baseTimeframe: number; newTimeframe: number } +): OHLCV[] | IOHLCV[] { if (ohlcvData.length === 0) { throw new Error("input OHLCV data has no candles"); @@ -45,10 +54,12 @@ export const resampleOhlcv = ( } /** - * Resample OHLCV in object format to different timeframe - * @param candledata - * @param baseFrame - * @param newFrame + * Resample OHLCV tuples (`[time, open, high, low, close, volume][]`) to a + * coarser timeframe. + * + * @param candledata Source candles as `OHLCV[]`. + * @param baseFrame Source timeframe in seconds. + * @param newFrame Target timeframe in seconds (must be a multiple of base). */ export const resampleOhlcvArray = ( From 540f98e3d40f9f59c37c7c44361532287af52074 Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 13:31:54 +0500 Subject: [PATCH 15/30] feat(cli)!: wire --input-format, add --shape flag, refactor internals BREAKING CHANGE: `parseCSV` (CLI helper, not part of the library API) now returns `{ rows, skipped }` instead of `IOHLCV[]`. Issue #8's "standardize to OHLCV (array-of-arrays)" bullet is now addressed. - `--input-format ` now actually honors the requested format (was previously a no-op heuristic that ignored the flag). - New `-s, --shape ` flag for OHLCV tuple vs object JSON output. Auto-detects shape on JSON input and preserves it through the pipeline by default. - `parseCSV` reports skipped rows; the CLI now warns to stderr and errors out when a CSV produces zero valid rows (was silently exiting 0 with empty output). - Collapsed triple-nested error wrapping in `readFileData` to a single `prefixError` helper. - Extracted `formatCSV`/`formatJSON` writer helpers. - SIGINT/SIGTERM now use `process.exit()` so they preserve a previously-set non-zero `exitCode`. - Dropped redundant `stdoutStream` default in `writeOutput`. - Tests now check the real `process.exitCode` (the previous `getExitCode()` helper was a tautology). Added array-of-arrays shape coverage. - README CLI section updated for the new flags. --- README.md | 27 ++- __tests__/cli.ts | 490 +++++++++++++++++++++++------------------------ src/cli.ts | 361 ++++++++++++++++------------------ 3 files changed, 427 insertions(+), 451 deletions(-) diff --git a/README.md b/README.md index 89f6fbd..cdfece0 100644 --- a/README.md +++ b/README.md @@ -197,16 +197,31 @@ ohlc-resample -i input.csv -o output.json -f json ```bash Options: - -V, --version Show version number - -i, --input Input file path (csv, json) or use pipe - -o, --output Output file path (csv, json) or use pipe - -f, --format Output file format (csv, json) (default: "json") - --input-format Input format when using pipe (csv, json, auto) (default: "auto") + -V, --version Show version number + -i, --input Input file path (csv, json) or use pipe + -o, --output Output file path (csv, json) or use stdout + -f, --format Output format (csv, json) (default: "json") + --input-format Input format when piping (csv, json, auto) (default: "auto") + -s, --shape Output shape for JSON: object, array, auto (default: "auto") -b, --base-timeframe Base timeframe in seconds (default: "60") -n, --new-timeframe New timeframe in seconds (default: "300") - -h, --help Display help for command + -h, --help Display help for command ``` +### OHLCV shapes + +The CLI accepts and emits two equivalent JSON shapes: + +```json +// object shape (IOHLCV[]) +[{ "time": 1609459200000, "open": 100, "high": 105, "low": 95, "close": 102, "volume": 1000 }] + +// array shape (OHLCV[], CCXT-style tuple) +[[1609459200000, 100, 105, 95, 102, 1000]] +``` + +Input shape is auto-detected. Output shape mirrors input by default; override with `-s array` or `-s object`. CSV input is always parsed as object-shape; CSV output is always rows. + ### Input Formats The CLI supports both CSV and JSON input formats: diff --git a/__tests__/cli.ts b/__tests__/cli.ts index 1ee56cd..8612a60 100644 --- a/__tests__/cli.ts +++ b/__tests__/cli.ts @@ -1,404 +1,386 @@ import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; -import { IOHLCV } from '../src/types'; -import { withTimeout } from './utils'; -import { runCli, parseCSV } from '../src/cli'; import { Readable, Writable } from 'stream'; +import { IOHLCV, OHLCV } from '../src/types'; +import { withTimeout } from './utils'; +import { runCli, parseCSV, detectFormat } from '../src/cli'; describe('CLI', () => { let tempDir: string; let testData: IOHLCV[]; + let testDataArray: OHLCV[]; let csvPath: string; let jsonPath: string; + let jsonArrayPath: string; + + const expectedCandle = { + time: 1609459200000, + open: 100, + high: 108, + low: 95, + close: 103, + volume: 5000, + }; beforeAll(() => { - // Create test data testData = [ { time: 1609459200000, open: 100, high: 105, low: 95, close: 102, volume: 1000 }, { time: 1609459260000, open: 102, high: 107, low: 101, close: 106, volume: 1200 }, { time: 1609459320000, open: 106, high: 108, low: 104, close: 105, volume: 800 }, { time: 1609459380000, open: 105, high: 106, low: 103, close: 104, volume: 900 }, - { time: 1609459440000, open: 104, high: 105, low: 102, close: 103, volume: 1100 } + { time: 1609459440000, open: 104, high: 105, low: 102, close: 103, volume: 1100 }, ]; + testDataArray = testData.map(d => + [d.time, d.open, d.high, d.low, d.close, d.volume] as OHLCV); }); beforeEach(async () => { - // Create temp directory tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'ohlc-resample-test-')); - - // Create test files csvPath = path.join(tempDir, 'test.csv'); jsonPath = path.join(tempDir, 'test.json'); - - // Write CSV file + jsonArrayPath = path.join(tempDir, 'test-array.json'); + const csvContent = 'time,open,high,low,close,volume\n' + testData.map(d => `${d.time},${d.open},${d.high},${d.low},${d.close},${d.volume}`).join('\n'); await fs.promises.writeFile(csvPath, csvContent); - - // Write JSON file await fs.promises.writeFile(jsonPath, JSON.stringify(testData, null, 2)); + await fs.promises.writeFile(jsonArrayPath, JSON.stringify(testDataArray, null, 2)); + + process.exitCode = 0; }); afterEach(async () => { - // Clean up temp directory await fs.promises.rm(tempDir, { recursive: true, force: true }); + process.exitCode = 0; }); - function getWritableStream(exitCode = false) { + function captureWritable() { let data = ''; const writable = new Writable({ write(chunk, _encoding, callback) { data += chunk.toString(); callback(); - } + }, }); - return { - writable, - getData: () => data, - getExitCode: () => exitCode ? 1 : 0 - }; + return { writable, getData: () => data }; } - function getReadableStream(str: string) { + function readableFromString(str: string) { return Readable.from([str]); } describe('File Input', () => { - test('should read CSV file', async () => { + test('reads CSV file', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - await runCli(['node', 'cli.js', '-i', csvPath], undefined, writable, writable, true); + const { writable, getData } = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', csvPath], undefined, writable, err.writable, true); const output = JSON.parse(getData()); - expect(output).toHaveLength(1); // Resampled to 5-minute candle - expect(output[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); + expect(output).toHaveLength(1); + expect(output[0]).toMatchObject(expectedCandle); }, 1000, 'read CSV file'); }); - test('should read JSON file', async () => { + test('reads JSON file (object shape)', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - await runCli(['node', 'cli.js', '-i', jsonPath], undefined, writable, writable, true); + const { writable, getData } = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', jsonPath], undefined, writable, err.writable, true); const output = JSON.parse(getData()); - expect(output).toHaveLength(1); // Resampled to 5-minute candle - expect(output[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); - }, 1000, 'read JSON file'); + expect(output).toHaveLength(1); + expect(output[0]).toMatchObject(expectedCandle); + }, 1000, 'read JSON object file'); + }); + + test('reads JSON file (array shape) and preserves shape on output', async () => { + await withTimeout(async () => { + const { writable, getData } = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', jsonArrayPath], undefined, writable, err.writable, true); + const output = JSON.parse(getData()); + expect(output).toHaveLength(1); + expect(Array.isArray(output[0])).toBe(true); + expect(output[0]).toEqual([1609459200000, 100, 108, 95, 103, 5000]); + }, 1000, 'read JSON array file'); }); - test('should handle invalid file format', async () => { + test('rejects non-csv/json file extension', async () => { await withTimeout(async () => { const invalidFile = path.join(tempDir, 'test.txt'); fs.writeFileSync(invalidFile, 'invalid data'); - const { writable, getData } = getWritableStream(); - await runCli(['node', 'cli.js', '-i', invalidFile], undefined, writable, writable, true); - expect(getData()).toContain('Only CSV and JSON files are accepted'); - }, 1000, 'handle invalid file format'); + const out = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', invalidFile], undefined, out.writable, err.writable, true); + expect(err.getData()).toContain('Only CSV and JSON files are accepted'); + expect(process.exitCode).toBe(1); + }, 1000, 'reject invalid extension'); }); }); describe('Pipe Input', () => { - test('should read from pipe', async () => { + test('reads CSV from pipe', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - const csvContent = fs.readFileSync(csvPath, 'utf8'); - const stdin = getReadableStream(csvContent); - await runCli(['node', 'cli.js'], stdin, writable, writable, false); - const output = JSON.parse(getData()); - expect(output).toHaveLength(1); // Resampled to 5-minute candle - expect(output[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); - }, 1000, 'read from pipe'); + const out = captureWritable(); + const err = captureWritable(); + const stdin = readableFromString(fs.readFileSync(csvPath, 'utf8')); + await runCli(['node', 'cli.js'], stdin, out.writable, err.writable, false); + const output = JSON.parse(out.getData()); + expect(output).toHaveLength(1); + expect(output[0]).toMatchObject(expectedCandle); + }, 1000, 'read pipe CSV'); }); }); - describe('Output Format', () => { - let outputFile: string; + describe('Output --shape flag', () => { + test('--shape array converts object input to tuple output', async () => { + await withTimeout(async () => { + const out = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', jsonPath, '-s', 'array'], undefined, out.writable, err.writable, true); + const output = JSON.parse(out.getData()); + expect(Array.isArray(output[0])).toBe(true); + expect(output[0]).toEqual([1609459200000, 100, 108, 95, 103, 5000]); + }, 1000, '--shape array'); + }); - beforeEach(() => { - outputFile = path.join(tempDir, 'output'); + test('--shape object converts tuple input to object output', async () => { + await withTimeout(async () => { + const out = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', jsonArrayPath, '-s', 'object'], undefined, out.writable, err.writable, true); + const output = JSON.parse(out.getData()); + expect(output[0]).toMatchObject(expectedCandle); + }, 1000, '--shape object'); }); - afterEach(() => { - if (fs.existsSync(outputFile)) { - fs.unlinkSync(outputFile); - } + test('--shape auto preserves CSV-derived object shape', async () => { + await withTimeout(async () => { + const out = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', csvPath], undefined, out.writable, err.writable, true); + const output = JSON.parse(out.getData()); + expect(output[0]).toMatchObject(expectedCandle); + }, 1000, '--shape auto'); }); + }); + + describe('Output Format', () => { + let outputFile: string; + beforeEach(() => { outputFile = path.join(tempDir, 'output'); }); - test('should write CSV output', async () => { + test('writes CSV output', async () => { await withTimeout(async () => { - await runCli(['node', 'cli.js', '-i', jsonPath, '-o', outputFile, '-f', 'csv'], undefined, undefined, undefined, true); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', jsonPath, '-o', outputFile, '-f', 'csv'], undefined, undefined, err.writable, true); const content = fs.readFileSync(outputFile, 'utf8'); expect(content).toContain('time,open,high,low,close,volume'); - expect(content.split('\n')).toHaveLength(2); // header + 1 row (resampled) - }, 1000, 'write CSV output'); + expect(content.split('\n')).toHaveLength(2); + }, 1000, 'write CSV'); }); - test('should write JSON output', async () => { + test('writes JSON output', async () => { await withTimeout(async () => { - await runCli(['node', 'cli.js', '-i', csvPath, '-o', outputFile, '-f', 'json'], undefined, undefined, undefined, true); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', csvPath, '-o', outputFile, '-f', 'json'], undefined, undefined, err.writable, true); const content = JSON.parse(fs.readFileSync(outputFile, 'utf8')); - expect(content).toHaveLength(1); // Resampled to 5-minute candle - expect(content[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); - }, 1000, 'write JSON output'); + expect(content).toHaveLength(1); + expect(content[0]).toMatchObject(expectedCandle); + }, 1000, 'write JSON'); }); - test('should write to stdout when no output file specified', async () => { + test('writes to stdout when no output file is given', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - await runCli(['node', 'cli.js', '-i', jsonPath], undefined, writable, writable, true); - const output = JSON.parse(getData()); - expect(output).toHaveLength(1); // Resampled to 5-minute candle - expect(output[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); - }, 1000, 'write to stdout'); + const out = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', jsonPath], undefined, out.writable, err.writable, true); + const output = JSON.parse(out.getData()); + expect(output).toHaveLength(1); + expect(output[0]).toMatchObject(expectedCandle); + }, 1000, 'write stdout'); }); }); describe('Error Handling', () => { - test('should handle missing input file', async () => { + test('missing input file β†’ exit 1 + ENOENT', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - await runCli(['node', 'cli.js', '-i', 'nonexistent.csv'], undefined, writable, writable, true); - expect(getData()).toContain('no such file or directory'); - }, 1000, 'handle missing input file'); + const out = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', 'nonexistent.csv'], undefined, out.writable, err.writable, true); + expect(err.getData()).toContain('no such file or directory'); + expect(process.exitCode).toBe(1); + }, 1000, 'missing file'); }); - test('should handle invalid JSON', async () => { + test('invalid JSON β†’ exit 1', async () => { await withTimeout(async () => { const invalidJsonFile = path.join(tempDir, 'invalid.json'); fs.writeFileSync(invalidJsonFile, '{invalid json'); - const { writable, getData, getExitCode } = getWritableStream(true); - await runCli(['node', 'cli.js', '-i', invalidJsonFile], undefined, writable, writable, true); - expect(getExitCode()).not.toBe(0); - }, 1000, 'handle invalid JSON'); + const out = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', invalidJsonFile], undefined, out.writable, err.writable, true); + expect(process.exitCode).toBe(1); + expect(err.getData()).toMatch(/Error:/); + }, 1000, 'invalid JSON'); }); - test('should handle invalid CSV', async () => { + test('CSV with all malformed rows β†’ exit 1', async () => { await withTimeout(async () => { const invalidCsvFile = path.join(tempDir, 'invalid.csv'); fs.writeFileSync(invalidCsvFile, 'time,open,high,low,close,volume\n1,2,3,4,5'); - const { writable, getData, getExitCode } = getWritableStream(true); - await runCli(['node', 'cli.js', '-i', invalidCsvFile], undefined, writable, writable, true); - expect(getExitCode()).not.toBe(0); - }, 1000, 'handle invalid CSV'); + const out = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', invalidCsvFile], undefined, out.writable, err.writable, true); + expect(process.exitCode).toBe(1); + expect(err.getData()).toContain('no valid OHLCV rows'); + }, 1000, 'invalid CSV'); }); - test('should handle invalid timeframe values', async () => { + test('non-numeric timeframe β†’ exit 1', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - await runCli(['node', 'cli.js', '-i', csvPath, '-b', 'invalid', '-n', '300'], undefined, writable, writable, true); - expect(getData()).toContain('Timeframes must be valid numbers'); - }, 1000, 'handle invalid timeframe values'); + const out = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', csvPath, '-b', 'invalid', '-n', '300'], undefined, out.writable, err.writable, true); + expect(err.getData()).toContain('Timeframes must be valid numbers'); + expect(process.exitCode).toBe(1); + }, 1000, 'bad timeframe'); }); - test('should handle invalid timeframe relationship', async () => { + test('new <= base timeframe β†’ exit 1', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - await runCli(['node', 'cli.js', '-i', csvPath, '-b', '300', '-n', '60'], undefined, writable, writable, true); - expect(getData()).toContain('New timeframe must be greater than base timeframe'); - }, 1000, 'handle invalid timeframe relationship'); + const out = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', csvPath, '-b', '300', '-n', '60'], undefined, out.writable, err.writable, true); + expect(err.getData()).toContain('New timeframe must be greater than base timeframe'); + expect(process.exitCode).toBe(1); + }, 1000, 'tf relationship'); }); }); describe('Resampling', () => { - test('should resample data with default timeframes', async () => { + test('default timeframes (60s β†’ 300s)', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - await runCli(['node', 'cli.js', '-i', csvPath], undefined, writable, writable, true); - const output = JSON.parse(getData()); - expect(output).toHaveLength(1); // 5 minutes of 1-minute data resampled to 5 minutes - expect(output[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); - }, 1000, 'resample with default timeframes'); + const out = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', csvPath], undefined, out.writable, err.writable, true); + const output = JSON.parse(out.getData()); + expect(output).toHaveLength(1); + expect(output[0]).toMatchObject(expectedCandle); + }, 1000, 'default tf'); }); - test('should resample data with custom timeframes', async () => { + test('custom timeframes (60s β†’ 120s)', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - await runCli(['node', 'cli.js', '-i', csvPath, '-b', '60', '-n', '120'], undefined, writable, writable, true); - const output = JSON.parse(getData()); - expect(output).toHaveLength(2); // 5 minutes of 1-minute data resampled to 2 minutes + const out = captureWritable(); + const err = captureWritable(); + await runCli(['node', 'cli.js', '-i', csvPath, '-b', '60', '-n', '120'], undefined, out.writable, err.writable, true); + const output = JSON.parse(out.getData()); + expect(output).toHaveLength(2); expect(output[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 107, - low: 95, - close: 106, - volume: 2200 + time: 1609459200000, open: 100, high: 107, low: 95, close: 106, volume: 2200, }); - }, 1000, 'resample with custom timeframes'); + }, 1000, 'custom tf'); }); }); - describe('Pipe Input Format Detection', () => { - it('should auto-detect JSON format from pipe', async () => { + describe('--input-format', () => { + test('auto-detects JSON from pipe', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - const jsonContent = fs.readFileSync(jsonPath, 'utf8'); - const stdin = getReadableStream(jsonContent); - await runCli(['node', 'cli.js'], stdin, writable, writable, false); - const result = JSON.parse(getData()); - expect(result).toHaveLength(1); // Resampled to 5-minute candle - expect(result[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); - }, 1000, 'auto-detect JSON format'); + const out = captureWritable(); + const err = captureWritable(); + const stdin = readableFromString(fs.readFileSync(jsonPath, 'utf8')); + await runCli(['node', 'cli.js'], stdin, out.writable, err.writable, false); + expect(JSON.parse(out.getData())[0]).toMatchObject(expectedCandle); + }, 1000, 'auto JSON'); }); - it('should auto-detect CSV format from pipe', async () => { + test('auto-detects CSV from pipe', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - const csvContent = fs.readFileSync(csvPath, 'utf8'); - const stdin = getReadableStream(csvContent); - await runCli(['node', 'cli.js'], stdin, writable, writable, false); - const result = JSON.parse(getData()); - expect(result).toHaveLength(1); // Resampled to 5-minute candle - expect(result[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); - }, 1000, 'auto-detect CSV format'); + const out = captureWritable(); + const err = captureWritable(); + const stdin = readableFromString(fs.readFileSync(csvPath, 'utf8')); + await runCli(['node', 'cli.js'], stdin, out.writable, err.writable, false); + expect(JSON.parse(out.getData())[0]).toMatchObject(expectedCandle); + }, 1000, 'auto CSV'); }); - it('should use forced JSON format from pipe', async () => { + test('--input-format json forces JSON parsing', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - const jsonContent = fs.readFileSync(jsonPath, 'utf8'); - const stdin = getReadableStream(jsonContent); - await runCli(['node', 'cli.js', '--input-format', 'json'], stdin, writable, writable, false); - const result = JSON.parse(getData()); - expect(result).toHaveLength(1); - expect(result[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); - }, 1000, 'force JSON format'); + const out = captureWritable(); + const err = captureWritable(); + const stdin = readableFromString(fs.readFileSync(jsonPath, 'utf8')); + await runCli(['node', 'cli.js', '--input-format', 'json'], stdin, out.writable, err.writable, false); + expect(JSON.parse(out.getData())[0]).toMatchObject(expectedCandle); + }, 1000, 'force JSON'); }); - it('should use forced CSV format from pipe', async () => { + test('--input-format csv forces CSV parsing (errors on JSON-looking input)', async () => { await withTimeout(async () => { - const { writable, getData } = getWritableStream(); - const csvContent = fs.readFileSync(csvPath, 'utf8'); - const stdin = getReadableStream(csvContent); - await runCli(['node', 'cli.js', '--input-format', 'csv'], stdin, writable, writable, false); - const result = JSON.parse(getData()); - expect(result).toHaveLength(1); - expect(result[0]).toMatchObject({ - time: 1609459200000, - open: 100, - high: 108, - low: 95, - close: 103, - volume: 5000 - }); - }, 1000, 'force CSV format'); + const out = captureWritable(); + const err = captureWritable(); + const stdin = readableFromString(fs.readFileSync(jsonPath, 'utf8')); + await runCli(['node', 'cli.js', '--input-format', 'csv'], stdin, out.writable, err.writable, false); + expect(process.exitCode).toBe(1); + }, 1000, 'force CSV on JSON'); }); }); describe('parseCSV', () => { - const { parseCSV } = require('../src/cli'); it('parses CSV with header', () => { - const csv = 'time,open,high,low,close,volume\n1000,1,2,0.5,1.5,10'; - const result = parseCSV(csv); - expect(result).toEqual([{ time: 1000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 }]); + const { rows, skipped } = parseCSV('time,open,high,low,close,volume\n1000,1,2,0.5,1.5,10'); + expect(rows).toEqual([{ time: 1000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 }]); + expect(skipped).toBe(0); }); + it('parses CSV without header', () => { - const csv = '1000,1,2,0.5,1.5,10'; - const result = parseCSV(csv); - expect(result).toEqual([{ time: 1000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 }]); + const { rows } = parseCSV('1000,1,2,0.5,1.5,10'); + expect(rows).toEqual([{ time: 1000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 }]); }); + it('throws for empty CSV', () => { expect(() => parseCSV('')).toThrow('Error: CSV must have at least one row'); }); - it('omits lines with wrong number of columns', () => { - const csv = '1000,1,2,0.5,1.5,10\n2000,1,2,0.5,1.5\n3000,1,2,0.5,1.5,10'; - const result = parseCSV(csv); - expect(result).toEqual([ - { time: 1000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 }, - { time: 3000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 } - ]); - }); - it('omits lines with missing values', () => { - const csv = '1000,1,2,0.5,1.5,10\n2000,1,2,,1.5,10\n3000,1,2,0.5,1.5,10'; - const result = parseCSV(csv); - expect(result).toEqual([ - { time: 1000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 }, - { time: 3000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 } - ]); - }); - it('omits lines with non-numeric values', () => { - const csv = '1000,1,2,0.5,1.5,10\n2000,1,2,0.5,1.5,abc\n3000,1,2,0.5,1.5,10'; - const result = parseCSV(csv); - expect(result).toEqual([ - { time: 1000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 }, - { time: 3000, open: 1, high: 2, low: 0.5, close: 1.5, volume: 10 } - ]); + + it('counts skipped rows with wrong column count', () => { + const { rows, skipped } = parseCSV('1000,1,2,0.5,1.5,10\n2000,1,2,0.5,1.5\n3000,1,2,0.5,1.5,10'); + expect(rows).toHaveLength(2); + expect(skipped).toBe(1); + }); + + it('counts skipped rows with missing values', () => { + const { rows, skipped } = parseCSV('1000,1,2,0.5,1.5,10\n2000,1,2,,1.5,10\n3000,1,2,0.5,1.5,10'); + expect(rows).toHaveLength(2); + expect(skipped).toBe(1); + }); + + it('counts skipped rows with non-numeric values', () => { + const { rows, skipped } = parseCSV('1000,1,2,0.5,1.5,10\n2000,1,2,0.5,1.5,abc\n3000,1,2,0.5,1.5,10'); + expect(rows).toHaveLength(2); + expect(skipped).toBe(1); }); }); describe('detectFormat', () => { - const { detectFormat } = require('../src/cli'); it('detects CSV for 5-comma line', () => { expect(detectFormat('1,2,3,4,5,6')).toBe('csv'); expect(detectFormat('1000,1,2,0.5,1.5,10\n')).toBe('csv'); }); - it('detects JSON for valid JSON', () => { + + it('detects JSON for array-of-objects', () => { expect(detectFormat('[{"time":1,"open":2,"high":3,"low":1,"close":2,"volume":10}]')).toBe('json'); }); + + it('detects JSON for array-of-tuples', () => { + expect(detectFormat('[[1,2,3,1,2,10]]')).toBe('json'); + }); + + it('rejects bare JSON scalars (not an array)', () => { + // Naked numbers/strings parse as JSON but aren't OHLCV input. + expect(() => detectFormat('1000')).toThrow('Could not detect input format'); + }); + it('throws for unknown format', () => { expect(() => detectFormat('foo|bar|baz')).toThrow('Could not detect input format'); }); }); -}); \ No newline at end of file +}); diff --git a/src/cli.ts b/src/cli.ts index 763292a..f4f9bf6 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -3,59 +3,54 @@ import * as path from 'path'; import * as fs from 'fs'; import { program as commanderProgram } from 'commander'; -import { IOHLCV } from './types'; +import { IOHLCV, OHLCV } from './types'; import { resampleOhlcv } from './lib'; +type Shape = 'object' | 'array'; +type InputFormat = 'csv' | 'json'; +type InputFormatOption = InputFormat | 'auto'; +type ShapeOption = Shape | 'auto'; + +const REQUIRED_FIELDS = ['time', 'open', 'high', 'low', 'close', 'volume'] as const; + /** - * Parse CSV data containing OHLCV (Open, High, Low, Close, Volume) information - * into a structured array of objects. Each row in the CSV should contain - * timestamp and OHLCV values in the correct order. - * - * @throws Error if the CSV is empty or has invalid format + * Parse a CSV string of OHLCV rows into `IOHLCV[]`. Accepts an optional + * header row matching the canonical field order; otherwise treats the first + * line as data. Malformed rows (wrong column count, missing values, or + * non-numeric cells) are skipped and counted in `skipped`. + * + * @throws if the input is empty. */ -export function parseCSV( - /** The CSV data string to parse */ - data: string -): IOHLCV[] { +export function parseCSV(data: string): { rows: IOHLCV[]; skipped: number } { const trimmed = data.trim(); if (!trimmed) { throw new Error('Error: CSV must have at least one row'); } const lines = trimmed.split('\n'); - let headers: string[]; - let startIndex: number; - const requiredFields = ['time', 'open', 'high', 'low', 'close', 'volume']; - // If the first line matches the required fields, treat as header - const firstLine = lines[0].trim(); - const firstLineFields = firstLine.split(',').map(h => h.trim()); - if (requiredFields.every((f, i) => firstLineFields[i] === f)) { - headers = firstLineFields; - startIndex = 1; - } else { - headers = requiredFields; - startIndex = 0; - } + const firstLine = lines[0].trim().split(',').map(h => h.trim()); + const hasHeader = REQUIRED_FIELDS.every((f, i) => firstLine[i] === f); + const headers = hasHeader ? firstLine : (REQUIRED_FIELDS as readonly string[]); + const startIndex = hasHeader ? 1 : 0; const rows: IOHLCV[] = []; + let skipped = 0; + for (let i = startIndex; i < lines.length; i++) { - if (!lines[i].trim()) continue; // skip empty lines - const values = lines[i].split(',').map(v => v.trim()); - if (values.length !== headers.length) { - // Skip lines that do not have exactly 5 commas (6 columns) - continue; - } - const row: any = {}; - headers.forEach((header, index) => { - row[header] = values[index]; - }); - const missingValues = requiredFields.filter(field => row[field] === undefined || row[field] === ''); - if (missingValues.length > 0) { - // Skip lines with missing required values + const line = lines[i].trim(); + if (!line) continue; + const values = line.split(',').map(v => v.trim()); + if (values.length !== headers.length) { skipped++; continue; } + + const row: Record = {}; + headers.forEach((header, index) => { row[header] = values[index]; }); + + if (REQUIRED_FIELDS.some(f => row[f] === undefined || row[f] === '')) { + skipped++; continue; } - // Skip lines with non-numeric values - if (isNaN(Number(row.time)) || isNaN(Number(row.open)) || isNaN(Number(row.high)) || isNaN(Number(row.low)) || isNaN(Number(row.close)) || isNaN(Number(row.volume))) { + if (REQUIRED_FIELDS.some(f => isNaN(Number(row[f])))) { + skipped++; continue; } rows.push({ @@ -64,193 +59,179 @@ export function parseCSV( high: Number(row.high), low: Number(row.low), close: Number(row.close), - volume: Number(row.volume) + volume: Number(row.volume), }); } - return rows; + return { rows, skipped }; } /** - * Detect whether the input data contains CSV or JSON formatted OHLCV data. - * The detection is based on the presence of JSON-specific characters and - * structure. - * - * @throws Error if the format cannot be detected + * Detect whether a string is JSON (array of objects or array of tuples) or + * CSV. JSON detection requires the value to parse and be an array. + * + * @throws if neither format is recognized. */ -export function detectFormat( - /** The input data string to analyze */ - data: string -): 'csv' | 'json' { +export function detectFormat(data: string): InputFormat { + const trimmed = data.trim(); try { - JSON.parse(data); - return 'json'; - } catch { - const firstLine = data.split('\n')[0].trim(); - // If the first line has exactly 5 commas, it's likely CSV (6 columns) - if ((firstLine.match(/,/g) || []).length === 5) { - return 'csv'; + const parsed = JSON.parse(trimmed); + if (Array.isArray(parsed)) return 'json'; + } catch { /* fall through */ } + const firstLine = trimmed.split('\n')[0]; + if ((firstLine.match(/,/g) || []).length === 5) return 'csv'; + throw new Error('Could not detect input format. Please specify --input-format'); +} + +/** Detect whether a parsed JSON payload is tuple- or object-shaped. */ +function detectShape(data: unknown[]): Shape { + return data.length > 0 && Array.isArray(data[0]) ? 'array' : 'object'; +} + +const toObjectShape = (data: OHLCV[] | IOHLCV[]): IOHLCV[] => { + if (data.length > 0 && Array.isArray(data[0])) { + return (data as OHLCV[]).map(([time, open, high, low, close, volume]) => ({ + time, open, high, low, close, volume, + })); + } + return data as IOHLCV[]; +}; + +const toArrayShape = (data: OHLCV[] | IOHLCV[]): OHLCV[] => { + if (data.length > 0 && !Array.isArray(data[0])) { + return (data as IOHLCV[]).map(({ time, open, high, low, close, volume }) => + [time, open, high, low, close, volume] as OHLCV); + } + return data as OHLCV[]; +}; + +/** Render OHLCV data as CSV text (with header). */ +function formatCSV(data: OHLCV[] | IOHLCV[]): string { + const rows = toArrayShape(data); + const lines = ['time,open,high,low,close,volume']; + for (const row of rows) lines.push(row.join(',')); + return lines.join('\n'); +} + +/** Render OHLCV data as JSON text in the requested shape. */ +function formatJSON(data: OHLCV[] | IOHLCV[], shape: Shape): string { + const out = shape === 'array' ? toArrayShape(data) : toObjectShape(data); + return JSON.stringify(out, null, 2); +} + +function prefixError(err: unknown): Error { + const msg = err instanceof Error ? err.message : String(err); + return new Error(msg.startsWith('Error:') ? msg : `Error: ${msg}`); +} + +interface ParsedInput { + data: IOHLCV[] | OHLCV[]; + shape: Shape; +} + +function parseInput(raw: string, format: InputFormat): ParsedInput { + if (format === 'csv') { + const { rows, skipped } = parseCSV(raw); + if (rows.length === 0) { + throw new Error('Error: no valid OHLCV rows found in input'); } - throw new Error('Could not detect input format. Please specify --input-format'); + return { data: rows, shape: 'object' }; + } + let parsed: unknown; + try { + parsed = JSON.parse(raw); + } catch (err) { + throw prefixError(err); } + if (!Array.isArray(parsed) || parsed.length === 0) { + throw new Error('Error: JSON input must be a non-empty array of OHLCV records'); + } + return { data: parsed as IOHLCV[] | OHLCV[], shape: detectShape(parsed) }; } /** - * Process command-line arguments and execute the OHLCV resampling workflow. - * Coordinates the data flow from input to output, applying the specified - * resampling rules. + * Run the OHLCV resampling CLI. Streams and TTY flag are injectable for + * testing. */ export async function runCli( - /** Command line arguments array */ argv: string[], - /** Input stream (defaults to process.stdin) */ stdin: NodeJS.ReadableStream = process.stdin, - /** Output stream (defaults to process.stdout) */ stdout: NodeJS.WritableStream = process.stdout, - /** Error stream (defaults to process.stderr) */ stderr: NodeJS.WritableStream = process.stderr, - /** Whether the input is a TTY (defaults to process.stdin.isTTY) */ - isTTY: boolean = process.stdin.isTTY + isTTY: boolean = process.stdin.isTTY, ): Promise { const program = commanderProgram.createCommand(); program .description('Resample OHLCV between timeframes and file formats') - .option('-i, --input ', 'Input file path (csv, json) or use pipe') - .option('-o, --output ', 'Output file path (csv, json) or use pipe') - .option('-f, --format ', 'Output file format (csv, json)', 'json') - .option('--input-format ', 'Input format when using pipe (csv, json, auto)', 'auto') + .option('-i, --input ', 'Input file path (csv, json) or use pipe') + .option('-o, --output ', 'Output file path (csv, json) or use stdout') + .option('-f, --format ', 'Output format (csv, json)', 'json') + .option('--input-format ', 'Input format when piping (csv, json, auto)', 'auto') + .option('-s, --shape ', 'Output shape for JSON (object, array, auto)', 'auto') .option('-b, --base-timeframe ', 'Base timeframe in seconds', '60') .option('-n, --new-timeframe ', 'New timeframe in seconds', '300') - .version('1.3.0'); + .version('2.0.0'); program.parse(argv); program.showHelpAfterError(); - const options = program.opts(); - /** - * Transform file contents into an array of OHLCV objects. Automatically - * detects and handles both CSV and JSON input formats. - * - * @throws Error if the file cannot be read or parsed - */ - async function readFileData( - /** Path to the input file */ - filePath: string - ): Promise { + async function readFileData(filePath: string): Promise { + const ext = path.extname(filePath).slice(1).toLowerCase(); + if (!['csv', 'json'].includes(ext)) { + throw new Error('Only CSV and JSON files are accepted as input'); + } + let raw: string; try { - const inFormat = path.extname(filePath).slice(1).toLowerCase(); - if (!['csv', 'json'].includes(inFormat)) { - throw new Error('Only CSV and JSON files are accepted as input'); - } - const inPath = path.resolve(filePath); - if (inFormat === 'csv') { - const data = await fs.promises.readFile(inPath, 'utf8'); - return parseCSV(data); - } else { - const inBuffer = await fs.promises.readFile(inPath); - try { - return JSON.parse(inBuffer.toString()); - } catch (err: any) { - const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); - throw new Error(msg); - } - } - } catch (err: any) { - const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); - throw new Error(msg); + raw = await fs.promises.readFile(path.resolve(filePath), 'utf8'); + } catch (err) { + throw prefixError(err); + } + const parsed = parseInput(raw, ext as InputFormat); + if (ext === 'csv') { + const { skipped } = parseCSV(raw); + if (skipped > 0) stderr.write(`Warning: skipped ${skipped} malformed CSV row(s)\n`); } + return parsed; } - /** - * Transform stdin data into an array of OHLCV objects. Processes the - * input stream line by line, handling both CSV and JSON formats. - * - * @throws Error if the data cannot be read or parsed - */ - async function readPipeData( - /** The input stream to read from */ - stdin: NodeJS.ReadableStream - ): Promise { - return new Promise((resolve, reject) => { - let data = ''; - stdin.on('data', (chunk) => { - data += chunk; - }); - stdin.on('end', () => { - try { - const inFormat = data.trim().startsWith('[') ? 'json' : 'csv'; - if (inFormat === 'csv') { - resolve(parseCSV(data)); - } else { - resolve(JSON.parse(data)); - } - } catch (err: any) { - const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); - reject(new Error(msg)); - } - }); - stdin.on('error', (err: any) => { - const msg = err && err.message && typeof err.message === 'string' && err.message.startsWith('Error:') ? err.message : 'Error: ' + (err && err.message ? err.message : String(err)); - reject(new Error(msg)); - }); + async function readPipeData(stream: NodeJS.ReadableStream): Promise { + const raw = await new Promise((resolve, reject) => { + let buf = ''; + stream.on('data', chunk => { buf += chunk; }); + stream.on('end', () => resolve(buf)); + stream.on('error', err => reject(prefixError(err))); }); + const requested = options.inputFormat as InputFormatOption; + const format: InputFormat = requested === 'auto' ? detectFormat(raw) : requested; + const parsed = parseInput(raw, format); + if (format === 'csv') { + const { skipped } = parseCSV(raw); + if (skipped > 0) stderr.write(`Warning: skipped ${skipped} malformed CSV row(s)\n`); + } + return parsed; } - /** - * Transform OHLCV data into the specified output format. Converts the - * array of objects into either CSV or JSON string representation. - */ async function writeOutput( - /** Array of OHLCV objects to write */ - data: IOHLCV[], - /** Output format ('csv' or 'json') */ + data: OHLCV[] | IOHLCV[], format: 'csv' | 'json', - /** Optional path to write the output file */ - outputPath?: string, - /** Stream to write to if no outputPath is provided */ - stdoutStream: NodeJS.WritableStream = process.stdout + shape: Shape, + outputPath: string | undefined, ): Promise { + const text = format === 'csv' ? formatCSV(data) : formatJSON(data, shape); if (outputPath) { - const outStream = fs.createWriteStream(outputPath); - await new Promise((resolve, reject) => { - outStream.on('error', reject); - outStream.on('finish', resolve); - if (format === 'json') { - outStream.write(JSON.stringify(data, null, 2), () => outStream.end()); - } else { - outStream.write('time,open,high,low,close,volume\n'); - data.forEach((row, idx) => { - const line = `${row.time},${row.open},${row.high},${row.low},${row.close},${row.volume}`; - if (idx < data.length - 1) { - outStream.write(line + '\n'); - } else { - outStream.write(line); - } - }); - outStream.end(); - } - }); - } else { - if (format === 'json') { - stdoutStream.write(JSON.stringify(data, null, 2)); - } else { - stdoutStream.write('time,open,high,low,close,volume\n'); - data.forEach((row, idx) => { - const line = `${row.time},${row.open},${row.high},${row.low},${row.close},${row.volume}`; - if (idx < data.length - 1) { - stdoutStream.write(line + '\n'); - } else { - stdoutStream.write(line); - } - }); - } + await fs.promises.writeFile(outputPath, text); + return; } + await new Promise((resolve, reject) => { + stdout.write(text, err => (err ? reject(err) : resolve())); + }); } try { - const data = isTTY && options.input + const input = isTTY && options.input ? await readFileData(options.input) : await readPipeData(stdin); + const baseTimeframe = parseInt(options.baseTimeframe, 10); const newTimeframe = parseInt(options.newTimeframe, 10); if (isNaN(baseTimeframe) || isNaN(newTimeframe)) { @@ -259,23 +240,21 @@ export async function runCli( if (newTimeframe <= baseTimeframe) { throw new Error('New timeframe must be greater than base timeframe'); } - const resampledData = resampleOhlcv(data, { baseTimeframe, newTimeframe }) as IOHLCV[]; - await writeOutput(resampledData, options.format, options.output, stdout); + + const resampled = resampleOhlcv(input.data as IOHLCV[], { baseTimeframe, newTimeframe }); + + const requestedShape = options.shape as ShapeOption; + const outputShape: Shape = requestedShape === 'auto' ? input.shape : requestedShape; + + await writeOutput(resampled, options.format, outputShape, options.output); } catch (error: unknown) { stderr.write((error instanceof Error ? error.message : String(error)) + '\n'); process.exitCode = 1; - return; } } -// Only run if this is the entrypoint if (require.main === module) { - // Handle process termination - process.on('SIGINT', () => { - process.exit(0); - }); - process.on('SIGTERM', () => { - process.exit(0); - }); + process.on('SIGINT', () => process.exit()); + process.on('SIGTERM', () => process.exit()); runCli(process.argv); -} \ No newline at end of file +} From 88317d8f799120daddcaace5850a144c4e15eb8b Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 13:32:08 +0500 Subject: [PATCH 16/30] =?UTF-8?q?chore(release)!:=202.0.0=20=E2=80=94=20fi?= =?UTF-8?q?x=20bin,=20modernize=20tooling,=20update=20CI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: `bin.ohlc` now points at `dist/cli.js` (was `src/cli.ts`). The previous binary was non-functional post-install because npm has no way to execute raw TypeScript; this fix changes the resolved path. Combined with the library and CLI breaking changes in the same release, this warrants a major bump. - `bin.ohlc` β†’ `dist/cli.js`; `src/cli.ts` retains its shebang so the emitted JS is directly executable. - Drop unused `chalk` runtime dep; drop `coveralls` devDep. - Move `ts-node` to devDependencies (no longer needed at runtime now that the bin points at compiled JS). - `prebuild` now cleans `dist/` (was incorrectly cleaning `build/`). - `prepublishOnly` simplified: a single test+build pass without the coveralls step that always failed without a token. - Drop obsolete `.npmignore` β€” superseded by `package.json#files`. - Add `types: dist/index.d.ts` to advertise type declarations. - CI workflow now triggers on `main` (was `master`) and runs Node 20.x and 22.x (was EOL 10.x and 12.x). Switched to pnpm with frozen lockfile, bumped action versions. - Added CHANGELOG.md with the full 2.0.0 breaking-change list. --- .github/workflows/nodejs.yml | 31 ++- CHANGELOG.md | 30 +++ package.json | 17 +- pnpm-lock.yaml | 372 +---------------------------------- 4 files changed, 55 insertions(+), 395 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 6c591a1..c28dac6 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -1,29 +1,26 @@ -# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions - name: Node.js CI on: push: - branches: [ master ] + branches: [main] pull_request: - branches: [ master ] + branches: [main] jobs: build: - runs-on: ubuntu-latest - strategy: matrix: - node-version: [10.x, 12.x] - + node-version: [20.x, 22.x] steps: - - uses: actions/checkout@v2 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - run: npm ci - - run: npm run build - - run: npm test + - uses: actions/checkout@v4 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + - uses: pnpm/action-setup@v4 + with: + version: 9 + - run: pnpm install --frozen-lockfile + - run: pnpm run build + - run: pnpm test diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b77db58 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,30 @@ +# Changelog + +## 2.0.0 + +### Breaking changes +- **Removed legacy `default` export** from the package entrypoint. The aliases `resample_ohlcv`, `array`, `json`, `trade_to_candle`, and `tick_chart` are gone β€” use the named exports `resampleOhlcv`, `resampleTicksByTime`, and `resampleTicksByCount` instead. +- **`bin.ohlc` now points at `dist/cli.js`** (was `src/cli.ts`). The previously published binary was non-functional; this fix changes the resolved path post-install. +- **`parseCSV` (CLI helper) now returns `{ rows, skipped }`** instead of `IOHLCV[]`. Internal API; only relevant if you imported it from `ohlc-resample/dist/cli`. + +### CLI +- The CLI is now actually functional β€” replaces the stub in 1.x. +- `--input-format ` now actually honors the requested format (was previously a no-op heuristic). +- New `-s, --shape ` flag for OHLCV tuple vs object JSON output. Closes #8 (the array-of-arrays requirement). +- Auto-detects tuple vs object shape on JSON input and preserves it through the pipeline by default. +- Malformed CSV rows are now reported as a warning to stderr, and a CSV with zero valid rows now exits non-zero instead of producing an empty output. +- SIGINT/SIGTERM no longer clobber a non-zero exit code. + +### Library +- `resampleOhlcv` now has overloaded signatures: pass `OHLCV[]` and TypeScript narrows the return to `OHLCV[]`; pass `IOHLCV[]` and you get `IOHLCV[]`. +- Fixed inverted JSDoc on `resampleOhlcvArray`. +- The package now also re-exports types (`IOHLCV`, `OHLCV`, `TradeTick`, etc.) from the entrypoint. + +### Build & tooling +- Dropped `fast-csv` dependency (1.x branch removed it; 2.0 ships clean). +- Dropped unused `chalk` dep. +- Moved `ts-node` to `devDependencies`. +- Dropped `coveralls` from `prepublishOnly` (was guaranteed to fail without a token). +- `prebuild` now cleans `dist/` (was cleaning a non-existent `build/`). +- CI workflow updated to trigger on `main` and run Node 20.x / 22.x (was `master` + Node 10/12). +- Removed obsolete `.npmignore` (superseded by `package.json#files`). diff --git a/package.json b/package.json index ae1f38c..05b3036 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,9 @@ { "name": "ohlc-resample", - "version": "1.3.0", + "version": "2.0.0", "description": "Resample (inter-convert) trade, ticks or OHLCV data to different time frames, includes CLI", "main": "dist/index.js", + "types": "dist/index.d.ts", "engines": { "node": ">=20.12.2" }, @@ -10,15 +11,14 @@ "dist" ], "scripts": { - "prebuild": "rimraf build", + "prebuild": "rimraf dist", "build": "tsc --build", "build:check": "node -e \"require('./dist')\"", - "prepublishOnly": "npm test && npm run build && npm run coveralls && npm run build && npm run build:check", - "test": "jest", - "coveralls": "jest --coverage --coverageReporters=text-lcov | coveralls" + "prepublishOnly": "npm test && npm run build && npm run build:check", + "test": "jest" }, "bin": { - "ohlc": "./src/cli.ts" + "ohlc": "./dist/cli.js" }, "keywords": [ "ohlc", @@ -46,15 +46,14 @@ "@types/jest": "^29.5.14", "@types/lodash": "^4.14.173", "@types/node": "^24.0.1", - "coveralls": "^3.1.1", "jest": ">=27.2.1", "rimraf": "^6.0.1", "ts-jest": ">=25.1.0", + "ts-node": "^10.9.1", "typescript": "^5.8.3" }, "dependencies": { "commander": "^14.0.0", - "lodash": "^4.17.21", - "ts-node": "^10.9.1" + "lodash": "^4.17.21" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 929e2a5..f51eaed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,9 +14,6 @@ importers: lodash: specifier: ^4.17.21 version: 4.17.21 - ts-node: - specifier: ^10.9.1 - version: 10.9.2(@types/node@24.0.1)(typescript@5.8.3) devDependencies: '@types/jest': specifier: ^29.5.14 @@ -27,9 +24,6 @@ importers: '@types/node': specifier: ^24.0.1 version: 24.0.1 - coveralls: - specifier: ^3.1.1 - version: 3.1.1 jest: specifier: '>=27.2.1' version: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) @@ -39,6 +33,9 @@ importers: ts-jest: specifier: '>=25.1.0' version: 29.4.0(@babel/core@7.27.4)(@jest/transform@30.0.0)(@jest/types@30.0.0)(babel-jest@30.0.0(@babel/core@7.27.4))(jest-util@30.0.0)(jest@30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)))(typescript@5.8.3) + ts-node: + specifier: ^10.9.1 + version: 10.9.2(@types/node@24.0.1)(typescript@5.8.3) typescript: specifier: ^5.8.3 version: 5.8.3 @@ -542,9 +539,6 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} @@ -579,25 +573,9 @@ packages: argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - asn1@0.2.6: - resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} - - assert-plus@1.0.0: - resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} - engines: {node: '>=0.8'} - async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - - aws-sign2@0.7.0: - resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} - - aws4@1.13.2: - resolution: {integrity: sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==} - babel-jest@30.0.0: resolution: {integrity: sha512-JQ0DhdFjODbSawDf0026uZuwaqfKkQzk+9mwWkq2XkKFIaMhFVOxlVmbFCOnnC76jATdxrff3IiUAvOAJec6tw==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} @@ -626,9 +604,6 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - bcrypt-pbkdf@1.0.2: - resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} - brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -669,9 +644,6 @@ packages: caniuse-lite@1.0.30001723: resolution: {integrity: sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==} - caseless@0.12.0: - resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -709,10 +681,6 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - commander@14.0.0: resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} engines: {node: '>=20'} @@ -723,14 +691,6 @@ packages: convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - core-util-is@1.0.2: - resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} - - coveralls@3.1.1: - resolution: {integrity: sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww==} - engines: {node: '>=6'} - hasBin: true - create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} @@ -738,10 +698,6 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - dashdash@1.14.1: - resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} - engines: {node: '>=0.10'} - debug@4.4.1: resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} @@ -763,10 +719,6 @@ packages: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} - delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - detect-newline@3.1.0: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} @@ -782,9 +734,6 @@ packages: eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - ecc-jsbn@0.1.2: - resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} - ejs@3.1.10: resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} engines: {node: '>=0.10.0'} @@ -835,16 +784,6 @@ packages: resolution: {integrity: sha512-xCdPp6gwiR9q9lsPCHANarIkFTN/IMZso6Kkq03sOm9IIGtzK/UJqml0dkhHibGh8HKOj8BIDIpZ0BZuU7QK6w==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - - extsprintf@1.3.0: - resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} - engines: {'0': node >=0.6.0} - - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -866,13 +805,6 @@ packages: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - forever-agent@0.6.1: - resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} - - form-data@2.3.3: - resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} - engines: {node: '>= 0.12'} - fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -897,9 +829,6 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - getpass@0.1.7: - resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} - glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true @@ -920,15 +849,6 @@ packages: graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - har-schema@2.0.0: - resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} - engines: {node: '>=4'} - - har-validator@5.1.5: - resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} - engines: {node: '>=6'} - deprecated: this library is no longer supported - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -936,10 +856,6 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - http-signature@1.2.0: - resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} - engines: {node: '>=0.8', npm: '>=1.3.7'} - human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -979,15 +895,9 @@ packages: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} - is-typedarray@1.0.0: - resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} - isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - isstream@0.1.2: - resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} - istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -1175,9 +1085,6 @@ packages: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true - jsbn@0.1.1: - resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} - jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -1186,28 +1093,11 @@ packages: json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-schema@0.4.0: - resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} - - json-stringify-safe@5.0.1: - resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true - jsprim@1.4.2: - resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} - engines: {node: '>=0.6.0'} - - lcov-parse@1.0.0: - resolution: {integrity: sha512-aprLII/vPzuQvYZnDRU78Fns9I2Ag3gi4Ipga/hxnVMCZC8DnR2nI7XBqrPoywGfxqIx/DgarGvDJZAD3YBTgQ==} - hasBin: true - leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -1225,10 +1115,6 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - log-driver@1.2.7: - resolution: {integrity: sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg==} - engines: {node: '>=0.8.6'} - lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -1256,14 +1142,6 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -1283,9 +1161,6 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} @@ -1315,9 +1190,6 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} - oauth-sign@0.9.0: - resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} - once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -1368,9 +1240,6 @@ packages: resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} engines: {node: 20 || >=22} - performance-now@2.1.0: - resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} - picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1398,28 +1267,12 @@ packages: resolution: {integrity: sha512-18NAOUr4ZOQiIR+BgI5NhQE7uREdx4ZyV0dyay5izh4yfQ+1T7BSvggxvRGoXocrRyevqW5OhScUjbi9GB8R8Q==} engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - psl@1.15.0: - resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - pure-rand@7.0.1: resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} - qs@6.5.3: - resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} - engines: {node: '>=0.6'} - react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - request@2.88.2: - resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} - engines: {node: '>= 6'} - deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 - require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} @@ -1437,12 +1290,6 @@ packages: engines: {node: 20 || >=22} hasBin: true - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -1481,11 +1328,6 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - sshpk@1.18.0: - resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} - engines: {node: '>=0.10.0'} - hasBin: true - stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -1545,10 +1387,6 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - tough-cookie@2.5.0: - resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} - engines: {node: '>=0.8'} - ts-jest@29.4.0: resolution: {integrity: sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==} engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} @@ -1593,12 +1431,6 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} - - tweetnacl@0.14.5: - resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} - type-detect@4.0.8: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} @@ -1628,14 +1460,6 @@ packages: peerDependencies: browserslist: '>= 4.21.0' - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - uuid@3.4.0: - resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} - deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. - hasBin: true - v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} @@ -1643,10 +1467,6 @@ packages: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} - verror@1.10.0: - resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} - engines: {'0': node >=0.6.0} - walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} @@ -2304,13 +2124,6 @@ snapshots: acorn@8.15.0: {} - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 @@ -2338,20 +2151,8 @@ snapshots: dependencies: sprintf-js: 1.0.3 - asn1@0.2.6: - dependencies: - safer-buffer: 2.1.2 - - assert-plus@1.0.0: {} - async@3.2.6: {} - asynckit@0.4.0: {} - - aws-sign2@0.7.0: {} - - aws4@1.13.2: {} - babel-jest@30.0.0(@babel/core@7.27.4): dependencies: '@babel/core': 7.27.4 @@ -2408,10 +2209,6 @@ snapshots: balanced-match@1.0.2: {} - bcrypt-pbkdf@1.0.2: - dependencies: - tweetnacl: 0.14.5 - brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -2450,8 +2247,6 @@ snapshots: caniuse-lite@1.0.30001723: {} - caseless@0.12.0: {} - chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -2481,26 +2276,12 @@ snapshots: color-name@1.1.4: {} - combined-stream@1.0.8: - dependencies: - delayed-stream: 1.0.0 - commander@14.0.0: {} concat-map@0.0.1: {} convert-source-map@2.0.0: {} - core-util-is@1.0.2: {} - - coveralls@3.1.1: - dependencies: - js-yaml: 3.14.1 - lcov-parse: 1.0.0 - log-driver: 1.2.7 - minimist: 1.2.8 - request: 2.88.2 - create-require@1.1.1: {} cross-spawn@7.0.6: @@ -2509,10 +2290,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - dashdash@1.14.1: - dependencies: - assert-plus: 1.0.0 - debug@4.4.1: dependencies: ms: 2.1.3 @@ -2521,8 +2298,6 @@ snapshots: deepmerge@4.3.1: {} - delayed-stream@1.0.0: {} - detect-newline@3.1.0: {} diff-sequences@29.6.3: {} @@ -2531,11 +2306,6 @@ snapshots: eastasianwidth@0.2.0: {} - ecc-jsbn@0.1.2: - dependencies: - jsbn: 0.1.1 - safer-buffer: 2.1.2 - ejs@3.1.10: dependencies: jake: 10.9.2 @@ -2589,12 +2359,6 @@ snapshots: jest-mock: 30.0.0 jest-util: 30.0.0 - extend@3.0.2: {} - - extsprintf@1.3.0: {} - - fast-deep-equal@3.1.3: {} - fast-json-stable-stringify@2.1.0: {} fb-watchman@2.0.2: @@ -2619,14 +2383,6 @@ snapshots: cross-spawn: 7.0.6 signal-exit: 4.1.0 - forever-agent@0.6.1: {} - - form-data@2.3.3: - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -2640,10 +2396,6 @@ snapshots: get-stream@6.0.1: {} - getpass@0.1.7: - dependencies: - assert-plus: 1.0.0 - glob@10.4.5: dependencies: foreground-child: 3.3.1 @@ -2675,23 +2427,10 @@ snapshots: graceful-fs@4.2.11: {} - har-schema@2.0.0: {} - - har-validator@5.1.5: - dependencies: - ajv: 6.12.6 - har-schema: 2.0.0 - has-flag@4.0.0: {} html-escaper@2.0.2: {} - http-signature@1.2.0: - dependencies: - assert-plus: 1.0.0 - jsprim: 1.4.2 - sshpk: 1.18.0 - human-signals@2.1.0: {} import-local@3.2.0: @@ -2718,12 +2457,8 @@ snapshots: is-stream@2.0.1: {} - is-typedarray@1.0.0: {} - isexe@2.0.0: {} - isstream@0.1.2: {} - istanbul-lib-coverage@3.2.2: {} istanbul-lib-instrument@6.0.3: @@ -3128,29 +2863,12 @@ snapshots: argparse: 1.0.10 esprima: 4.0.1 - jsbn@0.1.1: {} - jsesc@3.1.0: {} json-parse-even-better-errors@2.3.1: {} - json-schema-traverse@0.4.1: {} - - json-schema@0.4.0: {} - - json-stringify-safe@5.0.1: {} - json5@2.2.3: {} - jsprim@1.4.2: - dependencies: - assert-plus: 1.0.0 - extsprintf: 1.3.0 - json-schema: 0.4.0 - verror: 1.10.0 - - lcov-parse@1.0.0: {} - leven@3.1.0: {} lines-and-columns@1.2.4: {} @@ -3163,8 +2881,6 @@ snapshots: lodash@4.17.21: {} - log-driver@1.2.7: {} - lru-cache@10.4.3: {} lru-cache@11.1.0: {} @@ -3190,12 +2906,6 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 - mime-db@1.52.0: {} - - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - mimic-fn@2.1.0: {} minimatch@10.0.3: @@ -3214,8 +2924,6 @@ snapshots: dependencies: brace-expansion: 2.0.2 - minimist@1.2.8: {} - minipass@7.1.2: {} ms@2.1.3: {} @@ -3234,8 +2942,6 @@ snapshots: dependencies: path-key: 3.1.1 - oauth-sign@0.9.0: {} - once@1.4.0: dependencies: wrappy: 1.0.2 @@ -3283,8 +2989,6 @@ snapshots: lru-cache: 11.1.0 minipass: 7.1.2 - performance-now@2.1.0: {} - picocolors@1.1.1: {} picomatch@2.3.1: {} @@ -3309,41 +3013,10 @@ snapshots: ansi-styles: 5.2.0 react-is: 18.3.1 - psl@1.15.0: - dependencies: - punycode: 2.3.1 - - punycode@2.3.1: {} - pure-rand@7.0.1: {} - qs@6.5.3: {} - react-is@18.3.1: {} - request@2.88.2: - dependencies: - aws-sign2: 0.7.0 - aws4: 1.13.2 - caseless: 0.12.0 - combined-stream: 1.0.8 - extend: 3.0.2 - forever-agent: 0.6.1 - form-data: 2.3.3 - har-validator: 5.1.5 - http-signature: 1.2.0 - is-typedarray: 1.0.0 - isstream: 0.1.2 - json-stringify-safe: 5.0.1 - mime-types: 2.1.35 - oauth-sign: 0.9.0 - performance-now: 2.1.0 - qs: 6.5.3 - safe-buffer: 5.2.1 - tough-cookie: 2.5.0 - tunnel-agent: 0.6.0 - uuid: 3.4.0 - require-directory@2.1.1: {} resolve-cwd@3.0.0: @@ -3357,10 +3030,6 @@ snapshots: glob: 11.0.3 package-json-from-dist: 1.0.1 - safe-buffer@5.2.1: {} - - safer-buffer@2.1.2: {} - semver@6.3.1: {} semver@7.7.2: {} @@ -3386,18 +3055,6 @@ snapshots: sprintf-js@1.0.3: {} - sshpk@1.18.0: - dependencies: - asn1: 0.2.6 - assert-plus: 1.0.0 - bcrypt-pbkdf: 1.0.2 - dashdash: 1.14.1 - ecc-jsbn: 0.1.2 - getpass: 0.1.7 - jsbn: 0.1.1 - safer-buffer: 2.1.2 - tweetnacl: 0.14.5 - stack-utils@2.0.6: dependencies: escape-string-regexp: 2.0.0 @@ -3457,11 +3114,6 @@ snapshots: dependencies: is-number: 7.0.0 - tough-cookie@2.5.0: - dependencies: - psl: 1.15.0 - punycode: 2.3.1 - ts-jest@29.4.0(@babel/core@7.27.4)(@jest/transform@30.0.0)(@jest/types@30.0.0)(babel-jest@30.0.0(@babel/core@7.27.4))(jest-util@30.0.0)(jest@30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)))(typescript@5.8.3): dependencies: bs-logger: 0.2.6 @@ -3503,12 +3155,6 @@ snapshots: tslib@2.8.1: optional: true - tunnel-agent@0.6.0: - dependencies: - safe-buffer: 5.2.1 - - tweetnacl@0.14.5: {} - type-detect@4.0.8: {} type-fest@0.21.3: {} @@ -3549,12 +3195,6 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 - uri-js@4.4.1: - dependencies: - punycode: 2.3.1 - - uuid@3.4.0: {} - v8-compile-cache-lib@3.0.1: {} v8-to-istanbul@9.3.0: @@ -3563,12 +3203,6 @@ snapshots: '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 - verror@1.10.0: - dependencies: - assert-plus: 1.0.0 - core-util-is: 1.0.2 - extsprintf: 1.3.0 - walker@1.0.8: dependencies: makeerror: 1.0.12 From 4804f3bcd8bc269102abaa4b22462e8c89d18c74 Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 13:39:04 +0500 Subject: [PATCH 17/30] =?UTF-8?q?chore(test):=20migrate=20jest=20=E2=86=92?= =?UTF-8?q?=20vitest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace jest + ts-jest + @types/jest with vitest + @vitest/coverage-v8. - New `vitest.config.ts`, drops `jest.config.js` (incl. its ts-jest `ignoreCodes: [2345]` workaround). - Add `test:watch` and `test:coverage` scripts. The default `test` script no longer collects coverage on every run; use `test:coverage` on demand. - Add explicit `import { ... } from 'vitest'` at the top of each test file. `jest.spyOn` β†’ `vi.spyOn` in the one place it appears. - Fix a pre-existing race in `withTimeout`: a slow `testFn` could log after the test had torn down ("Cannot log after tests are done"). Tracked via a `settled` flag so post-rejection resolutions are ignored. Cold-start test time: ~9s β†’ ~2.5s. --- CHANGELOG.md | 1 + __tests__/cli.ts | 1 + __tests__/ohlcv.ts | 1 + __tests__/ticks.ts | 1 + __tests__/utils.ts | 34 +- jest.config.js | 14 - package.json | 12 +- pnpm-lock.yaml | 3150 ++++++++++---------------------------------- vitest.config.ts | 12 + 9 files changed, 741 insertions(+), 2485 deletions(-) delete mode 100644 jest.config.js create mode 100644 vitest.config.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index b77db58..4906af2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ - The package now also re-exports types (`IOHLCV`, `OHLCV`, `TradeTick`, etc.) from the entrypoint. ### Build & tooling +- **Test runner: jest β†’ vitest.** Replaces `jest` + `ts-jest` + `@types/jest` with `vitest` + `@vitest/coverage-v8`. Cold-start test time drops from ~9s to ~2.5s. Removed the `ts-jest` `ignoreCodes: [2345]` workaround. Added `test:watch` and `test:coverage` scripts; the default `test` script no longer auto-collects coverage on every run. - Dropped `fast-csv` dependency (1.x branch removed it; 2.0 ships clean). - Dropped unused `chalk` dep. - Moved `ts-node` to `devDependencies`. diff --git a/__tests__/cli.ts b/__tests__/cli.ts index 8612a60..3aa727d 100644 --- a/__tests__/cli.ts +++ b/__tests__/cli.ts @@ -1,3 +1,4 @@ +import { describe, it, test, expect, beforeAll, beforeEach, afterEach } from 'vitest'; import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; diff --git a/__tests__/ohlcv.ts b/__tests__/ohlcv.ts index 65b7d09..1159a83 100644 --- a/__tests__/ohlcv.ts +++ b/__tests__/ohlcv.ts @@ -1,5 +1,6 @@ "use strict"; +import { test, expect } from "vitest"; import { resampleOhlcv } from "../src/index"; import type { IOHLCV, OHLCV } from "../src/types"; diff --git a/__tests__/ticks.ts b/__tests__/ticks.ts index 4ed36a8..54d0604 100644 --- a/__tests__/ticks.ts +++ b/__tests__/ticks.ts @@ -1,5 +1,6 @@ "use strict"; +import { test, expect } from "vitest"; import { resampleTicksByTime, resampleTicksByCount } from "../src/index"; import type { Trade } from "../src/types"; diff --git a/__tests__/utils.ts b/__tests__/utils.ts index 5d2f11d..f656d2e 100644 --- a/__tests__/utils.ts +++ b/__tests__/utils.ts @@ -1,20 +1,32 @@ +import { describe, it, expect, vi } from 'vitest'; import { performance } from 'perf_hooks'; +/** + * Wrap a test function with a soft timeout that rejects past `timeoutMs` and + * warns when the function runs past 80% of the budget. Once timed out, any + * later resolution from the wrapped function is ignored, so a slow `testFn` + * cannot log after the test has torn down. + */ export function withTimeout( testFn: () => Promise, timeoutMs: number = 5000, testName: string = 'unnamed test' ): Promise { const startTime = performance.now(); - + let settled = false; + return new Promise((resolve, reject) => { const timeoutId = setTimeout(() => { + if (settled) return; + settled = true; const elapsed = performance.now() - startTime; reject(new Error(`Test "${testName}" took ${elapsed.toFixed(2)}ms (exceeded ${timeoutMs}ms timeout)`)); }, timeoutMs); testFn() .then((result) => { + if (settled) return; + settled = true; clearTimeout(timeoutId); const elapsed = performance.now() - startTime; if (elapsed > timeoutMs * 0.8) { @@ -23,6 +35,8 @@ export function withTimeout( resolve(result); }) .catch((error) => { + if (settled) return; + settled = true; clearTimeout(timeoutId); reject(error); }); @@ -30,16 +44,12 @@ export function withTimeout( } describe('withTimeout utility', () => { - it('should resolve when test completes within timeout', async () => { - const result = await withTimeout( - async () => 'success', - 1000, - 'fast test' - ); + it('resolves when test completes within timeout', async () => { + const result = await withTimeout(async () => 'success', 1000, 'fast test'); expect(result).toBe('success'); }); - it('should reject when test exceeds timeout', async () => { + it('rejects when test exceeds timeout', async () => { await expect(withTimeout( async () => { await new Promise(resolve => setTimeout(resolve, 2000)); @@ -50,9 +60,9 @@ describe('withTimeout utility', () => { )).rejects.toThrow('exceeded 1000ms timeout'); }); - it('should warn when test takes more than 80% of timeout', async () => { - const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(); - + it('warns when test takes more than 80% of timeout', async () => { + const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); + await withTimeout( async () => { await new Promise(resolve => setTimeout(resolve, 800)); @@ -65,4 +75,4 @@ describe('withTimeout utility', () => { expect(consoleSpy).toHaveBeenCalledWith(expect.stringContaining('80% of 1000ms timeout')); consoleSpy.mockRestore(); }); -}); \ No newline at end of file +}); diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index de09d6f..0000000 --- a/jest.config.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - collectCoverage: true, - coveragePathIgnorePatterns: ['/node_modules|dist/'], - collectCoverageFrom: ['src/**/*.ts'], - transform: { - '.(ts|tsx)': ['ts-jest', { - diagnostics: { - ignoreCodes: [2345] - } - }] - }, - testRegex: '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$', - moduleFileExtensions: ['ts', 'tsx', 'js'], -}; \ No newline at end of file diff --git a/package.json b/package.json index 05b3036..912d6e0 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,9 @@ "build": "tsc --build", "build:check": "node -e \"require('./dist')\"", "prepublishOnly": "npm test && npm run build && npm run build:check", - "test": "jest" + "test": "vitest run", + "test:watch": "vitest", + "test:coverage": "vitest run --coverage" }, "bin": { "ohlc": "./dist/cli.js" @@ -43,14 +45,12 @@ }, "homepage": "https://github.com/adiled/ohlc-resample#readme", "devDependencies": { - "@types/jest": "^29.5.14", "@types/lodash": "^4.14.173", "@types/node": "^24.0.1", - "jest": ">=27.2.1", + "@vitest/coverage-v8": "^2.1.0", "rimraf": "^6.0.1", - "ts-jest": ">=25.1.0", - "ts-node": "^10.9.1", - "typescript": "^5.8.3" + "typescript": "^5.8.3", + "vitest": "^2.1.0" }, "dependencies": { "commander": "^14.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f51eaed..91b9877 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,30 +15,24 @@ importers: specifier: ^4.17.21 version: 4.17.21 devDependencies: - '@types/jest': - specifier: ^29.5.14 - version: 29.5.14 '@types/lodash': specifier: ^4.14.173 version: 4.17.17 '@types/node': specifier: ^24.0.1 version: 24.0.1 - jest: - specifier: '>=27.2.1' - version: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) + '@vitest/coverage-v8': + specifier: ^2.1.0 + version: 2.1.9(vitest@2.1.9(@types/node@24.0.1)) rimraf: specifier: ^6.0.1 version: 6.0.1 - ts-jest: - specifier: '>=25.1.0' - version: 29.4.0(@babel/core@7.27.4)(@jest/transform@30.0.0)(@jest/types@30.0.0)(babel-jest@30.0.0(@babel/core@7.27.4))(jest-util@30.0.0)(jest@30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)))(typescript@5.8.3) - ts-node: - specifier: ^10.9.1 - version: 10.9.2(@types/node@24.0.1)(typescript@5.8.3) typescript: specifier: ^5.8.3 version: 5.8.3 + vitest: + specifier: ^2.1.0 + version: 2.1.9(@types/node@24.0.1) packages: @@ -46,40 +40,6 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@babel/code-frame@7.27.1': - resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.27.5': - resolution: {integrity: sha512-KiRAp/VoJaWkkte84TvUd9qjdbZAdiqyvMxrGl1N6vzFogKmaLgoM3L1kgtLicp2HP5fBJS8JrZKLVIZGVJAVg==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.27.4': - resolution: {integrity: sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.27.5': - resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.27.2': - resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.27.1': - resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.27.3': - resolution: {integrity: sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-plugin-utils@7.27.1': - resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} - engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -88,137 +48,155 @@ packages: resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.27.1': - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.27.6': - resolution: {integrity: sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==} - engines: {node: '>=6.9.0'} - '@babel/parser@7.27.5': resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-syntax-async-generators@7.8.4': - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@babel/types@7.27.6': + resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} + engines: {node: '>=6.9.0'} - '@babel/plugin-syntax-bigint@7.8.3': - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - '@babel/plugin-syntax-class-properties@7.12.13': - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] - '@babel/plugin-syntax-class-static-block@7.14.5': - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] - '@babel/plugin-syntax-import-attributes@7.27.1': - resolution: {integrity: sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] - '@babel/plugin-syntax-import-meta@7.10.4': - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] - '@babel/plugin-syntax-json-strings@7.8.3': - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] - '@babel/plugin-syntax-jsx@7.27.1': - resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] - '@babel/plugin-syntax-logical-assignment-operators@7.10.4': - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] - '@babel/plugin-syntax-numeric-separator@7.10.4': - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] - '@babel/plugin-syntax-object-rest-spread@7.8.3': - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] - '@babel/plugin-syntax-optional-catch-binding@7.8.3': - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] - '@babel/plugin-syntax-optional-chaining@7.8.3': - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] - '@babel/plugin-syntax-private-property-in-object@7.14.5': - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] - '@babel/plugin-syntax-top-level-await@7.14.5': - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] - '@babel/plugin-syntax-typescript@7.27.1': - resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] - '@babel/template@7.27.2': - resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} - engines: {node: '>=6.9.0'} + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] - '@babel/traverse@7.27.4': - resolution: {integrity: sha512-oNcu2QbHqts9BtOWJosOVJapWjBDSxGCpFvikNR5TGDYDQf3JwpIoMzIKrvfoti93cLfPJEG4tH9SPVeyCGgdA==} - engines: {node: '>=6.9.0'} + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] - '@babel/types@7.27.6': - resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} - engines: {node: '>=6.9.0'} + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] - '@bcoe/v8-coverage@0.2.3': - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] - '@cspotcode/source-map-support@0.8.1': - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} + cpu: [x64] + os: [sunos] - '@emnapi/core@1.4.3': - resolution: {integrity: sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==} + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] - '@emnapi/runtime@1.4.3': - resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] - '@emnapi/wasi-threads@1.0.2': - resolution: {integrity: sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==} + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} @@ -232,108 +210,10 @@ packages: resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} - '@istanbuljs/load-nyc-config@1.1.0': - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} - '@istanbuljs/schema@0.1.3': resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} - '@jest/console@30.0.0': - resolution: {integrity: sha512-vfpJap6JZQ3I8sUN8dsFqNAKJYO4KIGxkcB+3Fw7Q/BJiWY5HwtMMiuT1oP0avsiDhjE/TCLaDgbGfHwDdBVeg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/core@30.0.0': - resolution: {integrity: sha512-1zU39zFtWSl5ZuDK3Rd6P8S28MmS4F11x6Z4CURrgJ99iaAJg68hmdJ2SAHEEO6ociaNk43UhUYtHxWKEWoNYw==} - 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 - - '@jest/diff-sequences@30.0.0': - resolution: {integrity: sha512-xMbtoCeKJDto86GW6AiwVv7M4QAuI56R7dVBr1RNGYbOT44M2TIzOiske2RxopBqkumDY+A1H55pGvuribRY9A==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/environment@30.0.0': - resolution: {integrity: sha512-09sFbMMgS5JxYnvgmmtwIHhvoyzvR5fUPrVl8nOCrC5KdzmmErTcAxfWyAhJ2bv3rvHNQaKiS+COSG+O7oNbXw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/expect-utils@29.7.0': - resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/expect-utils@30.0.0': - resolution: {integrity: sha512-UiWfsqNi/+d7xepfOv8KDcbbzcYtkWBe3a3kVDtg6M1kuN6CJ7b4HzIp5e1YHrSaQaVS8sdCoyCMCZClTLNKFQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/expect@30.0.0': - resolution: {integrity: sha512-XZ3j6syhMeKiBknmmc8V3mNIb44kxLTbOQtaXA4IFdHy+vEN0cnXRzbRjdGBtrp4k1PWyMWNU3Fjz3iejrhpQg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/fake-timers@30.0.0': - resolution: {integrity: sha512-yzBmJcrMHAMcAEbV2w1kbxmx8WFpEz8Cth3wjLMSkq+LO8VeGKRhpr5+BUp7PPK+x4njq/b6mVnDR8e/tPL5ng==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/get-type@30.0.0': - resolution: {integrity: sha512-VZWMjrBzqfDKngQ7sUctKeLxanAbsBFoZnPxNIG6CmxK7Gv6K44yqd0nzveNIBfuhGZMmk1n5PGbvdSTOu0yTg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/globals@30.0.0': - resolution: {integrity: sha512-OEzYes5A1xwBJVMPqFRa8NCao8Vr42nsUZuf/SpaJWoLE+4kyl6nCQZ1zqfipmCrIXQVALC5qJwKy/7NQQLPhw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/pattern@30.0.0': - resolution: {integrity: sha512-k+TpEThzLVXMkbdxf8KHjZ83Wl+G54ytVJoDIGWwS96Ql4xyASRjc6SU1hs5jHVql+hpyK9G8N7WuFhLpGHRpQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/reporters@30.0.0': - resolution: {integrity: sha512-5WHNlLO0Ok+/o6ML5IzgVm1qyERtLHBNhwn67PAq92H4hZ+n5uW/BYj1VVwmTdxIcNrZLxdV9qtpdZkXf16HxA==} - 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 - - '@jest/schemas@29.6.3': - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/schemas@30.0.0': - resolution: {integrity: sha512-NID2VRyaEkevCRz6badhfqYwri/RvMbiHY81rk3AkK/LaiB0LSxi1RdVZ7MpZdTjNugtZeGfpL0mLs9Kp3MrQw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/snapshot-utils@30.0.0': - resolution: {integrity: sha512-C/QSFUmvZEYptg2Vin84FggAphwHvj6la39vkw1CNOZQORWZ7O/H0BXmdeeeGnvlXDYY8TlFM5jgFnxLAxpFjA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/source-map@30.0.0': - resolution: {integrity: sha512-oYBJ4d/NF4ZY3/7iq1VaeoERHRvlwKtrGClgescaXMIa1mmb+vfJd0xMgbW9yrI80IUA7qGbxpBWxlITrHkWoA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/test-result@30.0.0': - resolution: {integrity: sha512-685zco9HdgBaaWiB9T4xjLtBuN0Q795wgaQPpmuAeZPHwHZSoKFAUnozUtU+ongfi4l5VCz8AclOE5LAQdyjxQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/test-sequencer@30.0.0': - resolution: {integrity: sha512-Hmvv5Yg6UmghXIcVZIydkT0nAK7M/hlXx9WMHR5cLVwdmc14/qUQt3mC72T6GN0olPC6DhmKE6Cd/pHsgDbuqQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/transform@30.0.0': - resolution: {integrity: sha512-8xhpsCGYJsUjqpJOgLyMkeOSSlhqggFZEWAnZquBsvATtueoEs7CkMRxOUmJliF3E5x+mXmZ7gEEsHank029Og==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - '@jest/types@29.6.3': - resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/types@30.0.0': - resolution: {integrity: sha512-1Nox8mAL52PKPfEnUQWBvKU/bp8FTT6AiDu76bFDEJj/qsRFSAVSldfCH3XYMqialti2zHXKvD5gN0AaHc0yKA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} @@ -349,199 +229,190 @@ packages: '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@jridgewell/trace-mapping@0.3.9': - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - - '@napi-rs/wasm-runtime@0.2.11': - resolution: {integrity: sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==} - '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@pkgr/core@0.2.7': - resolution: {integrity: sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} - - '@sinclair/typebox@0.27.8': - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - - '@sinclair/typebox@0.34.35': - resolution: {integrity: sha512-C6ypdODf2VZkgRT6sFM8E1F8vR+HcffniX0Kp8MsU8PIfrlXbNCBz0jzj17GjdmjTx1OtZzdH8+iALL21UjF5A==} - - '@sinonjs/commons@3.0.1': - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - - '@sinonjs/fake-timers@13.0.5': - resolution: {integrity: sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==} - - '@tsconfig/node10@1.0.11': - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} - - '@tsconfig/node12@1.0.11': - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - - '@tsconfig/node14@1.0.3': - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - - '@tsconfig/node16@1.0.4': - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - - '@tybys/wasm-util@0.9.0': - resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} - - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - - '@types/babel__generator@7.27.0': - resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} - - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - - '@types/babel__traverse@7.20.7': - resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} - - '@types/istanbul-lib-coverage@2.0.6': - resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - - '@types/istanbul-lib-report@3.0.3': - resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} - - '@types/istanbul-reports@3.0.4': - resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - - '@types/jest@29.5.14': - resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} - - '@types/lodash@4.17.17': - resolution: {integrity: sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==} - - '@types/node@24.0.1': - resolution: {integrity: sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==} - - '@types/stack-utils@2.0.3': - resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} - - '@types/yargs-parser@21.0.3': - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - - '@types/yargs@17.0.33': - resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - - '@ungap/structured-clone@1.3.0': - resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - - '@unrs/resolver-binding-android-arm-eabi@1.9.0': - resolution: {integrity: sha512-h1T2c2Di49ekF2TE8ZCoJkb+jwETKUIPDJ/nO3tJBKlLFPu+fyd93f0rGP/BvArKx2k2HlRM4kqkNarj3dvZlg==} + '@rollup/rollup-android-arm-eabi@4.60.3': + resolution: {integrity: sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==} cpu: [arm] os: [android] - '@unrs/resolver-binding-android-arm64@1.9.0': - resolution: {integrity: sha512-sG1NHtgXtX8owEkJ11yn34vt0Xqzi3k9TJ8zppDmyG8GZV4kVWw44FHwKwHeEFl07uKPeC4ZoyuQaGh5ruJYPA==} + '@rollup/rollup-android-arm64@4.60.3': + resolution: {integrity: sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw==} cpu: [arm64] os: [android] - '@unrs/resolver-binding-darwin-arm64@1.9.0': - resolution: {integrity: sha512-nJ9z47kfFnCxN1z/oYZS7HSNsFh43y2asePzTEZpEvK7kGyuShSl3RRXnm/1QaqFL+iP+BjMwuB+DYUymOkA5A==} + '@rollup/rollup-darwin-arm64@4.60.3': + resolution: {integrity: sha512-vo6Y5Qfpx7/5EaamIwi0WqW2+zfiusVihKatLvtN1VFVy3D13uERk/6gZLU1UiHRL6fDXqj/ELIeVRGnvcTE1g==} cpu: [arm64] os: [darwin] - '@unrs/resolver-binding-darwin-x64@1.9.0': - resolution: {integrity: sha512-TK+UA1TTa0qS53rjWn7cVlEKVGz2B6JYe0C++TdQjvWYIyx83ruwh0wd4LRxYBM5HeuAzXcylA9BH2trARXJTw==} + '@rollup/rollup-darwin-x64@4.60.3': + resolution: {integrity: sha512-D+0QGcZhBzTN82weOnsSlY7V7+RMmPuF1CkbxyMAGE8+ZHeUjyb76ZiWmBlCu//AQQONvxcqRbwZTajZKqjuOw==} cpu: [x64] os: [darwin] - '@unrs/resolver-binding-freebsd-x64@1.9.0': - resolution: {integrity: sha512-6uZwzMRFcD7CcCd0vz3Hp+9qIL2jseE/bx3ZjaLwn8t714nYGwiE84WpaMCYjU+IQET8Vu/+BNAGtYD7BG/0yA==} + '@rollup/rollup-freebsd-arm64@4.60.3': + resolution: {integrity: sha512-6HnvHCT7fDyj6R0Ph7A6x8dQS/S38MClRWeDLqc0MdfWkxjiu1HSDYrdPhqSILzjTIC/pnXbbJbo+ft+gy/9hQ==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.60.3': + resolution: {integrity: sha512-KHLgC3WKlUYW3ShFKnnosZDOJ0xjg9zp7au3sIm2bs/tGBeC2ipmvRh/N7JKi0t9Ue20C0dpEshi8WUubg+cnA==} cpu: [x64] os: [freebsd] - '@unrs/resolver-binding-linux-arm-gnueabihf@1.9.0': - resolution: {integrity: sha512-bPUBksQfrgcfv2+mm+AZinaKq8LCFvt5PThYqRotqSuuZK1TVKkhbVMS/jvSRfYl7jr3AoZLYbDkItxgqMKRkg==} + '@rollup/rollup-linux-arm-gnueabihf@4.60.3': + resolution: {integrity: sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==} cpu: [arm] os: [linux] - '@unrs/resolver-binding-linux-arm-musleabihf@1.9.0': - resolution: {integrity: sha512-uT6E7UBIrTdCsFQ+y0tQd3g5oudmrS/hds5pbU3h4s2t/1vsGWbbSKhBSCD9mcqaqkBwoqlECpUrRJCmldl8PA==} + '@rollup/rollup-linux-arm-musleabihf@4.60.3': + resolution: {integrity: sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==} cpu: [arm] os: [linux] - '@unrs/resolver-binding-linux-arm64-gnu@1.9.0': - resolution: {integrity: sha512-vdqBh911wc5awE2bX2zx3eflbyv8U9xbE/jVKAm425eRoOVv/VseGZsqi3A3SykckSpF4wSROkbQPvbQFn8EsA==} + '@rollup/rollup-linux-arm64-gnu@4.60.3': + resolution: {integrity: sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==} cpu: [arm64] os: [linux] - '@unrs/resolver-binding-linux-arm64-musl@1.9.0': - resolution: {integrity: sha512-/8JFZ/SnuDr1lLEVsxsuVwrsGquTvT51RZGvyDB/dOK3oYK2UqeXzgeyq6Otp8FZXQcEYqJwxb9v+gtdXn03eQ==} + '@rollup/rollup-linux-arm64-musl@4.60.3': + resolution: {integrity: sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==} cpu: [arm64] os: [linux] - '@unrs/resolver-binding-linux-ppc64-gnu@1.9.0': - resolution: {integrity: sha512-FkJjybtrl+rajTw4loI3L6YqSOpeZfDls4SstL/5lsP2bka9TiHUjgMBjygeZEis1oC8LfJTS8FSgpKPaQx2tQ==} + '@rollup/rollup-linux-loong64-gnu@4.60.3': + resolution: {integrity: sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.60.3': + resolution: {integrity: sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.60.3': + resolution: {integrity: sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.60.3': + resolution: {integrity: sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==} cpu: [ppc64] os: [linux] - '@unrs/resolver-binding-linux-riscv64-gnu@1.9.0': - resolution: {integrity: sha512-w/NZfHNeDusbqSZ8r/hp8iL4S39h4+vQMc9/vvzuIKMWKppyUGKm3IST0Qv0aOZ1rzIbl9SrDeIqK86ZpUK37w==} + '@rollup/rollup-linux-riscv64-gnu@4.60.3': + resolution: {integrity: sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==} cpu: [riscv64] os: [linux] - '@unrs/resolver-binding-linux-riscv64-musl@1.9.0': - resolution: {integrity: sha512-bEPBosut8/8KQbUixPry8zg/fOzVOWyvwzOfz0C0Rw6dp+wIBseyiHKjkcSyZKv/98edrbMknBaMNJfA/UEdqw==} + '@rollup/rollup-linux-riscv64-musl@4.60.3': + resolution: {integrity: sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==} cpu: [riscv64] os: [linux] - '@unrs/resolver-binding-linux-s390x-gnu@1.9.0': - resolution: {integrity: sha512-LDtMT7moE3gK753gG4pc31AAqGUC86j3AplaFusc717EUGF9ZFJ356sdQzzZzkBk1XzMdxFyZ4f/i35NKM/lFA==} + '@rollup/rollup-linux-s390x-gnu@4.60.3': + resolution: {integrity: sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==} cpu: [s390x] os: [linux] - '@unrs/resolver-binding-linux-x64-gnu@1.9.0': - resolution: {integrity: sha512-WmFd5KINHIXj8o1mPaT8QRjA9HgSXhN1gl9Da4IZihARihEnOylu4co7i/yeaIpcfsI6sYs33cNZKyHYDh0lrA==} + '@rollup/rollup-linux-x64-gnu@4.60.3': + resolution: {integrity: sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==} cpu: [x64] os: [linux] - '@unrs/resolver-binding-linux-x64-musl@1.9.0': - resolution: {integrity: sha512-CYuXbANW+WgzVRIl8/QvZmDaZxrqvOldOwlbUjIM4pQ46FJ0W5cinJ/Ghwa/Ng1ZPMJMk1VFdsD/XwmCGIXBWg==} + '@rollup/rollup-linux-x64-musl@4.60.3': + resolution: {integrity: sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==} cpu: [x64] os: [linux] - '@unrs/resolver-binding-wasm32-wasi@1.9.0': - resolution: {integrity: sha512-6Rp2WH0OoitMYR57Z6VE8Y6corX8C6QEMWLgOV6qXiJIeZ1F9WGXY/yQ8yDC4iTraotyLOeJ2Asea0urWj2fKQ==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] + '@rollup/rollup-openbsd-x64@4.60.3': + resolution: {integrity: sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.60.3': + resolution: {integrity: sha512-AaXwSvUi3QIPtroAUw1t5yHGIyqKEXwH54WUocFolZhpGDruJcs8c+xPNDRn4XiQsS7MEwnYsHW2l0MBLDMkWg==} + cpu: [arm64] + os: [openharmony] - '@unrs/resolver-binding-win32-arm64-msvc@1.9.0': - resolution: {integrity: sha512-rknkrTRuvujprrbPmGeHi8wYWxmNVlBoNW8+4XF2hXUnASOjmuC9FNF1tGbDiRQWn264q9U/oGtixyO3BT8adQ==} + '@rollup/rollup-win32-arm64-msvc@4.60.3': + resolution: {integrity: sha512-65LAKM/bAWDqKNEelHlcHvm2V+Vfb8C6INFxQXRHCvaVN1rJfwr4NvdP4FyzUaLqWfaCGaadf6UbTm8xJeYfEg==} cpu: [arm64] os: [win32] - '@unrs/resolver-binding-win32-ia32-msvc@1.9.0': - resolution: {integrity: sha512-Ceymm+iBl+bgAICtgiHyMLz6hjxmLJKqBim8tDzpX61wpZOx2bPK6Gjuor7I2RiUynVjvvkoRIkrPyMwzBzF3A==} + '@rollup/rollup-win32-ia32-msvc@4.60.3': + resolution: {integrity: sha512-EEM2gyhBF5MFnI6vMKdX1LAosE627RGBzIoGMdLloPZkXrUN0Ckqgr2Qi8+J3zip/8NVVro3/FjB+tjhZUgUHA==} cpu: [ia32] os: [win32] - '@unrs/resolver-binding-win32-x64-msvc@1.9.0': - resolution: {integrity: sha512-k59o9ZyeyS0hAlcaKFezYSH2agQeRFEB7KoQLXl3Nb3rgkqT1NY9Vwy+SqODiLmYnEjxWJVRE/yq2jFVqdIxZw==} + '@rollup/rollup-win32-x64-gnu@4.60.3': + resolution: {integrity: sha512-E5Eb5H/DpxaoXH++Qkv28RcUJboMopmdDUALBczvHMf7hNIxaDZqwY5lK12UK1BHacSmvupoEWGu+n993Z0y1A==} cpu: [x64] os: [win32] - acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} - engines: {node: '>=0.4.0'} + '@rollup/rollup-win32-x64-msvc@4.60.3': + resolution: {integrity: sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA==} + cpu: [x64] + os: [win32] - acorn@8.15.0: - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} - engines: {node: '>=0.4.0'} - hasBin: true + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} + '@types/estree@1.0.9': + resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} + + '@types/lodash@4.17.17': + resolution: {integrity: sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==} + + '@types/node@24.0.1': + resolution: {integrity: sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==} + + '@vitest/coverage-v8@2.1.9': + resolution: {integrity: sha512-Z2cOr0ksM00MpEfyVE8KXIYPEcBFxdbLSs56L8PO0QQMxt/6bDj45uQfxoc96v05KW3clk7vvgP0qfDit9DmfQ==} + peerDependencies: + '@vitest/browser': 2.1.9 + vitest: 2.1.9 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@2.1.9': + resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==} + + '@vitest/mocker@2.1.9': + resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@2.1.9': + resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==} + + '@vitest/runner@2.1.9': + resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==} + + '@vitest/snapshot@2.1.9': + resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==} + + '@vitest/spy@2.1.9': + resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==} + + '@vitest/utils@2.1.9': + resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==} ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -555,124 +426,39 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - - argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - - async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - - babel-jest@30.0.0: - resolution: {integrity: sha512-JQ0DhdFjODbSawDf0026uZuwaqfKkQzk+9mwWkq2XkKFIaMhFVOxlVmbFCOnnC76jATdxrff3IiUAvOAJec6tw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - peerDependencies: - '@babel/core': ^7.11.0 - - babel-plugin-istanbul@7.0.0: - resolution: {integrity: sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - babel-plugin-jest-hoist@30.0.0: - resolution: {integrity: sha512-DSRm+US/FCB4xPDD6Rnslb6PAF9Bej1DZ+1u4aTiqJnk7ZX12eHsnDiIOqjGvITCq+u6wLqUhgS+faCNbVY8+g==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - babel-preset-current-node-syntax@1.1.0: - resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} - peerDependencies: - '@babel/core': ^7.0.0 - - babel-preset-jest@30.0.0: - resolution: {integrity: sha512-hgEuu/W7gk8QOWUA9+m3Zk+WpGvKc1Egp6rFQEfYxEoM9Fk/q8nuTXNL65OkhwGrTApauEGgakOoWVXj+UfhKw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - peerDependencies: - '@babel/core': ^7.11.0 - balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - brace-expansion@1.1.12: - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - - browserslist@4.25.0: - resolution: {integrity: sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - - bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - - camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - - caniuse-lite@1.0.30001723: - resolution: {integrity: sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} + brace-expansion@5.0.6: + resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} + engines: {node: 18 || 20 || >=22} - ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - ci-info@4.2.0: - resolution: {integrity: sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==} - engines: {node: '>=8'} - - cjs-module-lexer@2.1.0: - resolution: {integrity: sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==} - - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} - co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - - collect-v8-coverage@1.0.2: - resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} @@ -685,15 +471,6 @@ packages: resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} engines: {node: '>=20'} - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -707,130 +484,46 @@ packages: supports-color: optional: true - dedent@1.6.0: - resolution: {integrity: sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - - detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - - diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - ejs@3.1.10: - resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} - engines: {node: '>=0.10.0'} - hasBin: true - - electron-to-chromium@1.5.167: - resolution: {integrity: sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==} - - emittery@0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-string-regexp@2.0.0: - resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} - engines: {node: '>=8'} - - esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} hasBin: true - execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - - exit-x@0.2.2: - resolution: {integrity: sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==} - engines: {node: '>= 0.8.0'} - - expect@29.7.0: - resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - expect@30.0.0: - resolution: {integrity: sha512-xCdPp6gwiR9q9lsPCHANarIkFTN/IMZso6Kkq03sOm9IIGtzK/UJqml0dkhHibGh8HKOj8BIDIpZ0BZuU7QK6w==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fb-watchman@2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} - - filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@11.0.3: @@ -838,17 +531,6 @@ packages: engines: {node: 20 || >=22} hasBin: true - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -856,45 +538,10 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - - import-local@3.2.0: - resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} - engines: {node: '>=8'} - hasBin: true - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - inflight@1.0.6: - resolution: {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. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-generator-fn@2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -902,10 +549,6 @@ packages: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} - istanbul-lib-instrument@6.0.3: - resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} - engines: {node: '>=10'} - istanbul-lib-report@3.0.1: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} @@ -925,196 +568,12 @@ packages: resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} engines: {node: 20 || >=22} - jake@10.9.2: - resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} - engines: {node: '>=10'} - hasBin: true - - jest-changed-files@30.0.0: - resolution: {integrity: sha512-rzGpvCdPdEV1Ma83c1GbZif0L2KAm3vXSXGRlpx7yCt0vhruwCNouKNRh3SiVcISHP1mb3iJzjb7tAEnNu1laQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-circus@30.0.0: - resolution: {integrity: sha512-nTwah78qcKVyndBS650hAkaEmwWGaVsMMoWdJwMnH77XArRJow2Ir7hc+8p/mATtxVZuM9OTkA/3hQocRIK5Dw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-cli@30.0.0: - resolution: {integrity: sha512-fWKAgrhlwVVCfeizsmIrPRTBYTzO82WSba3gJniZNR3PKXADgdC0mmCSK+M+t7N8RCXOVfY6kvCkvjUNtzmHYQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - jest-config@30.0.0: - resolution: {integrity: sha512-p13a/zun+sbOMrBnTEUdq/5N7bZMOGd1yMfqtAJniPNuzURMay4I+vxZLK1XSDbjvIhmeVdG8h8RznqYyjctyg==} - 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' - peerDependenciesMeta: - '@types/node': - optional: true - esbuild-register: - optional: true - ts-node: - optional: true - - jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-diff@30.0.0: - resolution: {integrity: sha512-TgT1+KipV8JTLXXeFX0qSvIJR/UXiNNojjxb/awh3vYlBZyChU/NEmyKmq+wijKjWEztyrGJFL790nqMqNjTHA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-docblock@30.0.0: - resolution: {integrity: sha512-By/iQ0nvTzghEecGzUMCp1axLtBh+8wB4Hpoi5o+x1stycjEmPcH1mHugL4D9Q+YKV++vKeX/3ZTW90QC8ICPg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-each@30.0.0: - resolution: {integrity: sha512-qkFEW3cfytEjG2KtrhwtldZfXYnWSanO8xUMXLe4A6yaiHMHJUalk0Yyv4MQH6aeaxgi4sGVrukvF0lPMM7U1w==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-environment-node@30.0.0: - resolution: {integrity: sha512-sF6lxyA25dIURyDk4voYmGU9Uwz2rQKMfjxKnDd19yk+qxKGrimFqS5YsPHWTlAVBo+YhWzXsqZoaMzrTFvqfg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-haste-map@30.0.0: - resolution: {integrity: sha512-p4bXAhXTawTsADgQgTpbymdLaTyPW1xWNu1oIGG7/N3LIAbZVkH2JMJqS8/IUcnGR8Kc7WFE+vWbJvsqGCWZXw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-leak-detector@30.0.0: - resolution: {integrity: sha512-E/ly1azdVVbZrS0T6FIpyYHvsdek4FNaThJTtggjV/8IpKxh3p9NLndeUZy2+sjAI3ncS+aM0uLLon/dBg8htA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-matcher-utils@29.7.0: - resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-matcher-utils@30.0.0: - resolution: {integrity: sha512-m5mrunqopkrqwG1mMdJxe1J4uGmS9AHHKYUmoxeQOxBcLjEvirIrIDwuKmUYrecPHVB/PUBpXs2gPoeA2FSSLQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-message-util@29.7.0: - resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-message-util@30.0.0: - resolution: {integrity: sha512-pV3qcrb4utEsa/U7UI2VayNzSDQcmCllBZLSoIucrESRu0geKThFZOjjh0kACDJFJRAQwsK7GVsmS6SpEceD8w==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-mock@30.0.0: - resolution: {integrity: sha512-W2sRA4ALXILrEetEOh2ooZG6fZ01iwVs0OWMKSSWRcUlaLr4ESHuiKXDNTg+ZVgOq8Ei5445i/Yxrv59VT+XkA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-pnp-resolver@1.2.3: - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - - jest-regex-util@30.0.0: - resolution: {integrity: sha512-rT84010qRu/5OOU7a9TeidC2Tp3Qgt9Sty4pOZ/VSDuEmRupIjKZAb53gU3jr4ooMlhwScrgC9UixJxWzVu9oQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-resolve-dependencies@30.0.0: - resolution: {integrity: sha512-Yhh7odCAUNXhluK1bCpwIlHrN1wycYaTlZwq1GdfNBEESNNI/z1j1a7dUEWHbmB9LGgv0sanxw3JPmWU8NeebQ==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-resolve@30.0.0: - resolution: {integrity: sha512-zwWl1P15CcAfuQCEuxszjiKdsValhnWcj/aXg/R3aMHs8HVoCWHC4B/+5+1BirMoOud8NnN85GSP2LEZCbj3OA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-runner@30.0.0: - resolution: {integrity: sha512-xbhmvWIc8X1IQ8G7xTv0AQJXKjBVyxoVJEJgy7A4RXsSaO+k/1ZSBbHwjnUhvYqMvwQPomWssDkUx6EoidEhlw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-runtime@30.0.0: - resolution: {integrity: sha512-/O07qVgFrFAOGKGigojmdR3jUGz/y3+a/v9S/Yi2MHxsD+v6WcPppglZJw0gNJkRBArRDK8CFAwpM/VuEiiRjA==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-snapshot@30.0.0: - resolution: {integrity: sha512-6oCnzjpvfj/UIOMTqKZ6gedWAUgaycMdV8Y8h2dRJPvc2wSjckN03pzeoonw8y33uVngfx7WMo1ygdRGEKOT7w==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-util@30.0.0: - resolution: {integrity: sha512-fhNBBM9uSUbd4Lzsf8l/kcAdaHD/4SgoI48en3HXcBEMwKwoleKFMZ6cYEYs21SB779PRuRCyNLmymApAm8tZw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-validate@30.0.0: - resolution: {integrity: sha512-d6OkzsdlWItHAikUDs1hlLmpOIRhsZoXTCliV2XXalVQ3ZOeb9dy0CQ6AKulJu/XOZqpOEr/FiMH+FeOBVV+nw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-watcher@30.0.0: - resolution: {integrity: sha512-fbAkojcyS53bOL/B7XYhahORq9cIaPwOgd/p9qW/hybbC8l6CzxfWJJxjlPBAIVN8dRipLR0zdhpGQdam+YBtw==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest-worker@30.0.0: - resolution: {integrity: sha512-VZvxfWIybIvwK8N/Bsfe43LfQgd/rD0c4h5nLUx78CAqPxIQcW2qDjsVAC53iUR8yxzFIeCFFvWOh8en8hGzdg==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - jest@30.0.0: - resolution: {integrity: sha512-/3G2iFwsUY95vkflmlDn/IdLyLWqpQXcftptooaPH4qkyU52V7qVYf1BjmdSPlp1+0fs6BmNtrGaSFwOfV07ew==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -1122,40 +581,23 @@ packages: resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} engines: {node: 20 || >=22} - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - - makeerror@1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - minimatch@10.0.3: resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} engines: {node: 20 || >=22} - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} + minimatch@10.2.5: + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} @@ -1168,66 +610,14 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - napi-postinstall@0.2.4: - resolution: {integrity: sha512-ZEzHJwBhZ8qQSbknHqYcdtQVr8zUgGyM/q6h6qAyhtyVMNrSgDhrC4disf03dYW0e+czXyLnZINnCTEkWy0eJg==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + nanoid@3.3.12: + resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - node-int64@0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - - node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - - p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -1240,58 +630,28 @@ packages: resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} engines: {node: 20 || >=22} - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - picomatch@4.0.2: - resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} - engines: {node: '>=12'} - - pirates@4.0.7: - resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} - engines: {node: '>= 6'} - - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - - pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - pretty-format@30.0.0: - resolution: {integrity: sha512-18NAOUr4ZOQiIR+BgI5NhQE7uREdx4ZyV0dyay5izh4yfQ+1T7BSvggxvRGoXocrRyevqW5OhScUjbi9GB8R8Q==} - engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} - - pure-rand@7.0.1: - resolution: {integrity: sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==} - - react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} + postcss@8.5.14: + resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} + engines: {node: ^10 || ^12 || >=14} rimraf@6.0.1: resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} engines: {node: 20 || >=22} hasBin: true - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + rollup@4.60.3: + resolution: {integrity: sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true semver@7.7.2: @@ -1307,34 +667,22 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - - source-map-support@0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - - stack-utils@2.0.6: - resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} - engines: {node: '>=10'} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - string-length@4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} @@ -1352,129 +700,111 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} - strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} + test-exclude@7.0.2: + resolution: {integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==} + engines: {node: '>=18'} - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} - synckit@0.11.8: - resolution: {integrity: sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==} - engines: {node: ^14.18.0 || >=16.0.0} + tinyrainbow@1.2.0: + resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + engines: {node: '>=14.0.0'} - test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + typescript@5.8.3: + resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + engines: {node: '>=14.17'} + hasBin: true - tmpl@1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + undici-types@7.8.0: + resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + vite-node@2.1.9: + resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true - ts-jest@29.4.0: - resolution: {integrity: sha512-d423TJMnJGu80/eSgfQ5w/R+0zFJvdtTxwtF9KzFFunOpSeD+79lHJQIiAhluJoyGRbvj9NZJsl9WjCUo0ND7Q==} - engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} + vite@5.4.21: + resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true 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 - esbuild: '*' - jest: ^29.0.0 || ^30.0.0 - jest-util: ^29.0.0 || ^30.0.0 - typescript: '>=4.3 <6' + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 peerDependenciesMeta: - '@babel/core': + '@types/node': optional: true - '@jest/transform': + less: optional: true - '@jest/types': + lightningcss: optional: true - babel-jest: + sass: optional: true - esbuild: + sass-embedded: optional: true - jest-util: + stylus: + optional: true + sugarss: + optional: true + terser: optional: true - ts-node@10.9.2: - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + vitest@2.1.9: + resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.1.9 + '@vitest/ui': 2.1.9 + happy-dom: '*' + jsdom: '*' peerDependenciesMeta: - '@swc/core': + '@edge-runtime/vm': optional: true - '@swc/wasm': + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: optional: true - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - - type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - - type-fest@4.41.0: - resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} - engines: {node: '>=16'} - - typescript@5.8.3: - resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} - engines: {node: '>=14.17'} - hasBin: true - - undici-types@7.8.0: - resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} - - unrs-resolver@1.9.0: - resolution: {integrity: sha512-wqaRu4UnzBD2ABTC1kLfBjAqIDZ5YUTr/MLGa7By47JV1bJDSW7jq/ZSLigB7enLe7ubNaJhtnBXgrc/50cEhg==} - - update-browserslist-db@1.1.3: - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - - v8-to-istanbul@9.3.0: - resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} - engines: {node: '>=10.12.0'} - - walker@1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -1483,36 +813,6 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - write-file-atomic@5.0.1: - resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - - yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - snapshots: '@ampproject/remapping@2.3.0': @@ -1520,211 +820,88 @@ snapshots: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@babel/code-frame@7.27.1': - dependencies: - '@babel/helper-validator-identifier': 7.27.1 - js-tokens: 4.0.0 - picocolors: 1.1.1 + '@babel/helper-string-parser@7.27.1': {} - '@babel/compat-data@7.27.5': {} + '@babel/helper-validator-identifier@7.27.1': {} - '@babel/core@7.27.4': + '@babel/parser@7.27.5': dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.27.5 - '@babel/helper-compilation-targets': 7.27.2 - '@babel/helper-module-transforms': 7.27.3(@babel/core@7.27.4) - '@babel/helpers': 7.27.6 - '@babel/parser': 7.27.5 - '@babel/template': 7.27.2 - '@babel/traverse': 7.27.4 '@babel/types': 7.27.6 - convert-source-map: 2.0.0 - debug: 4.4.1 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - '@babel/generator@7.27.5': + '@babel/types@7.27.6': dependencies: - '@babel/parser': 7.27.5 - '@babel/types': 7.27.6 - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 3.1.0 - - '@babel/helper-compilation-targets@7.27.2': - dependencies: - '@babel/compat-data': 7.27.5 - '@babel/helper-validator-option': 7.27.1 - browserslist: 4.25.0 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-module-imports@7.27.1': - dependencies: - '@babel/traverse': 7.27.4 - '@babel/types': 7.27.6 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.27.3(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-module-imports': 7.27.1 + '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 - '@babel/traverse': 7.27.4 - transitivePeerDependencies: - - supports-color - - '@babel/helper-plugin-utils@7.27.1': {} - - '@babel/helper-string-parser@7.27.1': {} - - '@babel/helper-validator-identifier@7.27.1': {} - - '@babel/helper-validator-option@7.27.1': {} - - '@babel/helpers@7.27.6': - dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.27.6 - '@babel/parser@7.27.5': - dependencies: - '@babel/types': 7.27.6 - - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 - - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@bcoe/v8-coverage@0.2.3': {} - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/aix-ppc64@0.21.5': + optional: true - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/android-arm64@0.21.5': + optional: true - '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/android-arm@0.21.5': + optional: true - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/android-x64@0.21.5': + optional: true - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/darwin-arm64@0.21.5': + optional: true - '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/darwin-x64@0.21.5': + optional: true - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/freebsd-arm64@0.21.5': + optional: true - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/freebsd-x64@0.21.5': + optional: true - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/linux-arm64@0.21.5': + optional: true - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/linux-arm@0.21.5': + optional: true - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/linux-ia32@0.21.5': + optional: true - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/linux-loong64@0.21.5': + optional: true - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/linux-mips64el@0.21.5': + optional: true - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/linux-ppc64@0.21.5': + optional: true - '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.27.4)': - dependencies: - '@babel/core': 7.27.4 - '@babel/helper-plugin-utils': 7.27.1 + '@esbuild/linux-riscv64@0.21.5': + optional: true - '@babel/template@7.27.2': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/parser': 7.27.5 - '@babel/types': 7.27.6 + '@esbuild/linux-s390x@0.21.5': + optional: true - '@babel/traverse@7.27.4': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/generator': 7.27.5 - '@babel/parser': 7.27.5 - '@babel/template': 7.27.2 - '@babel/types': 7.27.6 - debug: 4.4.1 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color + '@esbuild/linux-x64@0.21.5': + optional: true - '@babel/types@7.27.6': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 + '@esbuild/netbsd-x64@0.21.5': + optional: true - '@bcoe/v8-coverage@0.2.3': {} + '@esbuild/openbsd-x64@0.21.5': + optional: true - '@cspotcode/source-map-support@0.8.1': - dependencies: - '@jridgewell/trace-mapping': 0.3.9 + '@esbuild/sunos-x64@0.21.5': + optional: true - '@emnapi/core@1.4.3': - dependencies: - '@emnapi/wasi-threads': 1.0.2 - tslib: 2.8.1 + '@esbuild/win32-arm64@0.21.5': optional: true - '@emnapi/runtime@1.4.3': - dependencies: - tslib: 2.8.1 + '@esbuild/win32-ia32@0.21.5': optional: true - '@emnapi/wasi-threads@1.0.2': - dependencies: - tslib: 2.8.1 + '@esbuild/win32-x64@0.21.5': optional: true '@isaacs/balanced-match@4.0.1': {} @@ -1742,212 +919,8 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 - '@istanbuljs/load-nyc-config@1.1.0': - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - '@istanbuljs/schema@0.1.3': {} - '@jest/console@30.0.0': - dependencies: - '@jest/types': 30.0.0 - '@types/node': 24.0.1 - chalk: 4.1.2 - jest-message-util: 30.0.0 - jest-util: 30.0.0 - slash: 3.0.0 - - '@jest/core@30.0.0(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3))': - dependencies: - '@jest/console': 30.0.0 - '@jest/pattern': 30.0.0 - '@jest/reporters': 30.0.0 - '@jest/test-result': 30.0.0 - '@jest/transform': 30.0.0 - '@jest/types': 30.0.0 - '@types/node': 24.0.1 - 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.0 - jest-config: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) - jest-haste-map: 30.0.0 - jest-message-util: 30.0.0 - jest-regex-util: 30.0.0 - jest-resolve: 30.0.0 - jest-resolve-dependencies: 30.0.0 - jest-runner: 30.0.0 - jest-runtime: 30.0.0 - jest-snapshot: 30.0.0 - jest-util: 30.0.0 - jest-validate: 30.0.0 - jest-watcher: 30.0.0 - micromatch: 4.0.8 - pretty-format: 30.0.0 - slash: 3.0.0 - transitivePeerDependencies: - - babel-plugin-macros - - esbuild-register - - supports-color - - ts-node - - '@jest/diff-sequences@30.0.0': {} - - '@jest/environment@30.0.0': - dependencies: - '@jest/fake-timers': 30.0.0 - '@jest/types': 30.0.0 - '@types/node': 24.0.1 - jest-mock: 30.0.0 - - '@jest/expect-utils@29.7.0': - dependencies: - jest-get-type: 29.6.3 - - '@jest/expect-utils@30.0.0': - dependencies: - '@jest/get-type': 30.0.0 - - '@jest/expect@30.0.0': - dependencies: - expect: 30.0.0 - jest-snapshot: 30.0.0 - transitivePeerDependencies: - - supports-color - - '@jest/fake-timers@30.0.0': - dependencies: - '@jest/types': 30.0.0 - '@sinonjs/fake-timers': 13.0.5 - '@types/node': 24.0.1 - jest-message-util: 30.0.0 - jest-mock: 30.0.0 - jest-util: 30.0.0 - - '@jest/get-type@30.0.0': {} - - '@jest/globals@30.0.0': - dependencies: - '@jest/environment': 30.0.0 - '@jest/expect': 30.0.0 - '@jest/types': 30.0.0 - jest-mock: 30.0.0 - transitivePeerDependencies: - - supports-color - - '@jest/pattern@30.0.0': - dependencies: - '@types/node': 24.0.1 - jest-regex-util: 30.0.0 - - '@jest/reporters@30.0.0': - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 30.0.0 - '@jest/test-result': 30.0.0 - '@jest/transform': 30.0.0 - '@jest/types': 30.0.0 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 24.0.1 - chalk: 4.1.2 - collect-v8-coverage: 1.0.2 - exit-x: 0.2.2 - glob: 10.4.5 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.3 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 5.0.6 - istanbul-reports: 3.1.7 - jest-message-util: 30.0.0 - jest-util: 30.0.0 - jest-worker: 30.0.0 - slash: 3.0.0 - string-length: 4.0.2 - v8-to-istanbul: 9.3.0 - transitivePeerDependencies: - - supports-color - - '@jest/schemas@29.6.3': - dependencies: - '@sinclair/typebox': 0.27.8 - - '@jest/schemas@30.0.0': - dependencies: - '@sinclair/typebox': 0.34.35 - - '@jest/snapshot-utils@30.0.0': - dependencies: - '@jest/types': 30.0.0 - chalk: 4.1.2 - graceful-fs: 4.2.11 - natural-compare: 1.4.0 - - '@jest/source-map@30.0.0': - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - callsites: 3.1.0 - graceful-fs: 4.2.11 - - '@jest/test-result@30.0.0': - dependencies: - '@jest/console': 30.0.0 - '@jest/types': 30.0.0 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.2 - - '@jest/test-sequencer@30.0.0': - dependencies: - '@jest/test-result': 30.0.0 - graceful-fs: 4.2.11 - jest-haste-map: 30.0.0 - slash: 3.0.0 - - '@jest/transform@30.0.0': - dependencies: - '@babel/core': 7.27.4 - '@jest/types': 30.0.0 - '@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.0 - jest-regex-util: 30.0.0 - jest-util: 30.0.0 - micromatch: 4.0.8 - pirates: 4.0.7 - slash: 3.0.0 - write-file-atomic: 5.0.1 - transitivePeerDependencies: - - supports-color - - '@jest/types@29.6.3': - dependencies: - '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 24.0.1 - '@types/yargs': 17.0.33 - chalk: 4.1.2 - - '@jest/types@30.0.0': - dependencies: - '@jest/pattern': 30.0.0 - '@jest/schemas': 30.0.0 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 24.0.1 - '@types/yargs': 17.0.33 - chalk: 4.1.2 - '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 @@ -1960,315 +933,194 @@ snapshots: '@jridgewell/sourcemap-codec@1.5.0': {} - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec@1.5.5': {} - '@jridgewell/trace-mapping@0.3.9': + '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@napi-rs/wasm-runtime@0.2.11': - dependencies: - '@emnapi/core': 1.4.3 - '@emnapi/runtime': 1.4.3 - '@tybys/wasm-util': 0.9.0 - optional: true - '@pkgjs/parseargs@0.11.0': optional: true - '@pkgr/core@0.2.7': {} - - '@sinclair/typebox@0.27.8': {} - - '@sinclair/typebox@0.34.35': {} - - '@sinonjs/commons@3.0.1': - dependencies: - type-detect: 4.0.8 - - '@sinonjs/fake-timers@13.0.5': - dependencies: - '@sinonjs/commons': 3.0.1 - - '@tsconfig/node10@1.0.11': {} - - '@tsconfig/node12@1.0.11': {} - - '@tsconfig/node14@1.0.3': {} - - '@tsconfig/node16@1.0.4': {} - - '@tybys/wasm-util@0.9.0': - dependencies: - tslib: 2.8.1 + '@rollup/rollup-android-arm-eabi@4.60.3': optional: true - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.27.5 - '@babel/types': 7.27.6 - '@types/babel__generator': 7.27.0 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.7 - - '@types/babel__generator@7.27.0': - dependencies: - '@babel/types': 7.27.6 - - '@types/babel__template@7.4.4': - dependencies: - '@babel/parser': 7.27.5 - '@babel/types': 7.27.6 - - '@types/babel__traverse@7.20.7': - dependencies: - '@babel/types': 7.27.6 - - '@types/istanbul-lib-coverage@2.0.6': {} - - '@types/istanbul-lib-report@3.0.3': - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 - - '@types/istanbul-reports@3.0.4': - dependencies: - '@types/istanbul-lib-report': 3.0.3 - - '@types/jest@29.5.14': - dependencies: - expect: 29.7.0 - pretty-format: 29.7.0 - - '@types/lodash@4.17.17': {} - - '@types/node@24.0.1': - dependencies: - undici-types: 7.8.0 - - '@types/stack-utils@2.0.3': {} - - '@types/yargs-parser@21.0.3': {} - - '@types/yargs@17.0.33': - dependencies: - '@types/yargs-parser': 21.0.3 - - '@ungap/structured-clone@1.3.0': {} - - '@unrs/resolver-binding-android-arm-eabi@1.9.0': + '@rollup/rollup-android-arm64@4.60.3': optional: true - '@unrs/resolver-binding-android-arm64@1.9.0': + '@rollup/rollup-darwin-arm64@4.60.3': optional: true - '@unrs/resolver-binding-darwin-arm64@1.9.0': + '@rollup/rollup-darwin-x64@4.60.3': optional: true - '@unrs/resolver-binding-darwin-x64@1.9.0': + '@rollup/rollup-freebsd-arm64@4.60.3': optional: true - '@unrs/resolver-binding-freebsd-x64@1.9.0': + '@rollup/rollup-freebsd-x64@4.60.3': optional: true - '@unrs/resolver-binding-linux-arm-gnueabihf@1.9.0': + '@rollup/rollup-linux-arm-gnueabihf@4.60.3': optional: true - '@unrs/resolver-binding-linux-arm-musleabihf@1.9.0': + '@rollup/rollup-linux-arm-musleabihf@4.60.3': optional: true - '@unrs/resolver-binding-linux-arm64-gnu@1.9.0': + '@rollup/rollup-linux-arm64-gnu@4.60.3': optional: true - '@unrs/resolver-binding-linux-arm64-musl@1.9.0': + '@rollup/rollup-linux-arm64-musl@4.60.3': optional: true - '@unrs/resolver-binding-linux-ppc64-gnu@1.9.0': + '@rollup/rollup-linux-loong64-gnu@4.60.3': optional: true - '@unrs/resolver-binding-linux-riscv64-gnu@1.9.0': + '@rollup/rollup-linux-loong64-musl@4.60.3': optional: true - '@unrs/resolver-binding-linux-riscv64-musl@1.9.0': + '@rollup/rollup-linux-ppc64-gnu@4.60.3': optional: true - '@unrs/resolver-binding-linux-s390x-gnu@1.9.0': + '@rollup/rollup-linux-ppc64-musl@4.60.3': optional: true - '@unrs/resolver-binding-linux-x64-gnu@1.9.0': + '@rollup/rollup-linux-riscv64-gnu@4.60.3': optional: true - '@unrs/resolver-binding-linux-x64-musl@1.9.0': + '@rollup/rollup-linux-riscv64-musl@4.60.3': optional: true - '@unrs/resolver-binding-wasm32-wasi@1.9.0': - dependencies: - '@napi-rs/wasm-runtime': 0.2.11 + '@rollup/rollup-linux-s390x-gnu@4.60.3': optional: true - '@unrs/resolver-binding-win32-arm64-msvc@1.9.0': + '@rollup/rollup-linux-x64-gnu@4.60.3': optional: true - '@unrs/resolver-binding-win32-ia32-msvc@1.9.0': + '@rollup/rollup-linux-x64-musl@4.60.3': optional: true - '@unrs/resolver-binding-win32-x64-msvc@1.9.0': + '@rollup/rollup-openbsd-x64@4.60.3': optional: true - acorn-walk@8.3.4: - dependencies: - acorn: 8.15.0 - - acorn@8.15.0: {} - - ansi-escapes@4.3.2: - dependencies: - type-fest: 0.21.3 + '@rollup/rollup-openharmony-arm64@4.60.3': + optional: true - ansi-regex@5.0.1: {} + '@rollup/rollup-win32-arm64-msvc@4.60.3': + optional: true - ansi-regex@6.1.0: {} + '@rollup/rollup-win32-ia32-msvc@4.60.3': + optional: true - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 + '@rollup/rollup-win32-x64-gnu@4.60.3': + optional: true - ansi-styles@5.2.0: {} + '@rollup/rollup-win32-x64-msvc@4.60.3': + optional: true - ansi-styles@6.2.1: {} + '@types/estree@1.0.8': {} - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 + '@types/estree@1.0.9': {} - arg@4.1.3: {} + '@types/lodash@4.17.17': {} - argparse@1.0.10: + '@types/node@24.0.1': dependencies: - sprintf-js: 1.0.3 - - async@3.2.6: {} + undici-types: 7.8.0 - babel-jest@30.0.0(@babel/core@7.27.4): + '@vitest/coverage-v8@2.1.9(vitest@2.1.9(@types/node@24.0.1))': dependencies: - '@babel/core': 7.27.4 - '@jest/transform': 30.0.0 - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 7.0.0 - babel-preset-jest: 30.0.0(@babel/core@7.27.4) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 0.2.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.21 + magicast: 0.3.5 + std-env: 3.10.0 + test-exclude: 7.0.2 + tinyrainbow: 1.2.0 + vitest: 2.1.9(@types/node@24.0.1) transitivePeerDependencies: - supports-color - babel-plugin-istanbul@7.0.0: + '@vitest/expect@2.1.9': dependencies: - '@babel/helper-plugin-utils': 7.27.1 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 6.0.3 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.3.3 + tinyrainbow: 1.2.0 - babel-plugin-jest-hoist@30.0.0: + '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@24.0.1))': dependencies: - '@babel/template': 7.27.2 - '@babel/types': 7.27.6 - '@types/babel__core': 7.20.5 + '@vitest/spy': 2.1.9 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 5.4.21(@types/node@24.0.1) - babel-preset-current-node-syntax@1.1.0(@babel/core@7.27.4): - dependencies: - '@babel/core': 7.27.4 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.27.4) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.27.4) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.27.4) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.27.4) - '@babel/plugin-syntax-import-attributes': 7.27.1(@babel/core@7.27.4) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.27.4) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.27.4) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.27.4) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.27.4) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.27.4) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.27.4) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.27.4) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.27.4) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.27.4) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.27.4) - - babel-preset-jest@30.0.0(@babel/core@7.27.4): + '@vitest/pretty-format@2.1.9': dependencies: - '@babel/core': 7.27.4 - babel-plugin-jest-hoist: 30.0.0 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.27.4) - - balanced-match@1.0.2: {} + tinyrainbow: 1.2.0 - brace-expansion@1.1.12: + '@vitest/runner@2.1.9': dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 + '@vitest/utils': 2.1.9 + pathe: 1.1.2 - brace-expansion@2.0.2: + '@vitest/snapshot@2.1.9': dependencies: - balanced-match: 1.0.2 + '@vitest/pretty-format': 2.1.9 + magic-string: 0.30.21 + pathe: 1.1.2 - braces@3.0.3: + '@vitest/spy@2.1.9': dependencies: - fill-range: 7.1.1 + tinyspy: 3.0.2 - browserslist@4.25.0: + '@vitest/utils@2.1.9': dependencies: - caniuse-lite: 1.0.30001723 - electron-to-chromium: 1.5.167 - node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.25.0) + '@vitest/pretty-format': 2.1.9 + loupe: 3.2.1 + tinyrainbow: 1.2.0 - bs-logger@0.2.6: - dependencies: - fast-json-stable-stringify: 2.1.0 + ansi-regex@5.0.1: {} - bser@2.1.1: - dependencies: - node-int64: 0.4.0 + ansi-regex@6.1.0: {} - buffer-from@1.1.2: {} + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 - callsites@3.1.0: {} + ansi-styles@6.2.1: {} - camelcase@5.3.1: {} + assertion-error@2.0.1: {} - camelcase@6.3.0: {} + balanced-match@1.0.2: {} - caniuse-lite@1.0.30001723: {} + balanced-match@4.0.4: {} - chalk@4.1.2: + brace-expansion@2.0.2: dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - char-regex@1.0.2: {} - - ci-info@3.9.0: {} + balanced-match: 1.0.2 - ci-info@4.2.0: {} + brace-expansion@5.0.6: + dependencies: + balanced-match: 4.0.4 - cjs-module-lexer@2.1.0: {} + cac@6.7.14: {} - cliui@8.0.1: + chai@5.3.3: dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 - co@4.6.0: {} - - collect-v8-coverage@1.0.2: {} + check-error@2.1.3: {} color-convert@2.0.1: dependencies: @@ -2278,124 +1130,66 @@ snapshots: commander@14.0.0: {} - concat-map@0.0.1: {} - - convert-source-map@2.0.0: {} - - create-require@1.1.1: {} - - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - debug@4.4.1: - dependencies: - ms: 2.1.3 - - dedent@1.6.0: {} - - deepmerge@4.3.1: {} - - detect-newline@3.1.0: {} - - diff-sequences@29.6.3: {} - - diff@4.0.2: {} - - eastasianwidth@0.2.0: {} - - ejs@3.1.10: - dependencies: - jake: 10.9.2 - - electron-to-chromium@1.5.167: {} - - emittery@0.13.1: {} - - emoji-regex@8.0.0: {} - - emoji-regex@9.2.2: {} - - error-ex@1.3.2: - dependencies: - is-arrayish: 0.2.1 - - escalade@3.2.0: {} - - escape-string-regexp@2.0.0: {} - - esprima@4.0.1: {} - - execa@5.1.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - exit-x@0.2.2: {} - - expect@29.7.0: + cross-spawn@7.0.6: dependencies: - '@jest/expect-utils': 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 - expect@30.0.0: + debug@4.4.1: dependencies: - '@jest/expect-utils': 30.0.0 - '@jest/get-type': 30.0.0 - jest-matcher-utils: 30.0.0 - jest-message-util: 30.0.0 - jest-mock: 30.0.0 - jest-util: 30.0.0 + ms: 2.1.3 - fast-json-stable-stringify@2.1.0: {} + deep-eql@5.0.2: {} - fb-watchman@2.0.2: - dependencies: - bser: 2.1.1 + eastasianwidth@0.2.0: {} - filelist@1.0.4: - dependencies: - minimatch: 5.1.6 + emoji-regex@8.0.0: {} - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 + emoji-regex@9.2.2: {} - find-up@4.1.0: - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 + es-module-lexer@1.7.0: {} + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + + expect-type@1.3.0: {} foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 - fs.realpath@1.0.0: {} - fsevents@2.3.3: optional: true - gensync@1.0.0-beta.2: {} - - get-caller-file@2.0.5: {} - - get-package-type@0.1.0: {} - - get-stream@6.0.1: {} - glob@10.4.5: dependencies: foreground-child: 3.3.1 @@ -2414,63 +1208,16 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 2.0.0 - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - globals@11.12.0: {} - - graceful-fs@4.2.11: {} - has-flag@4.0.0: {} html-escaper@2.0.2: {} - human-signals@2.1.0: {} - - import-local@3.2.0: - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - - imurmurhash@0.1.4: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - is-arrayish@0.2.1: {} - is-fullwidth-code-point@3.0.0: {} - is-generator-fn@2.1.0: {} - - is-number@7.0.0: {} - - is-stream@2.0.1: {} - isexe@2.0.0: {} istanbul-lib-coverage@3.2.2: {} - istanbul-lib-instrument@6.0.3: - dependencies: - '@babel/core': 7.27.4 - '@babel/parser': 7.27.5 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 7.7.2 - transitivePeerDependencies: - - supports-color - istanbul-lib-report@3.0.1: dependencies: istanbul-lib-coverage: 3.2.2 @@ -2500,425 +1247,35 @@ snapshots: dependencies: '@isaacs/cliui': 8.0.2 - jake@10.9.2: - dependencies: - async: 3.2.6 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - - jest-changed-files@30.0.0: - dependencies: - execa: 5.1.1 - jest-util: 30.0.0 - p-limit: 3.1.0 - - jest-circus@30.0.0: - dependencies: - '@jest/environment': 30.0.0 - '@jest/expect': 30.0.0 - '@jest/test-result': 30.0.0 - '@jest/types': 30.0.0 - '@types/node': 24.0.1 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.6.0 - is-generator-fn: 2.1.0 - jest-each: 30.0.0 - jest-matcher-utils: 30.0.0 - jest-message-util: 30.0.0 - jest-runtime: 30.0.0 - jest-snapshot: 30.0.0 - jest-util: 30.0.0 - p-limit: 3.1.0 - pretty-format: 30.0.0 - pure-rand: 7.0.1 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-cli@30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)): - dependencies: - '@jest/core': 30.0.0(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) - '@jest/test-result': 30.0.0 - '@jest/types': 30.0.0 - chalk: 4.1.2 - exit-x: 0.2.2 - import-local: 3.2.0 - jest-config: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) - jest-util: 30.0.0 - jest-validate: 30.0.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - esbuild-register - - supports-color - - ts-node - - jest-config@30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)): - dependencies: - '@babel/core': 7.27.4 - '@jest/get-type': 30.0.0 - '@jest/pattern': 30.0.0 - '@jest/test-sequencer': 30.0.0 - '@jest/types': 30.0.0 - babel-jest: 30.0.0(@babel/core@7.27.4) - chalk: 4.1.2 - ci-info: 4.2.0 - deepmerge: 4.3.1 - glob: 10.4.5 - graceful-fs: 4.2.11 - jest-circus: 30.0.0 - jest-docblock: 30.0.0 - jest-environment-node: 30.0.0 - jest-regex-util: 30.0.0 - jest-resolve: 30.0.0 - jest-runner: 30.0.0 - jest-util: 30.0.0 - jest-validate: 30.0.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 30.0.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 24.0.1 - ts-node: 10.9.2(@types/node@24.0.1)(typescript@5.8.3) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-diff@29.7.0: - dependencies: - chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-diff@30.0.0: - dependencies: - '@jest/diff-sequences': 30.0.0 - '@jest/get-type': 30.0.0 - chalk: 4.1.2 - pretty-format: 30.0.0 - - jest-docblock@30.0.0: - dependencies: - detect-newline: 3.1.0 - - jest-each@30.0.0: - dependencies: - '@jest/get-type': 30.0.0 - '@jest/types': 30.0.0 - chalk: 4.1.2 - jest-util: 30.0.0 - pretty-format: 30.0.0 - - jest-environment-node@30.0.0: - dependencies: - '@jest/environment': 30.0.0 - '@jest/fake-timers': 30.0.0 - '@jest/types': 30.0.0 - '@types/node': 24.0.1 - jest-mock: 30.0.0 - jest-util: 30.0.0 - jest-validate: 30.0.0 - - jest-get-type@29.6.3: {} - - jest-haste-map@30.0.0: - dependencies: - '@jest/types': 30.0.0 - '@types/node': 24.0.1 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 30.0.0 - jest-util: 30.0.0 - jest-worker: 30.0.0 - micromatch: 4.0.8 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - - jest-leak-detector@30.0.0: - dependencies: - '@jest/get-type': 30.0.0 - pretty-format: 30.0.0 - - jest-matcher-utils@29.7.0: - dependencies: - chalk: 4.1.2 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-matcher-utils@30.0.0: - dependencies: - '@jest/get-type': 30.0.0 - chalk: 4.1.2 - jest-diff: 30.0.0 - pretty-format: 30.0.0 - - jest-message-util@29.7.0: - dependencies: - '@babel/code-frame': 7.27.1 - '@jest/types': 29.6.3 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - stack-utils: 2.0.6 - - jest-message-util@30.0.0: - dependencies: - '@babel/code-frame': 7.27.1 - '@jest/types': 30.0.0 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.8 - pretty-format: 30.0.0 - slash: 3.0.0 - stack-utils: 2.0.6 - - jest-mock@30.0.0: - dependencies: - '@jest/types': 30.0.0 - '@types/node': 24.0.1 - jest-util: 30.0.0 - - jest-pnp-resolver@1.2.3(jest-resolve@30.0.0): - optionalDependencies: - jest-resolve: 30.0.0 + lodash@4.17.21: {} - jest-regex-util@30.0.0: {} + loupe@3.2.1: {} - jest-resolve-dependencies@30.0.0: - dependencies: - jest-regex-util: 30.0.0 - jest-snapshot: 30.0.0 - transitivePeerDependencies: - - supports-color + lru-cache@10.4.3: {} - jest-resolve@30.0.0: - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-haste-map: 30.0.0 - jest-pnp-resolver: 1.2.3(jest-resolve@30.0.0) - jest-util: 30.0.0 - jest-validate: 30.0.0 - slash: 3.0.0 - unrs-resolver: 1.9.0 - - jest-runner@30.0.0: - dependencies: - '@jest/console': 30.0.0 - '@jest/environment': 30.0.0 - '@jest/test-result': 30.0.0 - '@jest/transform': 30.0.0 - '@jest/types': 30.0.0 - '@types/node': 24.0.1 - chalk: 4.1.2 - emittery: 0.13.1 - exit-x: 0.2.2 - graceful-fs: 4.2.11 - jest-docblock: 30.0.0 - jest-environment-node: 30.0.0 - jest-haste-map: 30.0.0 - jest-leak-detector: 30.0.0 - jest-message-util: 30.0.0 - jest-resolve: 30.0.0 - jest-runtime: 30.0.0 - jest-util: 30.0.0 - jest-watcher: 30.0.0 - jest-worker: 30.0.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color + lru-cache@11.1.0: {} - jest-runtime@30.0.0: + magic-string@0.30.21: dependencies: - '@jest/environment': 30.0.0 - '@jest/fake-timers': 30.0.0 - '@jest/globals': 30.0.0 - '@jest/source-map': 30.0.0 - '@jest/test-result': 30.0.0 - '@jest/transform': 30.0.0 - '@jest/types': 30.0.0 - '@types/node': 24.0.1 - chalk: 4.1.2 - cjs-module-lexer: 2.1.0 - collect-v8-coverage: 1.0.2 - glob: 10.4.5 - graceful-fs: 4.2.11 - jest-haste-map: 30.0.0 - jest-message-util: 30.0.0 - jest-mock: 30.0.0 - jest-regex-util: 30.0.0 - jest-resolve: 30.0.0 - jest-snapshot: 30.0.0 - jest-util: 30.0.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color + '@jridgewell/sourcemap-codec': 1.5.5 - jest-snapshot@30.0.0: + magicast@0.3.5: dependencies: - '@babel/core': 7.27.4 - '@babel/generator': 7.27.5 - '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.27.4) - '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.27.4) + '@babel/parser': 7.27.5 '@babel/types': 7.27.6 - '@jest/expect-utils': 30.0.0 - '@jest/get-type': 30.0.0 - '@jest/snapshot-utils': 30.0.0 - '@jest/transform': 30.0.0 - '@jest/types': 30.0.0 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.27.4) - chalk: 4.1.2 - expect: 30.0.0 - graceful-fs: 4.2.11 - jest-diff: 30.0.0 - jest-matcher-utils: 30.0.0 - jest-message-util: 30.0.0 - jest-util: 30.0.0 - pretty-format: 30.0.0 - semver: 7.7.2 - synckit: 0.11.8 - transitivePeerDependencies: - - supports-color - - jest-util@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/node': 24.0.1 - chalk: 4.1.2 - ci-info: 3.9.0 - graceful-fs: 4.2.11 - picomatch: 2.3.1 - - jest-util@30.0.0: - dependencies: - '@jest/types': 30.0.0 - '@types/node': 24.0.1 - chalk: 4.1.2 - ci-info: 4.2.0 - graceful-fs: 4.2.11 - picomatch: 4.0.2 - - jest-validate@30.0.0: - dependencies: - '@jest/get-type': 30.0.0 - '@jest/types': 30.0.0 - camelcase: 6.3.0 - chalk: 4.1.2 - leven: 3.1.0 - pretty-format: 30.0.0 - - jest-watcher@30.0.0: - dependencies: - '@jest/test-result': 30.0.0 - '@jest/types': 30.0.0 - '@types/node': 24.0.1 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 30.0.0 - string-length: 4.0.2 - - jest-worker@30.0.0: - dependencies: - '@types/node': 24.0.1 - '@ungap/structured-clone': 1.3.0 - jest-util: 30.0.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - - jest@30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)): - dependencies: - '@jest/core': 30.0.0(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) - '@jest/types': 30.0.0 - import-local: 3.2.0 - jest-cli: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - esbuild-register - - supports-color - - ts-node - - js-tokens@4.0.0: {} - - js-yaml@3.14.1: - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - - jsesc@3.1.0: {} - - json-parse-even-better-errors@2.3.1: {} - - json5@2.2.3: {} - - leven@3.1.0: {} - - lines-and-columns@1.2.4: {} - - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 - - lodash.memoize@4.1.2: {} - - lodash@4.17.21: {} - - lru-cache@10.4.3: {} - - lru-cache@11.1.0: {} - - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 + source-map-js: 1.2.1 make-dir@4.0.0: dependencies: semver: 7.7.2 - make-error@1.3.6: {} - - makeerror@1.0.12: - dependencies: - tmpl: 1.0.5 - - merge-stream@2.0.0: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mimic-fn@2.1.0: {} - minimatch@10.0.3: dependencies: '@isaacs/brace-expansion': 5.0.0 - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.12 - - minimatch@5.1.6: + minimatch@10.2.5: dependencies: - brace-expansion: 2.0.2 + brace-expansion: 5.0.6 minimatch@9.0.5: dependencies: @@ -2928,55 +1285,10 @@ snapshots: ms@2.1.3: {} - napi-postinstall@0.2.4: {} - - natural-compare@1.4.0: {} - - node-int64@0.4.0: {} - - node-releases@2.0.19: {} - - normalize-path@3.0.0: {} - - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@4.1.0: - dependencies: - p-limit: 2.3.0 - - p-try@2.2.0: {} + nanoid@3.3.12: {} package-json-from-dist@1.0.1: {} - parse-json@5.2.0: - dependencies: - '@babel/code-frame': 7.27.1 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - path-key@3.1.1: {} path-scurry@1.11.1: @@ -2989,48 +1301,53 @@ snapshots: lru-cache: 11.1.0 minipass: 7.1.2 - picocolors@1.1.1: {} - - picomatch@2.3.1: {} - - picomatch@4.0.2: {} - - pirates@4.0.7: {} - - pkg-dir@4.2.0: - dependencies: - find-up: 4.1.0 - - pretty-format@29.7.0: - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - - pretty-format@30.0.0: - dependencies: - '@jest/schemas': 30.0.0 - ansi-styles: 5.2.0 - react-is: 18.3.1 - - pure-rand@7.0.1: {} + pathe@1.1.2: {} - react-is@18.3.1: {} + pathval@2.0.1: {} - require-directory@2.1.1: {} + picocolors@1.1.1: {} - resolve-cwd@3.0.0: + postcss@8.5.14: dependencies: - resolve-from: 5.0.0 - - resolve-from@5.0.0: {} + nanoid: 3.3.12 + picocolors: 1.1.1 + source-map-js: 1.2.1 rimraf@6.0.1: dependencies: glob: 11.0.3 package-json-from-dist: 1.0.1 - semver@6.3.1: {} + rollup@4.60.3: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.60.3 + '@rollup/rollup-android-arm64': 4.60.3 + '@rollup/rollup-darwin-arm64': 4.60.3 + '@rollup/rollup-darwin-x64': 4.60.3 + '@rollup/rollup-freebsd-arm64': 4.60.3 + '@rollup/rollup-freebsd-x64': 4.60.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.3 + '@rollup/rollup-linux-arm-musleabihf': 4.60.3 + '@rollup/rollup-linux-arm64-gnu': 4.60.3 + '@rollup/rollup-linux-arm64-musl': 4.60.3 + '@rollup/rollup-linux-loong64-gnu': 4.60.3 + '@rollup/rollup-linux-loong64-musl': 4.60.3 + '@rollup/rollup-linux-ppc64-gnu': 4.60.3 + '@rollup/rollup-linux-ppc64-musl': 4.60.3 + '@rollup/rollup-linux-riscv64-gnu': 4.60.3 + '@rollup/rollup-linux-riscv64-musl': 4.60.3 + '@rollup/rollup-linux-s390x-gnu': 4.60.3 + '@rollup/rollup-linux-x64-gnu': 4.60.3 + '@rollup/rollup-linux-x64-musl': 4.60.3 + '@rollup/rollup-openbsd-x64': 4.60.3 + '@rollup/rollup-openharmony-arm64': 4.60.3 + '@rollup/rollup-win32-arm64-msvc': 4.60.3 + '@rollup/rollup-win32-ia32-msvc': 4.60.3 + '@rollup/rollup-win32-x64-gnu': 4.60.3 + '@rollup/rollup-win32-x64-msvc': 4.60.3 + fsevents: 2.3.3 semver@7.7.2: {} @@ -3040,29 +1357,15 @@ snapshots: shebang-regex@3.0.0: {} - signal-exit@3.0.7: {} + siginfo@2.0.0: {} signal-exit@4.1.0: {} - slash@3.0.0: {} + source-map-js@1.2.1: {} - source-map-support@0.5.13: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.6.1: {} - - sprintf-js@1.0.3: {} - - stack-utils@2.0.6: - dependencies: - escape-string-regexp: 2.0.0 + stackback@0.0.2: {} - string-length@4.0.2: - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 + std-env@3.10.0: {} string-width@4.2.3: dependencies: @@ -3084,133 +1387,101 @@ snapshots: dependencies: ansi-regex: 6.1.0 - strip-bom@4.0.0: {} - - strip-final-newline@2.0.0: {} - - strip-json-comments@3.1.1: {} - supports-color@7.2.0: dependencies: has-flag: 4.0.0 - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - - synckit@0.11.8: - dependencies: - '@pkgr/core': 0.2.7 - - test-exclude@6.0.0: + test-exclude@7.0.2: dependencies: '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - - tmpl@1.0.5: {} - - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 + glob: 10.4.5 + minimatch: 10.2.5 - ts-jest@29.4.0(@babel/core@7.27.4)(@jest/transform@30.0.0)(@jest/types@30.0.0)(babel-jest@30.0.0(@babel/core@7.27.4))(jest-util@30.0.0)(jest@30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)))(typescript@5.8.3): - dependencies: - bs-logger: 0.2.6 - ejs: 3.1.10 - fast-json-stable-stringify: 2.1.0 - jest: 30.0.0(@types/node@24.0.1)(ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3)) - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.7.2 - type-fest: 4.41.0 - typescript: 5.8.3 - yargs-parser: 21.1.1 - optionalDependencies: - '@babel/core': 7.27.4 - '@jest/transform': 30.0.0 - '@jest/types': 30.0.0 - babel-jest: 30.0.0(@babel/core@7.27.4) - jest-util: 30.0.0 + tinybench@2.9.0: {} - ts-node@10.9.2(@types/node@24.0.1)(typescript@5.8.3): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 24.0.1 - acorn: 8.15.0 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.8.3 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - - tslib@2.8.1: - optional: true + tinyexec@0.3.2: {} - type-detect@4.0.8: {} + tinypool@1.1.1: {} - type-fest@0.21.3: {} + tinyrainbow@1.2.0: {} - type-fest@4.41.0: {} + tinyspy@3.0.2: {} typescript@5.8.3: {} undici-types@7.8.0: {} - unrs-resolver@1.9.0: - dependencies: - napi-postinstall: 0.2.4 - optionalDependencies: - '@unrs/resolver-binding-android-arm-eabi': 1.9.0 - '@unrs/resolver-binding-android-arm64': 1.9.0 - '@unrs/resolver-binding-darwin-arm64': 1.9.0 - '@unrs/resolver-binding-darwin-x64': 1.9.0 - '@unrs/resolver-binding-freebsd-x64': 1.9.0 - '@unrs/resolver-binding-linux-arm-gnueabihf': 1.9.0 - '@unrs/resolver-binding-linux-arm-musleabihf': 1.9.0 - '@unrs/resolver-binding-linux-arm64-gnu': 1.9.0 - '@unrs/resolver-binding-linux-arm64-musl': 1.9.0 - '@unrs/resolver-binding-linux-ppc64-gnu': 1.9.0 - '@unrs/resolver-binding-linux-riscv64-gnu': 1.9.0 - '@unrs/resolver-binding-linux-riscv64-musl': 1.9.0 - '@unrs/resolver-binding-linux-s390x-gnu': 1.9.0 - '@unrs/resolver-binding-linux-x64-gnu': 1.9.0 - '@unrs/resolver-binding-linux-x64-musl': 1.9.0 - '@unrs/resolver-binding-wasm32-wasi': 1.9.0 - '@unrs/resolver-binding-win32-arm64-msvc': 1.9.0 - '@unrs/resolver-binding-win32-ia32-msvc': 1.9.0 - '@unrs/resolver-binding-win32-x64-msvc': 1.9.0 - - update-browserslist-db@1.1.3(browserslist@4.25.0): + vite-node@2.1.9(@types/node@24.0.1): dependencies: - browserslist: 4.25.0 - escalade: 3.2.0 - picocolors: 1.1.1 - - v8-compile-cache-lib@3.0.1: {} + cac: 6.7.14 + debug: 4.4.1 + es-module-lexer: 1.7.0 + pathe: 1.1.2 + vite: 5.4.21(@types/node@24.0.1) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser - v8-to-istanbul@9.3.0: + vite@5.4.21(@types/node@24.0.1): dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@types/istanbul-lib-coverage': 2.0.6 - convert-source-map: 2.0.0 + esbuild: 0.21.5 + postcss: 8.5.14 + rollup: 4.60.3 + optionalDependencies: + '@types/node': 24.0.1 + fsevents: 2.3.3 - walker@1.0.8: + vitest@2.1.9(@types/node@24.0.1): dependencies: - makeerror: 1.0.12 + '@vitest/expect': 2.1.9 + '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@24.0.1)) + '@vitest/pretty-format': 2.1.9 + '@vitest/runner': 2.1.9 + '@vitest/snapshot': 2.1.9 + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.3.3 + debug: 4.4.1 + expect-type: 1.3.0 + magic-string: 0.30.21 + pathe: 1.1.2 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.1.1 + tinyrainbow: 1.2.0 + vite: 5.4.21(@types/node@24.0.1) + vite-node: 2.1.9(@types/node@24.0.1) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.0.1 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser which@2.0.2: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -3222,30 +1493,3 @@ snapshots: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 - - wrappy@1.0.2: {} - - write-file-atomic@5.0.1: - dependencies: - imurmurhash: 0.1.4 - signal-exit: 4.1.0 - - y18n@5.0.8: {} - - yallist@3.1.1: {} - - yargs-parser@21.1.1: {} - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - - yn@3.1.1: {} - - yocto-queue@0.1.0: {} diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..601b349 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + include: ['__tests__/**/*.ts'], + coverage: { + provider: 'v8', + include: ['src/**/*.ts'], + reporter: ['text', 'lcov'], + }, + }, +}); From 8c63d113d3e14742ad825144b12705185e3c77ef Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 13:49:19 +0500 Subject: [PATCH 18/30] fix(release): keep backward compatibility, target 1.4.0 Re-target this PR as a backward-compatible 1.4.0 minor instead of 2.0. - Restore the legacy `default` export with the `resample_ohlcv`, `array`, `json`, `trade_to_candle`, `tick_chart` aliases. 1.x consumers using `import lib from 'ohlc-resample'; lib.tick_chart(...)` continue to work unchanged. - Source the CLI's `--version` string from `package.json` at runtime via `require('../package.json')`, so version bumps stay in one place (matches the project's manual-bump convention). - Bump to 1.4.0 in `package.json`. - Rewrite CHANGELOG entry as 1.4.0; drop the breaking-changes section. Note: prior commits on this branch carry stale `!` markers and `BREAKING CHANGE:` trailers from when this was scoped as 2.0. The final state of the branch is non-breaking; squash-merging the PR is the cleanest path. --- CHANGELOG.md | 24 ++++++++++++------------ package.json | 2 +- src/cli.ts | 7 ++++++- src/index.ts | 13 +++++++++++++ 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4906af2..dfd6120 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,16 @@ # Changelog -## 2.0.0 +## 1.4.0 -### Breaking changes -- **Removed legacy `default` export** from the package entrypoint. The aliases `resample_ohlcv`, `array`, `json`, `trade_to_candle`, and `tick_chart` are gone β€” use the named exports `resampleOhlcv`, `resampleTicksByTime`, and `resampleTicksByCount` instead. -- **`bin.ohlc` now points at `dist/cli.js`** (was `src/cli.ts`). The previously published binary was non-functional; this fix changes the resolved path post-install. -- **`parseCSV` (CLI helper) now returns `{ rows, skipped }`** instead of `IOHLCV[]`. Internal API; only relevant if you imported it from `ohlc-resample/dist/cli`. +A backward-compatible feature release. The legacy `default` export (with the `resample_ohlcv`, `array`, `json`, `trade_to_candle`, `tick_chart` aliases) is preserved. ### CLI -- The CLI is now actually functional β€” replaces the stub in 1.x. +- The CLI is now actually functional β€” replaces the stub from earlier 1.x versions. - `--input-format ` now actually honors the requested format (was previously a no-op heuristic). -- New `-s, --shape ` flag for OHLCV tuple vs object JSON output. Closes #8 (the array-of-arrays requirement). -- Auto-detects tuple vs object shape on JSON input and preserves it through the pipeline by default. -- Malformed CSV rows are now reported as a warning to stderr, and a CSV with zero valid rows now exits non-zero instead of producing an empty output. +- New `-s, --shape ` flag for OHLCV tuple vs object JSON output. Auto-detects shape on JSON input and preserves it through the pipeline by default. Closes #8 (the array-of-arrays requirement). +- Malformed CSV rows are reported as a warning to stderr; a CSV with zero valid rows now exits non-zero instead of producing empty output. - SIGINT/SIGTERM no longer clobber a non-zero exit code. +- `bin.ohlc` now points at `dist/cli.js` (was `src/cli.ts`, which was non-functional post-install since npm cannot execute raw TypeScript). ### Library - `resampleOhlcv` now has overloaded signatures: pass `OHLCV[]` and TypeScript narrows the return to `OHLCV[]`; pass `IOHLCV[]` and you get `IOHLCV[]`. @@ -22,10 +19,13 @@ ### Build & tooling - **Test runner: jest β†’ vitest.** Replaces `jest` + `ts-jest` + `@types/jest` with `vitest` + `@vitest/coverage-v8`. Cold-start test time drops from ~9s to ~2.5s. Removed the `ts-jest` `ignoreCodes: [2345]` workaround. Added `test:watch` and `test:coverage` scripts; the default `test` script no longer auto-collects coverage on every run. -- Dropped `fast-csv` dependency (1.x branch removed it; 2.0 ships clean). +- Dropped `fast-csv` dependency (was unused in 1.x; 2.0 was going to remove it, this release ships the clean state). - Dropped unused `chalk` dep. -- Moved `ts-node` to `devDependencies`. +- Moved `ts-node` to `devDependencies` (no longer needed at runtime now that the bin points at compiled JS). - Dropped `coveralls` from `prepublishOnly` (was guaranteed to fail without a token). -- `prebuild` now cleans `dist/` (was cleaning a non-existent `build/`). +- `prebuild` now cleans `dist/` (was incorrectly cleaning `build/`). - CI workflow updated to trigger on `main` and run Node 20.x / 22.x (was `master` + Node 10/12). - Removed obsolete `.npmignore` (superseded by `package.json#files`). + +### Internal (not part of the public API) +- The CLI's `parseCSV` helper now returns `{ rows, skipped }` instead of `IOHLCV[]`. Only relevant if you imported it from `ohlc-resample/dist/cli`. diff --git a/package.json b/package.json index 912d6e0..e8f527d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ohlc-resample", - "version": "2.0.0", + "version": "1.4.0", "description": "Resample (inter-convert) trade, ticks or OHLCV data to different time frames, includes CLI", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/src/cli.ts b/src/cli.ts index f4f9bf6..ffe1382 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -6,6 +6,11 @@ import { program as commanderProgram } from 'commander'; import { IOHLCV, OHLCV } from './types'; import { resampleOhlcv } from './lib'; +// Read version from package.json so there's a single source of truth. +// `dist/cli.js` is one level deep; `../package.json` resolves to the +// installed package's manifest both during dev and post-install. +const { version: PACKAGE_VERSION } = require('../package.json') as { version: string }; + type Shape = 'object' | 'array'; type InputFormat = 'csv' | 'json'; type InputFormatOption = InputFormat | 'auto'; @@ -169,7 +174,7 @@ export async function runCli( .option('-s, --shape ', 'Output shape for JSON (object, array, auto)', 'auto') .option('-b, --base-timeframe ', 'Base timeframe in seconds', '60') .option('-n, --new-timeframe ', 'New timeframe in seconds', '300') - .version('2.0.0'); + .version(PACKAGE_VERSION); program.parse(argv); program.showHelpAfterError(); diff --git a/src/index.ts b/src/index.ts index e06143c..35ef3cc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,15 @@ +import * as lib from './lib'; export * from './lib'; export * from './types'; + +/** + * Legacy aliased export, kept for backward compatibility with 1.x consumers. + * Prefer the named exports above. + */ +export default { + resample_ohlcv: lib.resampleOhlcv, + array: lib.resampleOhlcv, + json: lib.resampleOhlcv, + trade_to_candle: lib.resampleTicksByTime, + tick_chart: lib.resampleTicksByCount, +}; From deee26fb14e40f4a73bc0a167e8c36457009158a Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 13:52:21 +0500 Subject: [PATCH 19/30] ci: add tag-triggered npm publish workflow with provenance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pushing a `v*` tag now runs build + tests, then `pnpm publish` with npm provenance. Replaces the implicit "publish from a maintainer's laptop" model. One-time setup before the first release: 1. Generate an npm "Automation" granular access token scoped to this package (npmjs.com β†’ Access Tokens). 2. Add it to the repo as the `NPM_TOKEN` secret. Release flow: - Bump `package.json#version`, commit, merge to `main`. - `git tag v1.4.0 && git push --tags`. - The workflow tests, builds, and publishes with provenance attesting the artifact came from this exact commit + workflow run. --- .github/workflows/publish.yml | 27 +++++++++++++++++++++++++++ CHANGELOG.md | 1 + 2 files changed, 28 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..ee84288 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,27 @@ +name: Publish + +on: + push: + tags: ['v*'] + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22.x + registry-url: 'https://registry.npmjs.org' + - uses: pnpm/action-setup@v4 + with: + version: 9 + - run: pnpm install --frozen-lockfile + - run: pnpm run build + - run: pnpm test + - run: pnpm publish --no-git-checks --access public --provenance + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index dfd6120..7d3f7c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ A backward-compatible feature release. The legacy `default` export (with the `re - Dropped `coveralls` from `prepublishOnly` (was guaranteed to fail without a token). - `prebuild` now cleans `dist/` (was incorrectly cleaning `build/`). - CI workflow updated to trigger on `main` and run Node 20.x / 22.x (was `master` + Node 10/12). +- New tag-triggered `publish.yml` workflow: pushing a `v*` tag runs build + tests, then `pnpm publish` with [npm provenance](https://docs.npmjs.com/generating-provenance-statements). Requires an `NPM_TOKEN` repo secret (npm "Automation" granular token). - Removed obsolete `.npmignore` (superseded by `package.json#files`). ### Internal (not part of the public API) From 22f56038d50fdb80f454dc68c62a1c1e6f5efc15 Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 14:26:02 +0500 Subject: [PATCH 20/30] ci: adopt Changesets for release management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the tag-triggered publish workflow with a Changesets-driven release pipeline. Every PR that affects users carries a markdown file in `.changeset/` describing the change and the semver bump. On merge to `main`, the action either opens a "Version Packages" PR (consuming pending changesets, bumping `package.json#version`, regenerating `CHANGELOG.md`) or, when no changesets are pending, publishes to npm with provenance and creates a matching GitHub Release. This delivers the trio (git tag + GitHub Release + npm publish) as a single consequence of merging the Version Packages PR, and tracks release notes in the file system instead of relying on commit message discipline. Changes - New `release.yml` workflow using `changesets/action@v1` with `contents: write`, `pull-requests: write`, and `id-token: write` (npm provenance). - Drop the prior `publish.yml`. - Add `@changesets/cli` and `@changesets/changelog-github` as devDependencies. Changelog entries are auto-linked to PRs/contributors. - New `release` script: `pnpm publish --no-git-checks --access public --provenance`. - New `changeset` script for ergonomics (`pnpm changeset`). - Reset `CHANGELOG.md` to a stub header so Changesets owns it going forward. - Roll `package.json#version` back to 1.3.0. The Version Packages PR produced after merging this one will propose the bump to 1.4.0 driven by the seed changeset. - Seed `.changeset/working-cli-and-modern-tooling.md` capturing the full body of work in this PR; this becomes the 1.4.0 release note. - README: new "Releasing" section documenting the flow. One-time setup before the first release - Add `NPM_TOKEN` (npm "Granular Access Token", read+write on this package) as a repo secret. - Settings β†’ Actions β†’ General β†’ enable "Allow GitHub Actions to create and approve pull requests". --- .changeset/README.md | 55 ++ .changeset/config.json | 14 + .changeset/working-cli-and-modern-tooling.md | 30 + .github/workflows/publish.yml | 27 - .github/workflows/release.yml | 69 ++ CHANGELOG.md | 33 +- README.md | 14 + package.json | 8 +- pnpm-lock.yaml | 783 +++++++++++++++++++ 9 files changed, 972 insertions(+), 61 deletions(-) create mode 100644 .changeset/README.md create mode 100644 .changeset/config.json create mode 100644 .changeset/working-cli-and-modern-tooling.md delete mode 100644 .github/workflows/publish.yml create mode 100644 .github/workflows/release.yml diff --git a/.changeset/README.md b/.changeset/README.md new file mode 100644 index 0000000..338dee3 --- /dev/null +++ b/.changeset/README.md @@ -0,0 +1,55 @@ +# Changesets + +This directory holds the source of truth for release notes and version bumps. + +## How it works + +Every PR that affects users (or anything you'd want to mention in a release) carries a markdown file in this directory. The CI workflow `release.yml` consumes these files when publishing. + +## Adding a changeset + +```bash +pnpm changeset +``` + +The CLI prompts for: +1. Bump type β€” `patch` (bugfix), `minor` (backward-compatible feature), or `major` (breaking change). +2. A summary β€” used as the release note. + +It writes a file like `.changeset/quiet-foxes-paint.md`. Commit it alongside your code change. + +## Manual format + +If you'd rather write the file directly (LLM-friendly), the format is: + +```markdown +--- +"ohlc-resample": minor +--- + +One-line summary of the change. + +Optional longer description in markdown. Bullets, code blocks, links β€” whatever +makes the release note useful. +``` + +The filename can be anything ending in `.md` other than `README.md` and `config.json`. + +## What happens after merge + +1. PR with code + changeset β†’ merges to `main` +2. `release.yml` opens (or updates) a "Version Packages" PR that: + - Bumps `package.json#version` + - Prepends a `CHANGELOG.md` section assembled from pending changesets + - Deletes the consumed changeset files +3. Merging the Version Packages PR triggers `release.yml` again, which: + - Publishes to npm with provenance + - Creates a `vX.Y.Z` git tag + - Creates a GitHub Release with the CHANGELOG entry as the body + +Trivial changes (typos, internal refactors that don't affect users) don't need a changeset. + +## Reference + +- https://github.com/changesets/changesets +- https://github.com/changesets/action diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 0000000..e9cc1a3 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", + "changelog": [ + "@changesets/changelog-github", + { "repo": "adiled/ohlc-resample" } + ], + "commit": false, + "fixed": [], + "linked": [], + "access": "public", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.changeset/working-cli-and-modern-tooling.md b/.changeset/working-cli-and-modern-tooling.md new file mode 100644 index 0000000..5a399ae --- /dev/null +++ b/.changeset/working-cli-and-modern-tooling.md @@ -0,0 +1,30 @@ +--- +"ohlc-resample": minor +--- + +Working CLI, vitest, modernized tooling. Closes #8. + +**CLI** + +- The CLI is now actually functional (was a stub in 1.x). +- `--input-format ` now honors the requested format (was previously a no-op heuristic). +- New `-s, --shape ` flag for OHLCV tuple vs object JSON output. Auto-detects shape on JSON input and preserves it through the pipeline by default. +- Malformed CSV rows are reported to stderr; a CSV with zero valid rows now exits non-zero instead of producing empty output. +- `bin.ohlc` now points at `dist/cli.js` (was `src/cli.ts`, which was non-functional post-install). +- SIGINT/SIGTERM no longer clobber a non-zero exit code. + +**Library** + +- `resampleOhlcv` now has overloaded signatures so the return type follows the input shape (`OHLCV[]` in β†’ `OHLCV[]` out, same for `IOHLCV[]`). +- Types (`IOHLCV`, `OHLCV`, `TradeTick`, etc.) are re-exported from the package entrypoint. +- Fixed inverted JSDoc on `resampleOhlcvArray`. +- Backward compatibility preserved: the legacy `default` export with `resample_ohlcv`, `array`, `json`, `trade_to_candle`, `tick_chart` aliases continues to work. + +**Build & tooling** + +- Test runner migrated jest β†’ vitest. Cold-start time: ~9s β†’ ~2.5s. +- Releases are now managed by [Changesets](https://github.com/changesets/changesets) with tag-triggered npm publish (with provenance) and auto-generated GitHub Releases. +- Dropped unused `chalk` and `coveralls` deps; moved `ts-node` to devDependencies. +- `prebuild` now cleans `dist/` (was incorrectly cleaning `build/`). +- CI workflow updated to trigger on `main` (was `master`) and run Node 20.x / 22.x (was EOL 10.x / 12.x). +- Removed obsolete `.npmignore` (superseded by `package.json#files`). diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index ee84288..0000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Publish - -on: - push: - tags: ['v*'] - -jobs: - publish: - runs-on: ubuntu-latest - permissions: - contents: read - id-token: write - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 22.x - registry-url: 'https://registry.npmjs.org' - - uses: pnpm/action-setup@v4 - with: - version: 9 - - run: pnpm install --frozen-lockfile - - run: pnpm run build - - run: pnpm test - - run: pnpm publish --no-git-checks --access public --provenance - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..362ee90 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,69 @@ +# Release workflow. +# +# Fires on every push to `main`. Runs the changesets action, which has two modes: +# +# 1. If pending `.changeset/*.md` files exist on `main`, opens (or updates) a +# "Version Packages" PR that bumps `package.json#version`, regenerates +# `CHANGELOG.md`, and deletes the consumed changeset files. +# +# 2. If there are no pending changesets (i.e. the Version Packages PR was just +# merged), runs `pnpm release` which publishes to npm with provenance. +# The action also creates a matching GitHub Release with the CHANGELOG +# entry as the body. +# +# One-time setup: +# - In repo Settings β†’ Secrets and variables β†’ Actions, add `NPM_TOKEN` +# (an npm "Granular Access Token" with read+write on this package). +# - In repo Settings β†’ Actions β†’ General, ensure the workflow has permission +# to create pull requests ("Allow GitHub Actions to create and approve pull +# requests"). + +name: Release + +on: + push: + branches: [main] + +# Prevent two release runs from racing each other. +concurrency: ${{ github.workflow }}-${{ github.ref }} + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write # tag pushes, CHANGELOG commits, GH Release creation + pull-requests: write # opening the Version Packages PR + id-token: write # npm provenance (OIDC) + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # full history; changesets needs it to diff branches + + - uses: pnpm/action-setup@v4 + with: + version: 9 + + - uses: actions/setup-node@v4 + with: + node-version: 22.x + cache: pnpm + registry-url: https://registry.npmjs.org + + - run: pnpm install --frozen-lockfile + + - run: pnpm run build + + - run: pnpm test + + - name: Create release PR or publish + uses: changesets/action@v1 + with: + publish: pnpm release + version: pnpm changeset version + commit: "chore(release): version packages" + title: "chore(release): version packages" + createGithubReleases: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d3f7c2..e930908 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,32 +1 @@ -# Changelog - -## 1.4.0 - -A backward-compatible feature release. The legacy `default` export (with the `resample_ohlcv`, `array`, `json`, `trade_to_candle`, `tick_chart` aliases) is preserved. - -### CLI -- The CLI is now actually functional β€” replaces the stub from earlier 1.x versions. -- `--input-format ` now actually honors the requested format (was previously a no-op heuristic). -- New `-s, --shape ` flag for OHLCV tuple vs object JSON output. Auto-detects shape on JSON input and preserves it through the pipeline by default. Closes #8 (the array-of-arrays requirement). -- Malformed CSV rows are reported as a warning to stderr; a CSV with zero valid rows now exits non-zero instead of producing empty output. -- SIGINT/SIGTERM no longer clobber a non-zero exit code. -- `bin.ohlc` now points at `dist/cli.js` (was `src/cli.ts`, which was non-functional post-install since npm cannot execute raw TypeScript). - -### Library -- `resampleOhlcv` now has overloaded signatures: pass `OHLCV[]` and TypeScript narrows the return to `OHLCV[]`; pass `IOHLCV[]` and you get `IOHLCV[]`. -- Fixed inverted JSDoc on `resampleOhlcvArray`. -- The package now also re-exports types (`IOHLCV`, `OHLCV`, `TradeTick`, etc.) from the entrypoint. - -### Build & tooling -- **Test runner: jest β†’ vitest.** Replaces `jest` + `ts-jest` + `@types/jest` with `vitest` + `@vitest/coverage-v8`. Cold-start test time drops from ~9s to ~2.5s. Removed the `ts-jest` `ignoreCodes: [2345]` workaround. Added `test:watch` and `test:coverage` scripts; the default `test` script no longer auto-collects coverage on every run. -- Dropped `fast-csv` dependency (was unused in 1.x; 2.0 was going to remove it, this release ships the clean state). -- Dropped unused `chalk` dep. -- Moved `ts-node` to `devDependencies` (no longer needed at runtime now that the bin points at compiled JS). -- Dropped `coveralls` from `prepublishOnly` (was guaranteed to fail without a token). -- `prebuild` now cleans `dist/` (was incorrectly cleaning `build/`). -- CI workflow updated to trigger on `main` and run Node 20.x / 22.x (was `master` + Node 10/12). -- New tag-triggered `publish.yml` workflow: pushing a `v*` tag runs build + tests, then `pnpm publish` with [npm provenance](https://docs.npmjs.com/generating-provenance-statements). Requires an `NPM_TOKEN` repo secret (npm "Automation" granular token). -- Removed obsolete `.npmignore` (superseded by `package.json#files`). - -### Internal (not part of the public API) -- The CLI's `parseCSV` helper now returns `{ rows, skipped }` instead of `IOHLCV[]`. Only relevant if you imported it from `ohlc-resample/dist/cli`. +# ohlc-resample diff --git a/README.md b/README.md index cdfece0..ba3b738 100644 --- a/README.md +++ b/README.md @@ -281,6 +281,20 @@ cat data.csv | ohlc-resample -o output.json ohlc-resample -i data.json -b 300 -n 3600 -f csv -o output.csv ``` +## Releasing + +Releases are managed by [Changesets](https://github.com/changesets/changesets). The flow: + +1. Make a code change. +2. `pnpm changeset` β€” pick the bump type (patch / minor / major) and write a one-line summary. (Or write the file by hand under `.changeset/`; see `.changeset/README.md` for the format.) +3. Commit both the code and the changeset, open a PR. +4. After the PR merges, the `Release` workflow opens a "Version Packages" PR with the version bump and `CHANGELOG.md` entry. +5. Merging that PR publishes to npm with provenance, creates a `vX.Y.Z` git tag, and creates a GitHub Release β€” all in one workflow run. + +Trivial changes (typos, internal refactors that don't affect users) don't need a changeset. + +**One-time setup before the first release:** add `NPM_TOKEN` (an npm "Granular Access Token" with read+write on this package) as a repo secret on GitHub. + ## Contributors πŸ‘€ **Adil Shaikh (https://adils.me)** diff --git a/package.json b/package.json index e8f527d..8c31ce0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ohlc-resample", - "version": "1.4.0", + "version": "1.3.0", "description": "Resample (inter-convert) trade, ticks or OHLCV data to different time frames, includes CLI", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -17,7 +17,9 @@ "prepublishOnly": "npm test && npm run build && npm run build:check", "test": "vitest run", "test:watch": "vitest", - "test:coverage": "vitest run --coverage" + "test:coverage": "vitest run --coverage", + "changeset": "changeset", + "release": "pnpm publish --no-git-checks --access public --provenance" }, "bin": { "ohlc": "./dist/cli.js" @@ -45,6 +47,8 @@ }, "homepage": "https://github.com/adiled/ohlc-resample#readme", "devDependencies": { + "@changesets/changelog-github": "^0.5.0", + "@changesets/cli": "^2.27.0", "@types/lodash": "^4.14.173", "@types/node": "^24.0.1", "@vitest/coverage-v8": "^2.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 91b9877..5cedc24 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,6 +15,12 @@ importers: specifier: ^4.17.21 version: 4.17.21 devDependencies: + '@changesets/changelog-github': + specifier: ^0.5.0 + version: 0.5.2 + '@changesets/cli': + specifier: ^2.27.0 + version: 2.31.0(@types/node@24.0.1) '@types/lodash': specifier: ^4.14.173 version: 4.17.17 @@ -53,6 +59,10 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + '@babel/types@7.27.6': resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} engines: {node: '>=6.9.0'} @@ -60,6 +70,67 @@ packages: '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@changesets/apply-release-plan@7.1.1': + resolution: {integrity: sha512-9qPCm/rLx/xoOFXIHGB229+4GOL76S4MC+7tyOuTsR6+1jYlfFDQORdvwR5hDA6y4FL2BPt3qpbcQIS+dW85LA==} + + '@changesets/assemble-release-plan@6.0.10': + resolution: {integrity: sha512-rSDcqdJ9KbVyjpBIuCidhvZNIiVt1XaIYp73ycVQRIA5n/j6wQaEk0ChRLMUQ1vkxZe51PTQ9OIhbg6HQMW45A==} + + '@changesets/changelog-git@0.2.1': + resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} + + '@changesets/changelog-github@0.5.2': + resolution: {integrity: sha512-HeGeDl8HaIGj9fQHo/tv5XKQ2SNEi9+9yl1Bss1jttPqeiASRXhfi0A2wv8yFKCp07kR1gpOI5ge6+CWNm1jPw==} + + '@changesets/cli@2.31.0': + resolution: {integrity: sha512-AhI4enNTgHu2IZr6K4WZyf0EPch4XVMn1yOMFmCD9gsfBGqMYaHXls5HyDv6/CL5axVQABz68eG30eCtbr2wFg==} + hasBin: true + + '@changesets/config@3.1.4': + resolution: {integrity: sha512-pf0bvD/v6WI2cRlZ6hzpjtZdSlXDXMAJ+Iz7xfFzV4ZxJ8OGGAON+1qYc99ZPrijnt4xp3VGG7eNvAOGS24V1Q==} + + '@changesets/errors@0.2.0': + resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} + + '@changesets/get-dependents-graph@2.1.4': + resolution: {integrity: sha512-ZsS00x6WvmHq3sQv8oCMwL0f/z3wbXCVuSVTJwCnnmbC/iBdNJGFx1EcbMG4PC6sXRyH69liM4A2WKXzn/kRPg==} + + '@changesets/get-github-info@0.7.0': + resolution: {integrity: sha512-+i67Bmhfj9V4KfDeS1+Tz3iF32btKZB2AAx+cYMqDSRFP7r3/ZdGbjCo+c6qkyViN9ygDuBjzageuPGJtKGe5A==} + + '@changesets/get-release-plan@4.0.16': + resolution: {integrity: sha512-2K5Om6CrMPm45rtvckfzWo7e9jOVCKLCnXia5eUPaURH7/LWzri7pK1TycdzAuAtehLkW7VPbWLCSExTHmiI6g==} + + '@changesets/get-version-range-type@0.4.0': + resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} + + '@changesets/git@3.0.4': + resolution: {integrity: sha512-BXANzRFkX+XcC1q/d27NKvlJ1yf7PSAgi8JG6dt8EfbHFHi4neau7mufcSca5zRhwOL8j9s6EqsxmT+s+/E6Sw==} + + '@changesets/logger@0.1.1': + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} + + '@changesets/parse@0.4.3': + resolution: {integrity: sha512-ZDmNc53+dXdWEv7fqIUSgRQOLYoUom5Z40gmLgmATmYR9NbL6FJJHwakcCpzaeCy+1D0m0n7mT4jj2B/MQPl7A==} + + '@changesets/pre@2.0.2': + resolution: {integrity: sha512-HaL/gEyFVvkf9KFg6484wR9s0qjAXlZ8qWPDkTyKF6+zqjBe/I2mygg3MbpZ++hdi0ToqNUF8cjj7fBy0dg8Ug==} + + '@changesets/read@0.6.7': + resolution: {integrity: sha512-D1G4AUYGrBEk8vj8MGwf75k9GpN6XL3wg8i42P2jZZwFLXnlr2Pn7r9yuQNbaMCarP7ZQWNJbV6XLeysAIMhTA==} + + '@changesets/should-skip-package@0.1.2': + resolution: {integrity: sha512-qAK/WrqWLNCP22UDdBTMPH5f41elVDlsNyat180A33dWxuUDyNpg6fPi/FyTZwRriVjg0L8gnjJn2F9XAoF0qw==} + + '@changesets/types@4.1.0': + resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} + + '@changesets/types@6.1.0': + resolution: {integrity: sha512-rKQcJ+o1nKNgeoYRHKOS07tAMNd3YSN0uHaJOZYjBAgxfV7TUE7JE+z4BzZdQwb5hKaYbayKN5KrYV7ODb2rAA==} + + '@changesets/write@0.4.0': + resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} + '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} @@ -198,6 +269,15 @@ packages: cpu: [x64] os: [win32] + '@inquirer/external-editor@1.0.3': + resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + '@isaacs/balanced-match@4.0.1': resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} engines: {node: 20 || >=22} @@ -235,6 +315,24 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@manypkg/find-root@1.1.0': + resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} + + '@manypkg/get-packages@1.1.3': + resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -373,6 +471,9 @@ packages: '@types/lodash@4.17.17': resolution: {integrity: sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==} + '@types/node@12.20.55': + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + '@types/node@24.0.1': resolution: {integrity: sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==} @@ -414,6 +515,10 @@ packages: '@vitest/utils@2.1.9': resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==} + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -430,6 +535,16 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} @@ -441,6 +556,10 @@ packages: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} engines: {node: 18 || 20 || >=22} + better-path-resolve@1.0.0: + resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} + engines: {node: '>=4'} + brace-expansion@2.0.2: resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} @@ -448,6 +567,10 @@ packages: resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} engines: {node: 18 || 20 || >=22} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -456,6 +579,9 @@ packages: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} + chardet@2.1.1: + resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + check-error@2.1.3: resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} engines: {node: '>= 16'} @@ -475,6 +601,9 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + dataloader@1.4.0: + resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} + debug@4.4.1: resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} engines: {node: '>=6.0'} @@ -488,6 +617,18 @@ packages: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} + detect-indent@6.1.0: + resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} + engines: {node: '>=8'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dotenv@8.6.0: + resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} + engines: {node: '>=10'} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -497,6 +638,10 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + enquirer@2.4.1: + resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} + engines: {node: '>=8.6'} + es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} @@ -505,6 +650,11 @@ packages: engines: {node: '>=12'} hasBin: true + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -512,15 +662,45 @@ packages: resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} + extendable-error@0.1.7: + resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fastq@1.20.1: + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me @@ -531,6 +711,13 @@ packages: engines: {node: 20 || >=22} hasBin: true + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -538,10 +725,42 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + human-id@4.1.3: + resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} + hasBin: true + + iconv-lite@0.7.2: + resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} + engines: {node: '>=0.10.0'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-subdir@1.2.0: + resolution: {integrity: sha512-2AT6j+gXe/1ueqbW6fLZJiIw3F8iXGJtt0yDrZaBhAZEG1raiTxKWU+IPqMCzQAXOUCKdA4UDMgacKH25XG2Cw==} + engines: {node: '>=4'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -568,6 +787,24 @@ packages: resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} engines: {node: 20 || >=22} + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + hasBin: true + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -591,6 +828,14 @@ packages: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + minimatch@10.0.3: resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} engines: {node: 20 || >=22} @@ -607,6 +852,10 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -615,9 +864,48 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + outdent@0.5.0: + resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} + + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + package-manager-detector@0.2.11: + resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -630,6 +918,10 @@ packages: resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} engines: {node: 20 || >=22} + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -640,10 +932,41 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + postcss@8.5.14: resolution: {integrity: sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==} engines: {node: ^10 || ^12 || >=14} + prettier@2.8.8: + resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} + engines: {node: '>=10.13.0'} + hasBin: true + + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + read-yaml-file@1.1.0: + resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} + engines: {node: '>=6'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rimraf@6.0.1: resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} engines: {node: 20 || >=22} @@ -654,6 +977,12 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + semver@7.7.2: resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} engines: {node: '>=10'} @@ -674,10 +1003,20 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + spawndamnit@3.0.1: + resolution: {integrity: sha512-MmnduQUuHCoFckZoWnXsTg7JaiLBJrKFj9UI2MbRPGaJeVpsLcVBu6P/IGZovziM/YBsellCmsprgNA+w0CzVg==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -700,10 +1039,18 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + term-size@2.2.1: + resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} + engines: {node: '>=8'} + test-exclude@7.0.2: resolution: {integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==} engines: {node: '>=18'} @@ -726,6 +1073,13 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + typescript@5.8.3: resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} engines: {node: '>=14.17'} @@ -734,6 +1088,10 @@ packages: undici-types@7.8.0: resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + vite-node@2.1.9: resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==} engines: {node: ^18.0.0 || >=20.0.0} @@ -795,6 +1153,12 @@ packages: jsdom: optional: true + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -828,6 +1192,8 @@ snapshots: dependencies: '@babel/types': 7.27.6 + '@babel/runtime@7.29.2': {} + '@babel/types@7.27.6': dependencies: '@babel/helper-string-parser': 7.27.1 @@ -835,6 +1201,164 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} + '@changesets/apply-release-plan@7.1.1': + dependencies: + '@changesets/config': 3.1.4 + '@changesets/get-version-range-type': 0.4.0 + '@changesets/git': 3.0.4 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + detect-indent: 6.1.0 + fs-extra: 7.0.1 + lodash.startcase: 4.4.0 + outdent: 0.5.0 + prettier: 2.8.8 + resolve-from: 5.0.0 + semver: 7.7.2 + + '@changesets/assemble-release-plan@6.0.10': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.4 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + semver: 7.7.2 + + '@changesets/changelog-git@0.2.1': + dependencies: + '@changesets/types': 6.1.0 + + '@changesets/changelog-github@0.5.2': + dependencies: + '@changesets/get-github-info': 0.7.0 + '@changesets/types': 6.1.0 + dotenv: 8.6.0 + transitivePeerDependencies: + - encoding + + '@changesets/cli@2.31.0(@types/node@24.0.1)': + dependencies: + '@changesets/apply-release-plan': 7.1.1 + '@changesets/assemble-release-plan': 6.0.10 + '@changesets/changelog-git': 0.2.1 + '@changesets/config': 3.1.4 + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.4 + '@changesets/get-release-plan': 4.0.16 + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.7 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@changesets/write': 0.4.0 + '@inquirer/external-editor': 1.0.3(@types/node@24.0.1) + '@manypkg/get-packages': 1.1.3 + ansi-colors: 4.1.3 + enquirer: 2.4.1 + fs-extra: 7.0.1 + mri: 1.2.0 + package-manager-detector: 0.2.11 + picocolors: 1.1.1 + resolve-from: 5.0.0 + semver: 7.7.2 + spawndamnit: 3.0.1 + term-size: 2.2.1 + transitivePeerDependencies: + - '@types/node' + + '@changesets/config@3.1.4': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/get-dependents-graph': 2.1.4 + '@changesets/logger': 0.1.1 + '@changesets/should-skip-package': 0.1.2 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + micromatch: 4.0.8 + + '@changesets/errors@0.2.0': + dependencies: + extendable-error: 0.1.7 + + '@changesets/get-dependents-graph@2.1.4': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + picocolors: 1.1.1 + semver: 7.7.2 + + '@changesets/get-github-info@0.7.0': + dependencies: + dataloader: 1.4.0 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + '@changesets/get-release-plan@4.0.16': + dependencies: + '@changesets/assemble-release-plan': 6.0.10 + '@changesets/config': 3.1.4 + '@changesets/pre': 2.0.2 + '@changesets/read': 0.6.7 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/get-version-range-type@0.4.0': {} + + '@changesets/git@3.0.4': + dependencies: + '@changesets/errors': 0.2.0 + '@manypkg/get-packages': 1.1.3 + is-subdir: 1.2.0 + micromatch: 4.0.8 + spawndamnit: 3.0.1 + + '@changesets/logger@0.1.1': + dependencies: + picocolors: 1.1.1 + + '@changesets/parse@0.4.3': + dependencies: + '@changesets/types': 6.1.0 + js-yaml: 4.1.1 + + '@changesets/pre@2.0.2': + dependencies: + '@changesets/errors': 0.2.0 + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + fs-extra: 7.0.1 + + '@changesets/read@0.6.7': + dependencies: + '@changesets/git': 3.0.4 + '@changesets/logger': 0.1.1 + '@changesets/parse': 0.4.3 + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + p-filter: 2.1.0 + picocolors: 1.1.1 + + '@changesets/should-skip-package@0.1.2': + dependencies: + '@changesets/types': 6.1.0 + '@manypkg/get-packages': 1.1.3 + + '@changesets/types@4.1.0': {} + + '@changesets/types@6.1.0': {} + + '@changesets/write@0.4.0': + dependencies: + '@changesets/types': 6.1.0 + fs-extra: 7.0.1 + human-id: 4.1.3 + prettier: 2.8.8 + '@esbuild/aix-ppc64@0.21.5': optional: true @@ -904,6 +1428,13 @@ snapshots: '@esbuild/win32-x64@0.21.5': optional: true + '@inquirer/external-editor@1.0.3(@types/node@24.0.1)': + dependencies: + chardet: 2.1.1 + iconv-lite: 0.7.2 + optionalDependencies: + '@types/node': 24.0.1 + '@isaacs/balanced-match@4.0.1': {} '@isaacs/brace-expansion@5.0.0': @@ -940,6 +1471,34 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@manypkg/find-root@1.1.0': + dependencies: + '@babel/runtime': 7.29.2 + '@types/node': 12.20.55 + find-up: 4.1.0 + fs-extra: 8.1.0 + + '@manypkg/get-packages@1.1.3': + dependencies: + '@babel/runtime': 7.29.2 + '@changesets/types': 4.1.0 + '@manypkg/find-root': 1.1.0 + fs-extra: 8.1.0 + globby: 11.1.0 + read-yaml-file: 1.1.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.20.1 + '@pkgjs/parseargs@0.11.0': optional: true @@ -1024,6 +1583,8 @@ snapshots: '@types/lodash@4.17.17': {} + '@types/node@12.20.55': {} + '@types/node@24.0.1': dependencies: undici-types: 7.8.0 @@ -1086,6 +1647,8 @@ snapshots: loupe: 3.2.1 tinyrainbow: 1.2.0 + ansi-colors@4.1.3: {} + ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -1096,12 +1659,24 @@ snapshots: ansi-styles@6.2.1: {} + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + array-union@2.1.0: {} + assertion-error@2.0.1: {} balanced-match@1.0.2: {} balanced-match@4.0.4: {} + better-path-resolve@1.0.0: + dependencies: + is-windows: 1.0.2 + brace-expansion@2.0.2: dependencies: balanced-match: 1.0.2 @@ -1110,6 +1685,10 @@ snapshots: dependencies: balanced-match: 4.0.4 + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + cac@6.7.14: {} chai@5.3.3: @@ -1120,6 +1699,8 @@ snapshots: loupe: 3.2.1 pathval: 2.0.1 + chardet@2.1.1: {} + check-error@2.1.3: {} color-convert@2.0.1: @@ -1136,18 +1717,33 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + dataloader@1.4.0: {} + debug@4.4.1: dependencies: ms: 2.1.3 deep-eql@5.0.2: {} + detect-indent@6.1.0: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dotenv@8.6.0: {} + eastasianwidth@0.2.0: {} emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} + enquirer@2.4.1: + dependencies: + ansi-colors: 4.1.3 + strip-ansi: 6.0.1 + es-module-lexer@1.7.0: {} esbuild@0.21.5: @@ -1176,20 +1772,61 @@ snapshots: '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 + esprima@4.0.1: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.9 expect-type@1.3.0: {} + extendable-error@0.1.7: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 + fs-extra@7.0.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + fsevents@2.3.3: optional: true + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + glob@10.4.5: dependencies: foreground-child: 3.3.1 @@ -1208,12 +1845,45 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 2.0.0 + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + graceful-fs@4.2.11: {} + has-flag@4.0.0: {} html-escaper@2.0.2: {} + human-id@4.1.3: {} + + iconv-lite@0.7.2: + dependencies: + safer-buffer: 2.1.2 + + ignore@5.3.2: {} + + is-extglob@2.1.1: {} + is-fullwidth-code-point@3.0.0: {} + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-subdir@1.2.0: + dependencies: + better-path-resolve: 1.0.0 + + is-windows@1.0.2: {} + isexe@2.0.0: {} istanbul-lib-coverage@3.2.2: {} @@ -1247,6 +1917,25 @@ snapshots: dependencies: '@isaacs/cliui': 8.0.2 + js-yaml@3.14.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + lodash.startcase@4.4.0: {} + lodash@4.17.21: {} loupe@3.2.1: {} @@ -1269,6 +1958,13 @@ snapshots: dependencies: semver: 7.7.2 + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + minimatch@10.0.3: dependencies: '@isaacs/brace-expansion': 5.0.0 @@ -1283,12 +1979,42 @@ snapshots: minipass@7.1.2: {} + mri@1.2.0: {} + ms@2.1.3: {} nanoid@3.3.12: {} + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + outdent@0.5.0: {} + + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-map@2.1.0: {} + + p-try@2.2.0: {} + package-json-from-dist@1.0.1: {} + package-manager-detector@0.2.11: + dependencies: + quansync: 0.2.11 + + path-exists@4.0.0: {} + path-key@3.1.1: {} path-scurry@1.11.1: @@ -1301,18 +2027,41 @@ snapshots: lru-cache: 11.1.0 minipass: 7.1.2 + path-type@4.0.0: {} + pathe@1.1.2: {} pathval@2.0.1: {} picocolors@1.1.1: {} + picomatch@2.3.2: {} + + pify@4.0.1: {} + postcss@8.5.14: dependencies: nanoid: 3.3.12 picocolors: 1.1.1 source-map-js: 1.2.1 + prettier@2.8.8: {} + + quansync@0.2.11: {} + + queue-microtask@1.2.3: {} + + read-yaml-file@1.1.0: + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.2 + pify: 4.0.1 + strip-bom: 3.0.0 + + resolve-from@5.0.0: {} + + reusify@1.1.0: {} + rimraf@6.0.1: dependencies: glob: 11.0.3 @@ -1349,6 +2098,12 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.60.3 fsevents: 2.3.3 + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safer-buffer@2.1.2: {} + semver@7.7.2: {} shebang-command@2.0.0: @@ -1361,8 +2116,17 @@ snapshots: signal-exit@4.1.0: {} + slash@3.0.0: {} + source-map-js@1.2.1: {} + spawndamnit@3.0.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + sprintf-js@1.0.3: {} + stackback@0.0.2: {} std-env@3.10.0: {} @@ -1387,10 +2151,14 @@ snapshots: dependencies: ansi-regex: 6.1.0 + strip-bom@3.0.0: {} + supports-color@7.2.0: dependencies: has-flag: 4.0.0 + term-size@2.2.1: {} + test-exclude@7.0.2: dependencies: '@istanbuljs/schema': 0.1.3 @@ -1407,10 +2175,18 @@ snapshots: tinyspy@3.0.2: {} + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + tr46@0.0.3: {} + typescript@5.8.3: {} undici-types@7.8.0: {} + universalify@0.1.2: {} + vite-node@2.1.9(@types/node@24.0.1): dependencies: cac: 6.7.14 @@ -1473,6 +2249,13 @@ snapshots: - supports-color - terser + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + which@2.0.2: dependencies: isexe: 2.0.0 From a03aa3efad074069f860275084ac6af19f3e9b22 Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 15:38:04 +0500 Subject: [PATCH 21/30] chore: clean stale docs and tooling references MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - README: drop coveralls badge + link (coveralls was removed earlier in this branch); fix master β†’ main in remaining links; replace yarn β†’ pnpm in the test instructions; drop reference to a CONTRIBUTING.md that doesn't exist; point license link to COPYING. - Remove deprecated.md β€” coveralls is gone and TypeScript is on 5.x, the file's contents no longer reflect reality. - prepublishOnly: switch to pnpm for consistency with the rest of the toolchain. --- README.md | 11 ++++------- deprecated.md | 33 --------------------------------- package.json | 2 +- 3 files changed, 5 insertions(+), 41 deletions(-) delete mode 100644 deprecated.md diff --git a/README.md b/README.md index ba3b738..c688865 100644 --- a/README.md +++ b/README.md @@ -13,10 +13,7 @@ Resample (inter-convert) trade, ticks or OHLCV data to different time frames Maintenance - - Coverage Status - - + License: LGPL--3.0

@@ -306,12 +303,12 @@ Trivial changes (typos, internal refactors that don't affect users) don't need a ## 🀝 Contributing -Contributions, issues and feature requests are welcome!
Feel free to check [issues page](https://github.com/adiled/ohlc-resample/issues). You can also take a look at the [contributing guide](https://github.com/adiled/ohlc-resample/blob/master/CONTRIBUTING.md). +Contributions, issues and feature requests are welcome!
Feel free to check the [issues page](https://github.com/adiled/ohlc-resample/issues). ### Run tests ```sh -yarn test +pnpm test ``` ## Show your support @@ -321,4 +318,4 @@ Give a ⭐️ if this project helped you! ## πŸ“ License Copyright Β© 2022 [Adil Shaikh (https://adils.me)](https://github.com/adiled).
-This project is [LGPL--3.0](https://github.com/adiled/ohlc-resample/blob/master/LICENSE) licensed. +This project is [LGPL--3.0](https://github.com/adiled/ohlc-resample/blob/main/COPYING) licensed. diff --git a/deprecated.md b/deprecated.md deleted file mode 100644 index 3d52031..0000000 --- a/deprecated.md +++ /dev/null @@ -1,33 +0,0 @@ -# Deprecated stuff that need attention - -## Result of clean npm install with no package-lock.json - -```sh -$ npm i -npm WARN deprecated har-validator@5.1.5: this library is no longer supported -npm WARN deprecated uuid@3.4.0: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known -to be problematic. See https://v8.dev/blog/math-random for details. -npm WARN deprecated request@2.88.2: request has been deprecated, see https://github.com/request/request/issues/3142 -``` - -```sh -/ohlc-resample -└─┬ coveralls@3.1.1 - └─┬ request@2.88.2 - └── uuid@3.4.0 -``` - -```sh -/ohlc-resample -└─┬ coveralls@3.1.1 - └─┬ request@2.88.2 - └── har-validator@5.1.5 -``` - -### Result of npm outdated - -```sh -$ npm outdated -Package Current Wanted Latest Location Depended by -typescript 3.9.10 3.9.10 4.4.3 node_modules/typescript ohlc-resample (updated to 4.4.3) -``` diff --git a/package.json b/package.json index 8c31ce0..6e59367 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "prebuild": "rimraf dist", "build": "tsc --build", "build:check": "node -e \"require('./dist')\"", - "prepublishOnly": "npm test && npm run build && npm run build:check", + "prepublishOnly": "pnpm test && pnpm run build && pnpm run build:check", "test": "vitest run", "test:watch": "vitest", "test:coverage": "vitest run --coverage", From 0b028a53357039aacba6de3d402920ff78a01f00 Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 15:53:13 +0500 Subject: [PATCH 22/30] docs: document hosting independence and manual release flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the layered architecture explicit: GitHub is the conveyer belt for our CI, not a dependency of the release model. The Changesets machinery (`.changeset/*.md`, CHANGELOG, version-bump logic, npm publish) is portable to any forge or to no forge at all. Only `.github/workflows/release.yml` is GitHub-specific. Adds two subsections under Releasing: - "Hosting independence" β€” table of layers and what to swap when moving off GitHub. - "Manual release" β€” the local laptop flow for when CI is unavailable, the project hasn't been pushed to a forge yet, or you simply prefer hand-driven publishes. --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index c688865..f280e4a 100644 --- a/README.md +++ b/README.md @@ -292,6 +292,39 @@ Trivial changes (typos, internal refactors that don't affect users) don't need a **One-time setup before the first release:** add `NPM_TOKEN` (an npm "Granular Access Token" with read+write on this package) as a repo secret on GitHub. +### Hosting independence + +GitHub is a convenience layer here, not a dependency. The release machinery is layered: + +| Layer | Where it lives | GitHub-specific? | +|---|---|---| +| `.changeset/*.md` files, `CHANGELOG.md`, version bumps | In the repo, managed by `@changesets/cli` (pure JS) | No | +| Publish target | npmjs.com (or any npm-compatible registry via `publishConfig.registry`) | No | +| Bot that opens "Version Packages" PRs and creates Releases | `.github/workflows/release.yml` using `changesets/action@v1` | **Yes β€” the only GitHub-specific piece** | +| Source hosting | git remote | Yes | + +To move the project off GitHub: + +1. Repoint the git remote to a new host (GitLab, Forgejo, Gitea, sourcehut, self-hosted, …). +2. Replace `.github/workflows/release.yml` with equivalent CI on that host (GitLab CI, Forgejo Actions, Drone, Jenkins, …) that runs `pnpm changeset version` on push-to-`main` and `pnpm publish` when there are no pending changesets. Or skip CI entirely and use the manual flow below. + +The `.changeset/` directory, `CHANGELOG.md` format, version-bump logic, and npm publish step are unchanged across hosts. + +### Manual release (no CI, no forge integration) + +If you want to publish from a laptop β€” because the CI is unavailable, you don't have the project on a forge yet, or you simply prefer local control: + +```sh +pnpm changeset # write a changeset describing the change (or hand-author the .md) +pnpm changeset version # bumps package.json, regenerates CHANGELOG.md, deletes consumed changesets +git commit -am "chore(release): version packages" +git tag "v$(node -p "require('./package.json').version")" +git push --follow-tags +pnpm publish --access public +``` + +Same artifacts, same CHANGELOG entries, same npm package as the automated flow. + ## Contributors πŸ‘€ **Adil Shaikh (https://adils.me)** From 0cc9b6c000059170a005f88a3e053d591162f9e9 Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 16:18:23 +0500 Subject: [PATCH 23/30] ci: switch release flow from PR-driven to direct-commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the changesets/action PR-opening behaviour with raw CLI calls that bump, commit-to-main with [skip ci], publish, tag, and create the GitHub Release in a single workflow run from one push to main. Rationale: the release decision is driven entirely by what's in `.changeset/`. The "Version Packages" PR was just plumbing for repos with branch protection on `main`. This branch isn't protected, so collapse the two-PR dance into a single push-and-ship. Behaviour: - Push to main with a `.changeset/*.md` β†’ CI bumps, commits the bump back to main with [skip ci], publishes, tags, creates GH Release. - Push to main without a changeset β†’ CI exits cleanly, nothing released. Doc-only edits and refactors are silent. Order of operations is publish-then-tag so a phantom version on main without a published artifact is avoided. (Re-running after a publish failure is safe β€” npm rejects duplicate versions.) Permissions trimmed: dropped `pull-requests: write` since we no longer open PRs. Side effects: - Removed the "Allow GitHub Actions to create and approve pull requests" prerequisite from the README β€” direct-commit flow doesn't need it. - Local `main` will be one commit behind after each release; pull to catch up. - gitignore: AGENTS.md and CLAUDE.md added (local-only agent context). --- .github/workflows/release.yml | 76 ++++++++++++++++++++++++----------- .gitignore | 4 ++ README.md | 14 ++++--- 3 files changed, 64 insertions(+), 30 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 362ee90..73fcafe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,22 +1,23 @@ # Release workflow. # -# Fires on every push to `main`. Runs the changesets action, which has two modes: +# Fires on every push to `main`. The decision to release is driven entirely by +# what's in `.changeset/`: # -# 1. If pending `.changeset/*.md` files exist on `main`, opens (or updates) a -# "Version Packages" PR that bumps `package.json#version`, regenerates -# `CHANGELOG.md`, and deletes the consumed changeset files. +# - If pending `.changeset/*.md` files exist, the workflow runs the changesets +# CLI to bump `package.json#version`, regenerate `CHANGELOG.md`, and delete +# the consumed changeset files. It commits and pushes those changes to main +# (with `[skip ci]` so the bot's own commit doesn't re-trigger this workflow), +# then publishes to npm with provenance, tags `vX.Y.Z`, and creates a +# matching GitHub Release. # -# 2. If there are no pending changesets (i.e. the Version Packages PR was just -# merged), runs `pnpm release` which publishes to npm with provenance. -# The action also creates a matching GitHub Release with the CHANGELOG -# entry as the body. +# - If there are no pending changesets, the workflow exits cleanly. Nothing +# to release. +# +# All of this happens in a single workflow run from one push to main. # # One-time setup: # - In repo Settings β†’ Secrets and variables β†’ Actions, add `NPM_TOKEN` # (an npm "Granular Access Token" with read+write on this package). -# - In repo Settings β†’ Actions β†’ General, ensure the workflow has permission -# to create pull requests ("Allow GitHub Actions to create and approve pull -# requests"). name: Release @@ -31,13 +32,12 @@ jobs: release: runs-on: ubuntu-latest permissions: - contents: write # tag pushes, CHANGELOG commits, GH Release creation - pull-requests: write # opening the Version Packages PR + contents: write # push the bump commit + tag, create GH Release id-token: write # npm provenance (OIDC) steps: - uses: actions/checkout@v4 with: - fetch-depth: 0 # full history; changesets needs it to diff branches + fetch-depth: 0 # full history; changesets needs it - uses: pnpm/action-setup@v4 with: @@ -55,15 +55,43 @@ jobs: - run: pnpm test - - name: Create release PR or publish - uses: changesets/action@v1 - with: - publish: pnpm release - version: pnpm changeset version - commit: "chore(release): version packages" - title: "chore(release): version packages" - createGithubReleases: true + - name: Apply pending changesets and publish env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: | + set -euo pipefail + + # Consume any pending changesets β€” bumps version, updates CHANGELOG, + # deletes the consumed .changeset/*.md files. No-op if none pending. + pnpm changeset version + + if [[ -z $(git status --porcelain) ]]; then + echo "No pending changesets β€” nothing to release." + exit 0 + fi + + VERSION=$(node -p "require('./package.json').version") + TAG="v${VERSION}" + + git config user.email "github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + git add -A + git commit -m "chore(release): ${TAG} [skip ci]" + git push origin HEAD:main + + # Publish first so a push success + publish failure doesn't leave a + # phantom version on main. (npm rejects duplicate versions, so a + # retried run is safe.) + pnpm publish --no-git-checks --access public --provenance + + git tag "${TAG}" + git push origin "${TAG}" + + # Extract the just-prepended CHANGELOG entry (everything between the + # first `## ` heading and the next one, minus the heading itself) and + # use it as the GitHub Release body. + awk '/^## /{i++} i==1' CHANGELOG.md | tail -n +2 > /tmp/release-notes.md + gh release create "${TAG}" \ + --title "${TAG}" \ + --notes-file /tmp/release-notes.md diff --git a/.gitignore b/.gitignore index e083eb3..acaf3dd 100644 --- a/.gitignore +++ b/.gitignore @@ -90,3 +90,7 @@ typings/ build/ dist/ .coveralls.yml + +# Local agent context β€” kept out of the repo +AGENTS.md +CLAUDE.md diff --git a/README.md b/README.md index f280e4a..eb6fef5 100644 --- a/README.md +++ b/README.md @@ -280,15 +280,17 @@ ohlc-resample -i data.json -b 300 -n 3600 -f csv -o output.csv ## Releasing -Releases are managed by [Changesets](https://github.com/changesets/changesets). The flow: +Releases are driven by [Changesets](https://github.com/changesets/changesets). Any push to `main` that includes a file under `.changeset/` will trigger a release. 1. Make a code change. -2. `pnpm changeset` β€” pick the bump type (patch / minor / major) and write a one-line summary. (Or write the file by hand under `.changeset/`; see `.changeset/README.md` for the format.) -3. Commit both the code and the changeset, open a PR. -4. After the PR merges, the `Release` workflow opens a "Version Packages" PR with the version bump and `CHANGELOG.md` entry. -5. Merging that PR publishes to npm with provenance, creates a `vX.Y.Z` git tag, and creates a GitHub Release β€” all in one workflow run. +2. Add a changeset: + - `pnpm changeset` (interactive prompt), **or** hand-author a markdown file under `.changeset/` (see `.changeset/README.md` for the format). +3. Commit code + changeset, push to `main` (or merge a PR β€” both work). +4. CI consumes the changeset, bumps `package.json#version`, regenerates `CHANGELOG.md`, commits the bump back to `main` (with `[skip ci]`), then publishes to npm with provenance, tags `vX.Y.Z`, and creates a matching GitHub Release. All in one workflow run. -Trivial changes (typos, internal refactors that don't affect users) don't need a changeset. +Pushes without a changeset don't release. Trivial changes (typos, internal refactors that don't affect users) don't need one. + +After a release fires, your local `main` is one commit behind the bot's bump commit β€” `git pull` to catch up. **One-time setup before the first release:** add `NPM_TOKEN` (an npm "Granular Access Token" with read+write on this package) as a repo secret on GitHub. From 843a8688cf5320423cedff5f78bde3405f97d45a Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 18:03:06 +0500 Subject: [PATCH 24/30] fix(lib): preserve union-typed call signature for resampleOhlcv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The two-overload form added in this branch (`OHLCV[]` in β†’ `OHLCV[]` out, `IOHLCV[]` in β†’ `IOHLCV[]` out) is strictly narrower than the 1.x signature. Callers with code like function process(data: OHLCV[] | IOHLCV[]) { return resampleOhlcv(data, opts); // 1.x: OK; 1.4.0-pre: type error } would fail to type-check, because TypeScript overload resolution doesn't match a union argument against the individual overloads. Add the original union signature as a third overload. The narrower overloads remain preferred for new code; the union form keeps 1.x TypeScript callers compiling. Verified empirically against `origin/main`'s build: - declarations diff is now strictly additive - runtime smoke test (each public function + every default export alias on identical inputs) shows no behavioural drift --- src/lib.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib.ts b/src/lib.ts index bcd545a..9aeea46 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -26,6 +26,12 @@ export function resampleOhlcv( ohlcvData: IOHLCV[], options: { baseTimeframe: number; newTimeframe: number } ): IOHLCV[]; +// 1.x BC overload: a union-typed argument still resolves cleanly. Keep this +// even though the narrower overloads above are preferred for new code. +export function resampleOhlcv( + ohlcvData: OHLCV[] | IOHLCV[], + options: { baseTimeframe: number; newTimeframe: number } +): OHLCV[] | IOHLCV[]; export function resampleOhlcv( ohlcvData: OHLCV[] | IOHLCV[], { baseTimeframe = 60, newTimeframe = 300 }: { baseTimeframe: number; newTimeframe: number } From 38c010e6e69e67c7a35a50be39be78d053ae42b1 Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 18:05:28 +0500 Subject: [PATCH 25/30] fix(release): leave package.json#version untouched, let Changesets drive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Earlier commits on this branch bumped `package.json#version` from 1.2.1 (matches `main`) to 1.3.0 / 1.4.0 by hand. With Changesets adopted, the version is supposed to be a derived value β€” the workflow runs `pnpm changeset version` post-merge and computes the bump from the pending `.changeset/*.md` files. Reset the working tree's version to match `main` (1.2.1). The seed changeset declares "minor", so the next release will ship as 1.3.0 (previous published was 1.2.1 β†’ minor β†’ 1.3.0). Verified locally: `pnpm changeset version` against this state produces `"version": "1.3.0"` and a clean `## 1.3.0` CHANGELOG entry. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6e59367..09dfcf8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ohlc-resample", - "version": "1.3.0", + "version": "1.2.1", "description": "Resample (inter-convert) trade, ticks or OHLCV data to different time frames, includes CLI", "main": "dist/index.js", "types": "dist/index.d.ts", From 674d0d1da9db093f6e25518ca149acf8beb2cb01 Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 18:31:02 +0500 Subject: [PATCH 26/30] chore(deps)!: bump to current-LTS Node + latest deps + TS 6 + vitest 4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Major-bump worthy because of `engines.node` β‰₯22.12.0 (was β‰₯20.12.2). Runtime API surface is unchanged; smoke-tested against `origin/main`'s build with zero behavioural drift on every public function and every default-export alias. Deps - typescript: 5.8 β†’ 6.x. tsconfig modernized: `target: es2022`, `lib: es2022`, explicit `types: ["node"]`, `ignoreDeprecations: "6.0"` for `moduleResolution: node` (will need a node16/nodenext migration before TS 7). - vitest: 2.x β†’ 4.x. Requires Node β‰₯22.12 because vite 7 + std-env use require-of-ESM, which is only stable from Node 22.12+. - @vitest/coverage-v8 to match. - @types/node: 24 β†’ 25. - rimraf, commander, lodash, @types/lodash, @changesets/changelog-github β€” all to latest within range. Engines / CI - engines.node: β‰₯20.12.2 β†’ β‰₯22.12.0. - nodejs.yml matrix: [20.x, 22.x] β†’ [22.x, 24.x]. - release.yml setup-node: 22.x β†’ 24.x. CLI fix (caught by ad-hoc kicking-the-tires) - `-i` now always wins over stdin, regardless of `isTTY`. The previous `isTTY && options.input` gate broke any non-interactive caller (CI, scripted invocations) where stdin is not a TTY but `-i` is the intended source. Removed the unused `isTTY` parameter from `runCli` and added a regression test. Seed changeset relabelled `minor β†’ major` so the next release ships as 2.0.0, matching the engine bump's semver impact. --- .changeset/working-cli-and-modern-tooling.md | 38 +- .github/workflows/nodejs.yml | 2 +- .github/workflows/release.yml | 2 +- __tests__/cli.ts | 59 +- package.json | 22 +- pnpm-lock.yaml | 1181 +++++++----------- src/cli.ts | 6 +- tsconfig.json | 11 +- 8 files changed, 556 insertions(+), 765 deletions(-) diff --git a/.changeset/working-cli-and-modern-tooling.md b/.changeset/working-cli-and-modern-tooling.md index 5a399ae..16f5e16 100644 --- a/.changeset/working-cli-and-modern-tooling.md +++ b/.changeset/working-cli-and-modern-tooling.md @@ -1,30 +1,34 @@ --- -"ohlc-resample": minor +"ohlc-resample": major --- Working CLI, vitest, modernized tooling. Closes #8. -**CLI** +**Breaking change** -- The CLI is now actually functional (was a stub in 1.x). -- `--input-format ` now honors the requested format (was previously a no-op heuristic). -- New `-s, --shape ` flag for OHLCV tuple vs object JSON output. Auto-detects shape on JSON input and preserves it through the pipeline by default. -- Malformed CSV rows are reported to stderr; a CSV with zero valid rows now exits non-zero instead of producing empty output. -- `bin.ohlc` now points at `dist/cli.js` (was `src/cli.ts`, which was non-functional post-install). -- SIGINT/SIGTERM no longer clobber a non-zero exit code. +- `engines.node` bumped from `>=20.12.2` to `>=22.12.0` (current LTS floor). The runtime API surface is unchanged β€” this is purely an install-constraint update. Library consumers on Node 22+ see no behavioural difference. + +**CLI** (was a non-functional stub in 1.x; now ships) + +- `--input-format ` honors the requested format (was a no-op heuristic). +- New `-s, --shape ` for OHLCV tuple vs object JSON output. Auto-detects shape on JSON input and preserves it through the pipeline by default. +- `-i` always wins over stdin, even in non-TTY contexts (CI, scripts). +- Malformed CSV rows reported to stderr; zero valid rows now exits non-zero instead of producing empty output. +- `bin.ohlc` β†’ `dist/cli.js` (was `src/cli.ts`, non-functional post-install). +- SIGINT/SIGTERM preserve a previously-set non-zero exit code. **Library** -- `resampleOhlcv` now has overloaded signatures so the return type follows the input shape (`OHLCV[]` in β†’ `OHLCV[]` out, same for `IOHLCV[]`). -- Types (`IOHLCV`, `OHLCV`, `TradeTick`, etc.) are re-exported from the package entrypoint. +- `resampleOhlcv` now has overloaded signatures so the return type follows the input shape (`OHLCV[]` in β†’ `OHLCV[]` out, same for `IOHLCV[]`). The original union signature is preserved as a third overload, so 1.x TS callers with union-typed data still compile. +- Types (`IOHLCV`, `OHLCV`, `TradeTick`, etc.) are now re-exported from the package entrypoint. - Fixed inverted JSDoc on `resampleOhlcvArray`. -- Backward compatibility preserved: the legacy `default` export with `resample_ohlcv`, `array`, `json`, `trade_to_candle`, `tick_chart` aliases continues to work. +- The legacy `default` export with `resample_ohlcv`, `array`, `json`, `trade_to_candle`, `tick_chart` aliases is preserved unchanged. **Build & tooling** -- Test runner migrated jest β†’ vitest. Cold-start time: ~9s β†’ ~2.5s. -- Releases are now managed by [Changesets](https://github.com/changesets/changesets) with tag-triggered npm publish (with provenance) and auto-generated GitHub Releases. -- Dropped unused `chalk` and `coveralls` deps; moved `ts-node` to devDependencies. -- `prebuild` now cleans `dist/` (was incorrectly cleaning `build/`). -- CI workflow updated to trigger on `main` (was `master`) and run Node 20.x / 22.x (was EOL 10.x / 12.x). -- Removed obsolete `.npmignore` (superseded by `package.json#files`). +- Test runner migrated jest β†’ vitest 4. Cold-start time ~9s β†’ ~2.5s. +- TypeScript bumped to 6.x; tsconfig modernized (`target: es2022`, `lib: es2022`, explicit `types: ["node"]`). +- Releases managed by [Changesets](https://github.com/changesets/changesets) with a direct-commit workflow: a push to `main` with a changeset triggers bump + commit + npm publish (with provenance) + tag + GitHub Release in a single CI run. +- Dropped unused `chalk`, `coveralls`, `fast-csv` deps; moved `ts-node` to devDependencies. +- CI workflow: triggers on `main`, runs Node 22.x and 24.x. +- Removed obsolete `.npmignore`, dropped stale `deprecated.md`, cleaned coveralls/yarn/master references from README. diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index c28dac6..3a3b2bd 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [20.x, 22.x] + node-version: [22.x, 24.x] steps: - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 73fcafe..1f6bb74 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,7 +45,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 22.x + node-version: 24.x cache: pnpm registry-url: https://registry.npmjs.org diff --git a/__tests__/cli.ts b/__tests__/cli.ts index 3aa727d..69dbe98 100644 --- a/__tests__/cli.ts +++ b/__tests__/cli.ts @@ -76,7 +76,7 @@ describe('CLI', () => { await withTimeout(async () => { const { writable, getData } = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', csvPath], undefined, writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', csvPath], undefined, writable, err.writable); const output = JSON.parse(getData()); expect(output).toHaveLength(1); expect(output[0]).toMatchObject(expectedCandle); @@ -87,7 +87,7 @@ describe('CLI', () => { await withTimeout(async () => { const { writable, getData } = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', jsonPath], undefined, writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', jsonPath], undefined, writable, err.writable); const output = JSON.parse(getData()); expect(output).toHaveLength(1); expect(output[0]).toMatchObject(expectedCandle); @@ -98,7 +98,7 @@ describe('CLI', () => { await withTimeout(async () => { const { writable, getData } = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', jsonArrayPath], undefined, writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', jsonArrayPath], undefined, writable, err.writable); const output = JSON.parse(getData()); expect(output).toHaveLength(1); expect(Array.isArray(output[0])).toBe(true); @@ -112,7 +112,7 @@ describe('CLI', () => { fs.writeFileSync(invalidFile, 'invalid data'); const out = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', invalidFile], undefined, out.writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', invalidFile], undefined, out.writable, err.writable); expect(err.getData()).toContain('Only CSV and JSON files are accepted'); expect(process.exitCode).toBe(1); }, 1000, 'reject invalid extension'); @@ -125,12 +125,27 @@ describe('CLI', () => { const out = captureWritable(); const err = captureWritable(); const stdin = readableFromString(fs.readFileSync(csvPath, 'utf8')); - await runCli(['node', 'cli.js'], stdin, out.writable, err.writable, false); + await runCli(['node', 'cli.js'], stdin, out.writable, err.writable); const output = JSON.parse(out.getData()); expect(output).toHaveLength(1); expect(output[0]).toMatchObject(expectedCandle); }, 1000, 'read pipe CSV'); }); + + test('-i wins even when stdin is non-interactive (regression)', async () => { + // Previously the CLI gated file-reading on `isTTY`, which broke + // scripted/CI invocations where stdin is not a TTY but `-i` is set. + await withTimeout(async () => { + const out = captureWritable(); + const err = captureWritable(); + // Hand it a non-empty stdin to prove it's ignored when -i is given. + const stdin = readableFromString('garbage that should never be read'); + await runCli(['node', 'cli.js', '-i', csvPath], stdin, out.writable, err.writable); + const output = JSON.parse(out.getData()); + expect(output[0]).toMatchObject(expectedCandle); + expect(process.exitCode).toBe(0); + }, 1000, '-i over stdin'); + }); }); describe('Output --shape flag', () => { @@ -138,7 +153,7 @@ describe('CLI', () => { await withTimeout(async () => { const out = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', jsonPath, '-s', 'array'], undefined, out.writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', jsonPath, '-s', 'array'], undefined, out.writable, err.writable); const output = JSON.parse(out.getData()); expect(Array.isArray(output[0])).toBe(true); expect(output[0]).toEqual([1609459200000, 100, 108, 95, 103, 5000]); @@ -149,7 +164,7 @@ describe('CLI', () => { await withTimeout(async () => { const out = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', jsonArrayPath, '-s', 'object'], undefined, out.writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', jsonArrayPath, '-s', 'object'], undefined, out.writable, err.writable); const output = JSON.parse(out.getData()); expect(output[0]).toMatchObject(expectedCandle); }, 1000, '--shape object'); @@ -159,7 +174,7 @@ describe('CLI', () => { await withTimeout(async () => { const out = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', csvPath], undefined, out.writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', csvPath], undefined, out.writable, err.writable); const output = JSON.parse(out.getData()); expect(output[0]).toMatchObject(expectedCandle); }, 1000, '--shape auto'); @@ -173,7 +188,7 @@ describe('CLI', () => { test('writes CSV output', async () => { await withTimeout(async () => { const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', jsonPath, '-o', outputFile, '-f', 'csv'], undefined, undefined, err.writable, true); + await runCli(['node', 'cli.js', '-i', jsonPath, '-o', outputFile, '-f', 'csv'], undefined, undefined, err.writable); const content = fs.readFileSync(outputFile, 'utf8'); expect(content).toContain('time,open,high,low,close,volume'); expect(content.split('\n')).toHaveLength(2); @@ -183,7 +198,7 @@ describe('CLI', () => { test('writes JSON output', async () => { await withTimeout(async () => { const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', csvPath, '-o', outputFile, '-f', 'json'], undefined, undefined, err.writable, true); + await runCli(['node', 'cli.js', '-i', csvPath, '-o', outputFile, '-f', 'json'], undefined, undefined, err.writable); const content = JSON.parse(fs.readFileSync(outputFile, 'utf8')); expect(content).toHaveLength(1); expect(content[0]).toMatchObject(expectedCandle); @@ -194,7 +209,7 @@ describe('CLI', () => { await withTimeout(async () => { const out = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', jsonPath], undefined, out.writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', jsonPath], undefined, out.writable, err.writable); const output = JSON.parse(out.getData()); expect(output).toHaveLength(1); expect(output[0]).toMatchObject(expectedCandle); @@ -207,7 +222,7 @@ describe('CLI', () => { await withTimeout(async () => { const out = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', 'nonexistent.csv'], undefined, out.writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', 'nonexistent.csv'], undefined, out.writable, err.writable); expect(err.getData()).toContain('no such file or directory'); expect(process.exitCode).toBe(1); }, 1000, 'missing file'); @@ -219,7 +234,7 @@ describe('CLI', () => { fs.writeFileSync(invalidJsonFile, '{invalid json'); const out = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', invalidJsonFile], undefined, out.writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', invalidJsonFile], undefined, out.writable, err.writable); expect(process.exitCode).toBe(1); expect(err.getData()).toMatch(/Error:/); }, 1000, 'invalid JSON'); @@ -231,7 +246,7 @@ describe('CLI', () => { fs.writeFileSync(invalidCsvFile, 'time,open,high,low,close,volume\n1,2,3,4,5'); const out = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', invalidCsvFile], undefined, out.writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', invalidCsvFile], undefined, out.writable, err.writable); expect(process.exitCode).toBe(1); expect(err.getData()).toContain('no valid OHLCV rows'); }, 1000, 'invalid CSV'); @@ -241,7 +256,7 @@ describe('CLI', () => { await withTimeout(async () => { const out = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', csvPath, '-b', 'invalid', '-n', '300'], undefined, out.writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', csvPath, '-b', 'invalid', '-n', '300'], undefined, out.writable, err.writable); expect(err.getData()).toContain('Timeframes must be valid numbers'); expect(process.exitCode).toBe(1); }, 1000, 'bad timeframe'); @@ -251,7 +266,7 @@ describe('CLI', () => { await withTimeout(async () => { const out = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', csvPath, '-b', '300', '-n', '60'], undefined, out.writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', csvPath, '-b', '300', '-n', '60'], undefined, out.writable, err.writable); expect(err.getData()).toContain('New timeframe must be greater than base timeframe'); expect(process.exitCode).toBe(1); }, 1000, 'tf relationship'); @@ -263,7 +278,7 @@ describe('CLI', () => { await withTimeout(async () => { const out = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', csvPath], undefined, out.writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', csvPath], undefined, out.writable, err.writable); const output = JSON.parse(out.getData()); expect(output).toHaveLength(1); expect(output[0]).toMatchObject(expectedCandle); @@ -274,7 +289,7 @@ describe('CLI', () => { await withTimeout(async () => { const out = captureWritable(); const err = captureWritable(); - await runCli(['node', 'cli.js', '-i', csvPath, '-b', '60', '-n', '120'], undefined, out.writable, err.writable, true); + await runCli(['node', 'cli.js', '-i', csvPath, '-b', '60', '-n', '120'], undefined, out.writable, err.writable); const output = JSON.parse(out.getData()); expect(output).toHaveLength(2); expect(output[0]).toMatchObject({ @@ -290,7 +305,7 @@ describe('CLI', () => { const out = captureWritable(); const err = captureWritable(); const stdin = readableFromString(fs.readFileSync(jsonPath, 'utf8')); - await runCli(['node', 'cli.js'], stdin, out.writable, err.writable, false); + await runCli(['node', 'cli.js'], stdin, out.writable, err.writable); expect(JSON.parse(out.getData())[0]).toMatchObject(expectedCandle); }, 1000, 'auto JSON'); }); @@ -300,7 +315,7 @@ describe('CLI', () => { const out = captureWritable(); const err = captureWritable(); const stdin = readableFromString(fs.readFileSync(csvPath, 'utf8')); - await runCli(['node', 'cli.js'], stdin, out.writable, err.writable, false); + await runCli(['node', 'cli.js'], stdin, out.writable, err.writable); expect(JSON.parse(out.getData())[0]).toMatchObject(expectedCandle); }, 1000, 'auto CSV'); }); @@ -310,7 +325,7 @@ describe('CLI', () => { const out = captureWritable(); const err = captureWritable(); const stdin = readableFromString(fs.readFileSync(jsonPath, 'utf8')); - await runCli(['node', 'cli.js', '--input-format', 'json'], stdin, out.writable, err.writable, false); + await runCli(['node', 'cli.js', '--input-format', 'json'], stdin, out.writable, err.writable); expect(JSON.parse(out.getData())[0]).toMatchObject(expectedCandle); }, 1000, 'force JSON'); }); @@ -320,7 +335,7 @@ describe('CLI', () => { const out = captureWritable(); const err = captureWritable(); const stdin = readableFromString(fs.readFileSync(jsonPath, 'utf8')); - await runCli(['node', 'cli.js', '--input-format', 'csv'], stdin, out.writable, err.writable, false); + await runCli(['node', 'cli.js', '--input-format', 'csv'], stdin, out.writable, err.writable); expect(process.exitCode).toBe(1); }, 1000, 'force CSV on JSON'); }); diff --git a/package.json b/package.json index 09dfcf8..ad65d57 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "engines": { - "node": ">=20.12.2" + "node": ">=22.12.0" }, "files": [ "dist" @@ -47,17 +47,17 @@ }, "homepage": "https://github.com/adiled/ohlc-resample#readme", "devDependencies": { - "@changesets/changelog-github": "^0.5.0", - "@changesets/cli": "^2.27.0", - "@types/lodash": "^4.14.173", - "@types/node": "^24.0.1", - "@vitest/coverage-v8": "^2.1.0", - "rimraf": "^6.0.1", - "typescript": "^5.8.3", - "vitest": "^2.1.0" + "@changesets/changelog-github": "^0.7.0", + "@changesets/cli": "^2.31.0", + "@types/lodash": "^4.17.24", + "@types/node": "^25.6.2", + "@vitest/coverage-v8": "^4.1.5", + "rimraf": "^6.1.3", + "typescript": "^6.0.3", + "vitest": "^4.1.5" }, "dependencies": { - "commander": "^14.0.0", - "lodash": "^4.17.21" + "commander": "^14.0.3", + "lodash": "^4.18.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5cedc24..96f0d38 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,53 +9,49 @@ importers: .: dependencies: commander: - specifier: ^14.0.0 - version: 14.0.0 + specifier: ^14.0.3 + version: 14.0.3 lodash: - specifier: ^4.17.21 - version: 4.17.21 + specifier: ^4.18.1 + version: 4.18.1 devDependencies: '@changesets/changelog-github': - specifier: ^0.5.0 - version: 0.5.2 + specifier: ^0.7.0 + version: 0.7.0 '@changesets/cli': - specifier: ^2.27.0 - version: 2.31.0(@types/node@24.0.1) + specifier: ^2.31.0 + version: 2.31.0(@types/node@25.6.2) '@types/lodash': - specifier: ^4.14.173 - version: 4.17.17 + specifier: ^4.17.24 + version: 4.17.24 '@types/node': - specifier: ^24.0.1 - version: 24.0.1 + specifier: ^25.6.2 + version: 25.6.2 '@vitest/coverage-v8': - specifier: ^2.1.0 - version: 2.1.9(vitest@2.1.9(@types/node@24.0.1)) + specifier: ^4.1.5 + version: 4.1.5(vitest@4.1.5) rimraf: - specifier: ^6.0.1 - version: 6.0.1 + specifier: ^6.1.3 + version: 6.1.3 typescript: - specifier: ^5.8.3 - version: 5.8.3 + specifier: ^6.0.3 + version: 6.0.3 vitest: - specifier: ^2.1.0 - version: 2.1.9(@types/node@24.0.1) + specifier: ^4.1.5 + version: 4.1.5(@types/node@25.6.2)(@vitest/coverage-v8@4.1.5)(vite@7.3.3(@types/node@25.6.2)) packages: - '@ampproject/remapping@2.3.0': - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.27.1': - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/parser@7.27.5': - resolution: {integrity: sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==} + '@babel/parser@7.29.3': + resolution: {integrity: sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==} engines: {node: '>=6.0.0'} hasBin: true @@ -63,12 +59,13 @@ packages: resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} engines: {node: '>=6.9.0'} - '@babel/types@7.27.6': - resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} - '@bcoe/v8-coverage@0.2.3': - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} '@changesets/apply-release-plan@7.1.1': resolution: {integrity: sha512-9qPCm/rLx/xoOFXIHGB229+4GOL76S4MC+7tyOuTsR6+1jYlfFDQORdvwR5hDA6y4FL2BPt3qpbcQIS+dW85LA==} @@ -79,8 +76,8 @@ packages: '@changesets/changelog-git@0.2.1': resolution: {integrity: sha512-x/xEleCFLH28c3bQeQIyeZf8lFXyDFVn1SgcBiR2Tw/r4IAWlk1fzxCEZ6NxQAjF2Nwtczoen3OA2qR+UawQ8Q==} - '@changesets/changelog-github@0.5.2': - resolution: {integrity: sha512-HeGeDl8HaIGj9fQHo/tv5XKQ2SNEi9+9yl1Bss1jttPqeiASRXhfi0A2wv8yFKCp07kR1gpOI5ge6+CWNm1jPw==} + '@changesets/changelog-github@0.7.0': + resolution: {integrity: sha512-rBsbRvc4TVn+FvFnOVM3LxlFJfTXXCp8gfVJ+0BubxWNSVnLuAzowi5j+IEraLLP52w8AAs9QfKbPS3MMiXQJA==} '@changesets/cli@2.31.0': resolution: {integrity: sha512-AhI4enNTgHu2IZr6K4WZyf0EPch4XVMn1yOMFmCD9gsfBGqMYaHXls5HyDv6/CL5axVQABz68eG30eCtbr2wFg==} @@ -95,8 +92,8 @@ packages: '@changesets/get-dependents-graph@2.1.4': resolution: {integrity: sha512-ZsS00x6WvmHq3sQv8oCMwL0f/z3wbXCVuSVTJwCnnmbC/iBdNJGFx1EcbMG4PC6sXRyH69liM4A2WKXzn/kRPg==} - '@changesets/get-github-info@0.7.0': - resolution: {integrity: sha512-+i67Bmhfj9V4KfDeS1+Tz3iF32btKZB2AAx+cYMqDSRFP7r3/ZdGbjCo+c6qkyViN9ygDuBjzageuPGJtKGe5A==} + '@changesets/get-github-info@0.8.0': + resolution: {integrity: sha512-cRnC+xdF0JIik7coko3iUP9qbnfi1iJQ3sAa6dE+Tx3+ET8bjFEm63PA4WEohgjYcmsOikPHWzPsMWWiZmntOQ==} '@changesets/get-release-plan@4.0.16': resolution: {integrity: sha512-2K5Om6CrMPm45rtvckfzWo7e9jOVCKLCnXia5eUPaURH7/LWzri7pK1TycdzAuAtehLkW7VPbWLCSExTHmiI6g==} @@ -131,141 +128,159 @@ packages: '@changesets/write@0.4.0': resolution: {integrity: sha512-CdTLvIOPiCNuH71pyDu3rA+Q0n65cmAbXnwWH84rKGiFumFzkmHNT8KHTMEchcxN+Kl8I54xGUhJ7l3E7X396Q==} - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} + '@esbuild/netbsd-arm64@0.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} + '@esbuild/openharmony-arm64@0.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -278,42 +293,15 @@ packages: '@types/node': optional: true - '@isaacs/balanced-match@4.0.1': - resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} - engines: {node: 20 || >=22} - - '@isaacs/brace-expansion@5.0.0': - resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} - engines: {node: 20 || >=22} - - '@isaacs/cliui@8.0.2': - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - - '@istanbuljs/schema@0.1.3': - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - - '@jridgewell/gen-mapping@0.3.8': - resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} - engines: {node: '>=6.0.0'} - '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} - '@jridgewell/set-array@1.2.1': - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.0': - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - '@jridgewell/sourcemap-codec@1.5.5': resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - '@jridgewell/trace-mapping@0.3.25': - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -333,10 +321,6 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - '@rollup/rollup-android-arm-eabi@4.60.3': resolution: {integrity: sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw==} cpu: [arm] @@ -371,66 +355,79 @@ packages: resolution: {integrity: sha512-DV6fJoxEYWJOvaZIsok7KrYl0tPvga5OZ2yvKHNNYyk/2roMLqQAbGhr78EQ5YhHpnhLKJD3S1WFusAkmUuV5g==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.60.3': resolution: {integrity: sha512-mQKoJAzvuOs6F+TZybQO4GOTSMUu7v0WdxEk24krQ/uUxXoPTtHjuaUuPmFhtBcM4K0ons8nrE3JyhTuCFtT/w==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.60.3': resolution: {integrity: sha512-Whjj2qoiJ6+OOJMGptTYazaJvjOJm+iKHpXQM1P3LzGjt7Ff++Tp7nH4N8J/BUA7R9IHfDyx4DJIflifwnbmIA==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.60.3': resolution: {integrity: sha512-4YTNHKqGng5+yiZt3mg77nmyuCfmNfX4fPmyUapBcIk+BdwSwmCWGXOUxhXbBEkFHtoN5boLj/5NON+u5QC9tg==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.60.3': resolution: {integrity: sha512-SU3kNlhkpI4UqlUc2VXPGK9o886ZsSeGfMAX2ba2b8DKmMXq4AL7KUrkSWVbb7koVqx41Yczx6dx5PNargIrEA==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.60.3': resolution: {integrity: sha512-6lDLl5h4TXpB1mTf2rQWnAk/LcXrx9vBfu/DT5TIPhvMhRWaZ5MxkIc8u4lJAmBo6klTe1ywXIUHFjylW505sg==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.60.3': resolution: {integrity: sha512-BMo8bOw8evlup/8G+cj5xWtPyp93xPdyoSN16Zy90Q2QZ0ZYRhCt6ZJSwbrRzG9HApFabjwj2p25TUPDWrhzqQ==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.60.3': resolution: {integrity: sha512-E0L8X1dZN1/Rph+5VPF6Xj2G7JJvMACVXtamTJIDrVI44Y3K+G8gQaMEAavbqCGTa16InptiVrX6eM6pmJ+7qA==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.60.3': resolution: {integrity: sha512-oZJ/WHaVfHUiRAtmTAeo3DcevNsVvH8mbvodjZy7D5QKvCefO371SiKRpxoDcCxB3PTRTLayWBkvmDQKTcX/sw==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.60.3': resolution: {integrity: sha512-Dhbyh7j9FybM3YaTgaHmVALwA8AkUwTPccyCQ79TG9AJUsMQqgN1DDEZNr4+QUfwiWvLDumW5vdwzoeUF+TNxQ==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.60.3': resolution: {integrity: sha512-cJd1X5XhHHlltkaypz1UcWLA8AcoIi1aWhsvaWDskD1oz2eKCypnqvTQ8ykMNI0RSmm7NkTdSqSSD7zM0xa6Ig==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.60.3': resolution: {integrity: sha512-DAZDBHQfG2oQuhY7mc6I3/qB4LU2fQCjRvxbDwd/Jdvb9fypP4IJ4qmtu6lNjes6B531AI8cg1aKC2di97bUxA==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.60.3': resolution: {integrity: sha512-cRxsE8c13mZOh3vP+wLDxpQBRrOHDIGOWyDL93Sy0Ga8y515fBcC2pjUfFwUe5T7tqvTvWbCpg1URM/AXdWIXA==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.60.3': resolution: {integrity: sha512-QaWcIgRxqEdQdhJqW4DJctsH6HCmo5vHxY0krHSX4jMtOqfzC+dqDGuHM87bu4H8JBeibWx7jFz+h6/4C8wA5Q==} @@ -462,58 +459,67 @@ packages: cpu: [x64] os: [win32] + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} - '@types/lodash@4.17.17': - resolution: {integrity: sha512-RRVJ+J3J+WmyOTqnz3PiBLA501eKwXl2noseKOrNo/6+XEHjTAxO4xHvxQB6QuNm+s4WRbn6rSiap8+EA+ykFQ==} + '@types/lodash@4.17.24': + resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} - '@types/node@24.0.1': - resolution: {integrity: sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==} + '@types/node@25.6.2': + resolution: {integrity: sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw==} - '@vitest/coverage-v8@2.1.9': - resolution: {integrity: sha512-Z2cOr0ksM00MpEfyVE8KXIYPEcBFxdbLSs56L8PO0QQMxt/6bDj45uQfxoc96v05KW3clk7vvgP0qfDit9DmfQ==} + '@vitest/coverage-v8@4.1.5': + resolution: {integrity: sha512-38C0/Ddb7HcRG0Z4/DUem8x57d2p9jYgp18mkaYswEOQBGsI1CG4f/hjm0ZCeaJfWhSZ4k7jgs29V1Zom7Ki9A==} peerDependencies: - '@vitest/browser': 2.1.9 - vitest: 2.1.9 + '@vitest/browser': 4.1.5 + vitest: 4.1.5 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@2.1.9': - resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==} + '@vitest/expect@4.1.5': + resolution: {integrity: sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==} - '@vitest/mocker@2.1.9': - resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==} + '@vitest/mocker@4.1.5': + resolution: {integrity: sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@2.1.9': - resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==} + '@vitest/pretty-format@4.1.5': + resolution: {integrity: sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==} - '@vitest/runner@2.1.9': - resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==} + '@vitest/runner@4.1.5': + resolution: {integrity: sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==} - '@vitest/snapshot@2.1.9': - resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==} + '@vitest/snapshot@4.1.5': + resolution: {integrity: sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==} - '@vitest/spy@2.1.9': - resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==} + '@vitest/spy@4.1.5': + resolution: {integrity: sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==} - '@vitest/utils@2.1.9': - resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==} + '@vitest/utils@4.1.5': + resolution: {integrity: sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==} ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} @@ -523,18 +529,6 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.1.0: - resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} - engines: {node: '>=12'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -549,8 +543,8 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + ast-v8-to-istanbul@1.0.0: + resolution: {integrity: sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==} balanced-match@4.0.4: resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} @@ -560,9 +554,6 @@ packages: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} - brace-expansion@2.0.2: - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} - brace-expansion@5.0.6: resolution: {integrity: sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==} engines: {node: 18 || 20 || >=22} @@ -571,32 +562,20 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} - - chai@5.3.3: - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} - check-error@2.1.3: - resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} - engines: {node: '>= 16'} - - color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - - color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - commander@14.0.0: - resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} + commander@14.0.3: + resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} engines: {node: '>=20'} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -604,19 +583,6 @@ packages: dataloader@1.4.0: resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} - debug@4.4.1: - resolution: {integrity: sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - deep-eql@5.0.2: - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} - engines: {node: '>=6'} - detect-indent@6.1.0: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} @@ -629,25 +595,16 @@ packages: resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} engines: {node: '>=10'} - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - enquirer@2.4.1: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} - es-module-lexer@1.7.0: - resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} - esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} + esbuild@0.27.7: + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + engines: {node: '>=18'} hasBin: true esprima@4.0.1: @@ -672,6 +629,15 @@ packages: fastq@1.20.1: resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -680,10 +646,6 @@ packages: resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} engines: {node: '>=8'} - foreground-child@3.3.1: - resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} - engines: {node: '>=14'} - fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -701,15 +663,9 @@ packages: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} - glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} - deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me - hasBin: true - - glob@11.0.3: - resolution: {integrity: sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==} - engines: {node: 20 || >=22} - hasBin: true + glob@13.0.6: + resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==} + engines: {node: 18 || 20 || >=22} globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} @@ -741,10 +697,6 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -772,20 +724,12 @@ packages: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} - istanbul-lib-source-maps@5.0.6: - resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} - engines: {node: '>=10'} - - istanbul-reports@3.1.7: - resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} - jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - - jackspeak@4.1.1: - resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} - engines: {node: 20 || >=22} + js-tokens@10.0.0: + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} js-yaml@3.14.2: resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} @@ -805,24 +749,18 @@ packages: lodash.startcase@4.4.0: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + lodash@4.18.1: + resolution: {integrity: sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==} - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - lru-cache@11.1.0: - resolution: {integrity: sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==} + lru-cache@11.3.6: + resolution: {integrity: sha512-Gf/KoL3C/MlI7Bt0PGI9I+TeTC/I6r/csU58N4BSNc4lppLBeKsOdFYkK+dX0ABDUMJNfCHTyPpzwwO21Awd3A==} engines: {node: 20 || >=22} magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - magicast@0.3.5: - resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + magicast@0.5.2: + resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} @@ -836,29 +774,18 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} - minimatch@10.0.3: - resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} - engines: {node: 20 || >=22} - minimatch@10.2.5: resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} engines: {node: 18 || 20 || >=22} - minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.12: resolution: {integrity: sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -873,6 +800,9 @@ packages: encoding: optional: true + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + outdent@0.5.0: resolution: {integrity: sha512-/jHxFIzoMXdqPzTaCpFzAAWhpkSjZPF4Vsn6jAfNpmbH/ymsmd7Qc6VE9BGn0L6YMj6uwpQLxCECpus4ukKS9Q==} @@ -910,24 +840,16 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - - path-scurry@2.0.0: - resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} - engines: {node: 20 || >=22} + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - pathe@1.1.2: - resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} - - pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} - engines: {node: '>= 14.16'} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -936,6 +858,10 @@ packages: resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} engines: {node: '>=8.6'} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -967,8 +893,8 @@ packages: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rimraf@6.0.1: - resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} + rimraf@6.1.3: + resolution: {integrity: sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==} engines: {node: 20 || >=22} hasBin: true @@ -983,8 +909,8 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - semver@7.7.2: - resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + semver@7.8.0: + resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==} engines: {node: '>=10'} hasBin: true @@ -1020,25 +946,13 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - std-env@3.10.0: - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - - string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -1051,26 +965,19 @@ packages: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} - test-exclude@7.0.2: - resolution: {integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==} - engines: {node: '>=18'} - tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@0.3.2: - resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - - tinypool@1.1.1: - resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} - engines: {node: ^18.0.0 || >=20.0.0} + tinyexec@1.1.2: + resolution: {integrity: sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA==} + engines: {node: '>=18'} - tinyrainbow@1.2.0: - resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} - engines: {node: '>=14.0.0'} + tinyglobby@0.2.16: + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} - tinyspy@3.0.2: - resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} to-regex-range@5.0.1: @@ -1080,39 +987,39 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - typescript@5.8.3: - resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==} + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} engines: {node: '>=14.17'} hasBin: true - undici-types@7.8.0: - resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} + undici-types@7.19.2: + resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==} universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} - vite-node@2.1.9: - resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - - vite@5.4.21: - resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==} - engines: {node: ^18.0.0 || >=20.0.0} + vite@7.3.3: + resolution: {integrity: sha512-/4XH147Ui7OGTjg3HbdWe5arnZQSbfuRzdr9Ec7TQi5I7R+ir0Rlc9GIvD4v0XZurELqA035KVXJXpR61xhiTA==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 lightningcss: ^1.21.0 - sass: '*' - sass-embedded: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.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 + jiti: + optional: true less: optional: true lightningcss: @@ -1127,24 +1034,44 @@ packages: optional: true terser: optional: true + tsx: + optional: true + yaml: + optional: true - vitest@2.1.9: - resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==} - engines: {node: ^18.0.0 || >=20.0.0} + vitest@4.1.5: + resolution: {integrity: sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/node': ^18.0.0 || >=20.0.0 - '@vitest/browser': 2.1.9 - '@vitest/ui': 2.1.9 + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.5 + '@vitest/browser-preview': 4.1.5 + '@vitest/browser-webdriverio': 4.1.5 + '@vitest/coverage-istanbul': 4.1.5 + '@vitest/coverage-v8': 4.1.5 + '@vitest/ui': 4.1.5 happy-dom: '*' jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true + '@opentelemetry/api': + optional: true '@types/node': optional: true - '@vitest/browser': + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/coverage-istanbul': + optional: true + '@vitest/coverage-v8': optional: true '@vitest/ui': optional: true @@ -1169,37 +1096,24 @@ packages: engines: {node: '>=8'} hasBin: true - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - snapshots: - '@ampproject/remapping@2.3.0': - dependencies: - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.27.1': {} + '@babel/helper-validator-identifier@7.28.5': {} - '@babel/parser@7.27.5': + '@babel/parser@7.29.3': dependencies: - '@babel/types': 7.27.6 + '@babel/types': 7.29.0 '@babel/runtime@7.29.2': {} - '@babel/types@7.27.6': + '@babel/types@7.29.0': dependencies: '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 - '@bcoe/v8-coverage@0.2.3': {} + '@bcoe/v8-coverage@1.0.2': {} '@changesets/apply-release-plan@7.1.1': dependencies: @@ -1215,7 +1129,7 @@ snapshots: outdent: 0.5.0 prettier: 2.8.8 resolve-from: 5.0.0 - semver: 7.7.2 + semver: 7.8.0 '@changesets/assemble-release-plan@6.0.10': dependencies: @@ -1224,21 +1138,21 @@ snapshots: '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@manypkg/get-packages': 1.1.3 - semver: 7.7.2 + semver: 7.8.0 '@changesets/changelog-git@0.2.1': dependencies: '@changesets/types': 6.1.0 - '@changesets/changelog-github@0.5.2': + '@changesets/changelog-github@0.7.0': dependencies: - '@changesets/get-github-info': 0.7.0 + '@changesets/get-github-info': 0.8.0 '@changesets/types': 6.1.0 dotenv: 8.6.0 transitivePeerDependencies: - encoding - '@changesets/cli@2.31.0(@types/node@24.0.1)': + '@changesets/cli@2.31.0(@types/node@25.6.2)': dependencies: '@changesets/apply-release-plan': 7.1.1 '@changesets/assemble-release-plan': 6.0.10 @@ -1254,7 +1168,7 @@ snapshots: '@changesets/should-skip-package': 0.1.2 '@changesets/types': 6.1.0 '@changesets/write': 0.4.0 - '@inquirer/external-editor': 1.0.3(@types/node@24.0.1) + '@inquirer/external-editor': 1.0.3(@types/node@25.6.2) '@manypkg/get-packages': 1.1.3 ansi-colors: 4.1.3 enquirer: 2.4.1 @@ -1263,7 +1177,7 @@ snapshots: package-manager-detector: 0.2.11 picocolors: 1.1.1 resolve-from: 5.0.0 - semver: 7.7.2 + semver: 7.8.0 spawndamnit: 3.0.1 term-size: 2.2.1 transitivePeerDependencies: @@ -1289,9 +1203,9 @@ snapshots: '@changesets/types': 6.1.0 '@manypkg/get-packages': 1.1.3 picocolors: 1.1.1 - semver: 7.7.2 + semver: 7.8.0 - '@changesets/get-github-info@0.7.0': + '@changesets/get-github-info@0.8.0': dependencies: dataloader: 1.4.0 node-fetch: 2.7.0 @@ -1359,117 +1273,99 @@ snapshots: human-id: 4.1.3 prettier: 2.8.8 - '@esbuild/aix-ppc64@0.21.5': + '@esbuild/aix-ppc64@0.27.7': optional: true - '@esbuild/android-arm64@0.21.5': + '@esbuild/android-arm64@0.27.7': optional: true - '@esbuild/android-arm@0.21.5': + '@esbuild/android-arm@0.27.7': optional: true - '@esbuild/android-x64@0.21.5': + '@esbuild/android-x64@0.27.7': optional: true - '@esbuild/darwin-arm64@0.21.5': + '@esbuild/darwin-arm64@0.27.7': optional: true - '@esbuild/darwin-x64@0.21.5': + '@esbuild/darwin-x64@0.27.7': optional: true - '@esbuild/freebsd-arm64@0.21.5': + '@esbuild/freebsd-arm64@0.27.7': optional: true - '@esbuild/freebsd-x64@0.21.5': + '@esbuild/freebsd-x64@0.27.7': optional: true - '@esbuild/linux-arm64@0.21.5': + '@esbuild/linux-arm64@0.27.7': optional: true - '@esbuild/linux-arm@0.21.5': + '@esbuild/linux-arm@0.27.7': optional: true - '@esbuild/linux-ia32@0.21.5': + '@esbuild/linux-ia32@0.27.7': optional: true - '@esbuild/linux-loong64@0.21.5': + '@esbuild/linux-loong64@0.27.7': optional: true - '@esbuild/linux-mips64el@0.21.5': + '@esbuild/linux-mips64el@0.27.7': optional: true - '@esbuild/linux-ppc64@0.21.5': + '@esbuild/linux-ppc64@0.27.7': optional: true - '@esbuild/linux-riscv64@0.21.5': + '@esbuild/linux-riscv64@0.27.7': optional: true - '@esbuild/linux-s390x@0.21.5': + '@esbuild/linux-s390x@0.27.7': optional: true - '@esbuild/linux-x64@0.21.5': + '@esbuild/linux-x64@0.27.7': optional: true - '@esbuild/netbsd-x64@0.21.5': + '@esbuild/netbsd-arm64@0.27.7': optional: true - '@esbuild/openbsd-x64@0.21.5': + '@esbuild/netbsd-x64@0.27.7': optional: true - '@esbuild/sunos-x64@0.21.5': + '@esbuild/openbsd-arm64@0.27.7': optional: true - '@esbuild/win32-arm64@0.21.5': + '@esbuild/openbsd-x64@0.27.7': optional: true - '@esbuild/win32-ia32@0.21.5': + '@esbuild/openharmony-arm64@0.27.7': optional: true - '@esbuild/win32-x64@0.21.5': + '@esbuild/sunos-x64@0.27.7': optional: true - '@inquirer/external-editor@1.0.3(@types/node@24.0.1)': - dependencies: - chardet: 2.1.1 - iconv-lite: 0.7.2 - optionalDependencies: - '@types/node': 24.0.1 - - '@isaacs/balanced-match@4.0.1': {} - - '@isaacs/brace-expansion@5.0.0': - dependencies: - '@isaacs/balanced-match': 4.0.1 + '@esbuild/win32-arm64@0.27.7': + optional: true - '@isaacs/cliui@8.0.2': - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 + '@esbuild/win32-ia32@0.27.7': + optional: true - '@istanbuljs/schema@0.1.3': {} + '@esbuild/win32-x64@0.27.7': + optional: true - '@jridgewell/gen-mapping@0.3.8': + '@inquirer/external-editor@1.0.3(@types/node@25.6.2)': dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 + chardet: 2.1.1 + iconv-lite: 0.7.2 + optionalDependencies: + '@types/node': 25.6.2 '@jridgewell/resolve-uri@3.1.2': {} - '@jridgewell/set-array@1.2.1': {} - - '@jridgewell/sourcemap-codec@1.5.0': {} - '@jridgewell/sourcemap-codec@1.5.5': {} - '@jridgewell/trace-mapping@0.3.25': + '@jridgewell/trace-mapping@0.3.31': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 '@manypkg/find-root@1.1.0': dependencies: @@ -1499,9 +1395,6 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - '@pkgjs/parseargs@0.11.0': - optional: true - '@rollup/rollup-android-arm-eabi@4.60.3': optional: true @@ -1577,88 +1470,86 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.60.3': optional: true + '@standard-schema/spec@1.1.0': {} + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + '@types/estree@1.0.8': {} '@types/estree@1.0.9': {} - '@types/lodash@4.17.17': {} + '@types/lodash@4.17.24': {} '@types/node@12.20.55': {} - '@types/node@24.0.1': + '@types/node@25.6.2': dependencies: - undici-types: 7.8.0 + undici-types: 7.19.2 - '@vitest/coverage-v8@2.1.9(vitest@2.1.9(@types/node@24.0.1))': + '@vitest/coverage-v8@4.1.5(vitest@4.1.5)': dependencies: - '@ampproject/remapping': 2.3.0 - '@bcoe/v8-coverage': 0.2.3 - debug: 4.4.1 + '@bcoe/v8-coverage': 1.0.2 + '@vitest/utils': 4.1.5 + ast-v8-to-istanbul: 1.0.0 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.21 - magicast: 0.3.5 - std-env: 3.10.0 - test-exclude: 7.0.2 - tinyrainbow: 1.2.0 - vitest: 2.1.9(@types/node@24.0.1) - transitivePeerDependencies: - - supports-color + istanbul-reports: 3.2.0 + magicast: 0.5.2 + obug: 2.1.1 + std-env: 4.1.0 + tinyrainbow: 3.1.0 + vitest: 4.1.5(@types/node@25.6.2)(@vitest/coverage-v8@4.1.5)(vite@7.3.3(@types/node@25.6.2)) - '@vitest/expect@2.1.9': + '@vitest/expect@4.1.5': dependencies: - '@vitest/spy': 2.1.9 - '@vitest/utils': 2.1.9 - chai: 5.3.3 - tinyrainbow: 1.2.0 + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 + chai: 6.2.2 + tinyrainbow: 3.1.0 - '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@24.0.1))': + '@vitest/mocker@4.1.5(vite@7.3.3(@types/node@25.6.2))': dependencies: - '@vitest/spy': 2.1.9 + '@vitest/spy': 4.1.5 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 5.4.21(@types/node@24.0.1) + vite: 7.3.3(@types/node@25.6.2) - '@vitest/pretty-format@2.1.9': + '@vitest/pretty-format@4.1.5': dependencies: - tinyrainbow: 1.2.0 + tinyrainbow: 3.1.0 - '@vitest/runner@2.1.9': + '@vitest/runner@4.1.5': dependencies: - '@vitest/utils': 2.1.9 - pathe: 1.1.2 + '@vitest/utils': 4.1.5 + pathe: 2.0.3 - '@vitest/snapshot@2.1.9': + '@vitest/snapshot@4.1.5': dependencies: - '@vitest/pretty-format': 2.1.9 + '@vitest/pretty-format': 4.1.5 + '@vitest/utils': 4.1.5 magic-string: 0.30.21 - pathe: 1.1.2 + pathe: 2.0.3 - '@vitest/spy@2.1.9': - dependencies: - tinyspy: 3.0.2 + '@vitest/spy@4.1.5': {} - '@vitest/utils@2.1.9': + '@vitest/utils@4.1.5': dependencies: - '@vitest/pretty-format': 2.1.9 - loupe: 3.2.1 - tinyrainbow: 1.2.0 + '@vitest/pretty-format': 4.1.5 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 ansi-colors@4.1.3: {} ansi-regex@5.0.1: {} - ansi-regex@6.1.0: {} - - ansi-styles@4.3.0: - dependencies: - color-convert: 2.0.1 - - ansi-styles@6.2.1: {} - argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -1669,7 +1560,11 @@ snapshots: assertion-error@2.0.1: {} - balanced-match@1.0.2: {} + ast-v8-to-istanbul@1.0.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + estree-walker: 3.0.3 + js-tokens: 10.0.0 balanced-match@4.0.4: {} @@ -1677,10 +1572,6 @@ snapshots: dependencies: is-windows: 1.0.2 - brace-expansion@2.0.2: - dependencies: - balanced-match: 1.0.2 - brace-expansion@5.0.6: dependencies: balanced-match: 4.0.4 @@ -1689,27 +1580,13 @@ snapshots: dependencies: fill-range: 7.1.1 - cac@6.7.14: {} - - chai@5.3.3: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.3 - deep-eql: 5.0.2 - loupe: 3.2.1 - pathval: 2.0.1 + chai@6.2.2: {} chardet@2.1.1: {} - check-error@2.1.3: {} + commander@14.0.3: {} - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - - commander@14.0.0: {} + convert-source-map@2.0.0: {} cross-spawn@7.0.6: dependencies: @@ -1719,12 +1596,6 @@ snapshots: dataloader@1.4.0: {} - debug@4.4.1: - dependencies: - ms: 2.1.3 - - deep-eql@5.0.2: {} - detect-indent@6.1.0: {} dir-glob@3.0.1: @@ -1733,44 +1604,41 @@ snapshots: dotenv@8.6.0: {} - eastasianwidth@0.2.0: {} - - emoji-regex@8.0.0: {} - - emoji-regex@9.2.2: {} - enquirer@2.4.1: dependencies: ansi-colors: 4.1.3 strip-ansi: 6.0.1 - es-module-lexer@1.7.0: {} + es-module-lexer@2.1.0: {} - esbuild@0.21.5: + esbuild@0.27.7: optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 esprima@4.0.1: {} @@ -1794,6 +1662,10 @@ snapshots: dependencies: reusify: 1.1.0 + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -1803,11 +1675,6 @@ snapshots: locate-path: 5.0.0 path-exists: 4.0.0 - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - fs-extra@7.0.1: dependencies: graceful-fs: 4.2.11 @@ -1827,23 +1694,11 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@10.4.5: - dependencies: - foreground-child: 3.3.1 - jackspeak: 3.4.3 - minimatch: 9.0.5 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 1.11.1 - - glob@11.0.3: + glob@13.0.6: dependencies: - foreground-child: 3.3.1 - jackspeak: 4.1.1 - minimatch: 10.0.3 - minipass: 7.1.2 - package-json-from-dist: 1.0.1 - path-scurry: 2.0.0 + minimatch: 10.2.5 + minipass: 7.1.3 + path-scurry: 2.0.2 globby@11.1.0: dependencies: @@ -1870,8 +1725,6 @@ snapshots: is-extglob@2.1.1: {} - is-fullwidth-code-point@3.0.0: {} - is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -1894,28 +1747,12 @@ snapshots: make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@5.0.6: - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - debug: 4.4.1 - istanbul-lib-coverage: 3.2.2 - transitivePeerDependencies: - - supports-color - - istanbul-reports@3.1.7: + istanbul-reports@3.2.0: dependencies: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 - jackspeak@3.4.3: - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - - jackspeak@4.1.1: - dependencies: - '@isaacs/cliui': 8.0.2 + js-tokens@10.0.0: {} js-yaml@3.14.2: dependencies: @@ -1936,27 +1773,23 @@ snapshots: lodash.startcase@4.4.0: {} - lodash@4.17.21: {} - - loupe@3.2.1: {} - - lru-cache@10.4.3: {} + lodash@4.18.1: {} - lru-cache@11.1.0: {} + lru-cache@11.3.6: {} magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magicast@0.3.5: + magicast@0.5.2: dependencies: - '@babel/parser': 7.27.5 - '@babel/types': 7.27.6 + '@babel/parser': 7.29.3 + '@babel/types': 7.29.0 source-map-js: 1.2.1 make-dir@4.0.0: dependencies: - semver: 7.7.2 + semver: 7.8.0 merge2@1.4.1: {} @@ -1965,30 +1798,22 @@ snapshots: braces: 3.0.3 picomatch: 2.3.2 - minimatch@10.0.3: - dependencies: - '@isaacs/brace-expansion': 5.0.0 - minimatch@10.2.5: dependencies: brace-expansion: 5.0.6 - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.2 - - minipass@7.1.2: {} + minipass@7.1.3: {} mri@1.2.0: {} - ms@2.1.3: {} - nanoid@3.3.12: {} node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 + obug@2.1.1: {} + outdent@0.5.0: {} p-filter@2.1.0: @@ -2017,26 +1842,21 @@ snapshots: path-key@3.1.1: {} - path-scurry@1.11.1: + path-scurry@2.0.2: dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - - path-scurry@2.0.0: - dependencies: - lru-cache: 11.1.0 - minipass: 7.1.2 + lru-cache: 11.3.6 + minipass: 7.1.3 path-type@4.0.0: {} - pathe@1.1.2: {} - - pathval@2.0.1: {} + pathe@2.0.3: {} picocolors@1.1.1: {} picomatch@2.3.2: {} + picomatch@4.0.4: {} + pify@4.0.1: {} postcss@8.5.14: @@ -2062,9 +1882,9 @@ snapshots: reusify@1.1.0: {} - rimraf@6.0.1: + rimraf@6.1.3: dependencies: - glob: 11.0.3 + glob: 13.0.6 package-json-from-dist: 1.0.1 rollup@4.60.3: @@ -2104,7 +1924,7 @@ snapshots: safer-buffer@2.1.2: {} - semver@7.7.2: {} + semver@7.8.0: {} shebang-command@2.0.0: dependencies: @@ -2129,28 +1949,12 @@ snapshots: stackback@0.0.2: {} - std-env@3.10.0: {} - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - string-width@5.1.2: - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 + std-env@4.1.0: {} strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.1.0 - strip-bom@3.0.0: {} supports-color@7.2.0: @@ -2159,21 +1963,16 @@ snapshots: term-size@2.2.1: {} - test-exclude@7.0.2: - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 10.4.5 - minimatch: 10.2.5 - tinybench@2.9.0: {} - tinyexec@0.3.2: {} + tinyexec@1.1.2: {} - tinypool@1.1.1: {} - - tinyrainbow@1.2.0: {} + tinyglobby@0.2.16: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 - tinyspy@3.0.2: {} + tinyrainbow@3.1.0: {} to-regex-range@5.0.1: dependencies: @@ -2181,73 +1980,51 @@ snapshots: tr46@0.0.3: {} - typescript@5.8.3: {} + typescript@6.0.3: {} - undici-types@7.8.0: {} + undici-types@7.19.2: {} universalify@0.1.2: {} - vite-node@2.1.9(@types/node@24.0.1): + vite@7.3.3(@types/node@25.6.2): dependencies: - cac: 6.7.14 - debug: 4.4.1 - es-module-lexer: 1.7.0 - pathe: 1.1.2 - vite: 5.4.21(@types/node@24.0.1) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - vite@5.4.21(@types/node@24.0.1): - dependencies: - esbuild: 0.21.5 + esbuild: 0.27.7 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 postcss: 8.5.14 rollup: 4.60.3 + tinyglobby: 0.2.16 optionalDependencies: - '@types/node': 24.0.1 + '@types/node': 25.6.2 fsevents: 2.3.3 - vitest@2.1.9(@types/node@24.0.1): - dependencies: - '@vitest/expect': 2.1.9 - '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@24.0.1)) - '@vitest/pretty-format': 2.1.9 - '@vitest/runner': 2.1.9 - '@vitest/snapshot': 2.1.9 - '@vitest/spy': 2.1.9 - '@vitest/utils': 2.1.9 - chai: 5.3.3 - debug: 4.4.1 + vitest@4.1.5(@types/node@25.6.2)(@vitest/coverage-v8@4.1.5)(vite@7.3.3(@types/node@25.6.2)): + dependencies: + '@vitest/expect': 4.1.5 + '@vitest/mocker': 4.1.5(vite@7.3.3(@types/node@25.6.2)) + '@vitest/pretty-format': 4.1.5 + '@vitest/runner': 4.1.5 + '@vitest/snapshot': 4.1.5 + '@vitest/spy': 4.1.5 + '@vitest/utils': 4.1.5 + es-module-lexer: 2.1.0 expect-type: 1.3.0 magic-string: 0.30.21 - pathe: 1.1.2 - std-env: 3.10.0 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.1.0 tinybench: 2.9.0 - tinyexec: 0.3.2 - tinypool: 1.1.1 - tinyrainbow: 1.2.0 - vite: 5.4.21(@types/node@24.0.1) - vite-node: 2.1.9(@types/node@24.0.1) + tinyexec: 1.1.2 + tinyglobby: 0.2.16 + tinyrainbow: 3.1.0 + vite: 7.3.3(@types/node@25.6.2) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 24.0.1 + '@types/node': 25.6.2 + '@vitest/coverage-v8': 4.1.5(vitest@4.1.5) transitivePeerDependencies: - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser webidl-conversions@3.0.1: {} @@ -2264,15 +2041,3 @@ snapshots: dependencies: siginfo: 2.0.0 stackback: 0.0.2 - - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 diff --git a/src/cli.ts b/src/cli.ts index ffe1382..8e95c7e 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -162,7 +162,6 @@ export async function runCli( stdin: NodeJS.ReadableStream = process.stdin, stdout: NodeJS.WritableStream = process.stdout, stderr: NodeJS.WritableStream = process.stderr, - isTTY: boolean = process.stdin.isTTY, ): Promise { const program = commanderProgram.createCommand(); program @@ -233,7 +232,10 @@ export async function runCli( } try { - const input = isTTY && options.input + // `-i` always wins. Only fall back to stdin when no input file is given. + // Don't gate on `isTTY` β€” that breaks scripted/CI invocations where stdin + // is not a TTY but `-i` is the intended source. + const input = options.input ? await readFileData(options.input) : await readPipeData(stdin); diff --git a/tsconfig.json b/tsconfig.json index 6d196d1..e4dfaae 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,16 +1,21 @@ { "compilerOptions": { - "target": "es2015", + "target": "es2022", + "lib": ["es2022"], "module": "commonjs", + "moduleResolution": "node", + "ignoreDeprecations": "6.0", "declaration": true, "sourceMap": true, "outDir": "./dist", "rootDir": "./src", "strict": true, "alwaysStrict": true, - "esModuleInterop": true + "esModuleInterop": true, + "skipLibCheck": true, + "types": ["node"] }, "include": [ "src/**/*.ts" ] -} \ No newline at end of file +} From 4246856da0e249e9f297fcf3e8c4338c3695f37c Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 18:31:11 +0500 Subject: [PATCH 27/30] =?UTF-8?q?docs(readme):=20strip=20maintainer=20sect?= =?UTF-8?q?ions=20=E2=80=94=20README=20is=20the=20marketing=20pitch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Releasing / Hosting independence / Manual release subsections were maintainer-facing and don't belong in a public-facing README. That content lives in the gitignored AGENTS.md. --- README.md | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) diff --git a/README.md b/README.md index eb6fef5..9f0f820 100644 --- a/README.md +++ b/README.md @@ -278,55 +278,6 @@ cat data.csv | ohlc-resample -o output.json ohlc-resample -i data.json -b 300 -n 3600 -f csv -o output.csv ``` -## Releasing - -Releases are driven by [Changesets](https://github.com/changesets/changesets). Any push to `main` that includes a file under `.changeset/` will trigger a release. - -1. Make a code change. -2. Add a changeset: - - `pnpm changeset` (interactive prompt), **or** hand-author a markdown file under `.changeset/` (see `.changeset/README.md` for the format). -3. Commit code + changeset, push to `main` (or merge a PR β€” both work). -4. CI consumes the changeset, bumps `package.json#version`, regenerates `CHANGELOG.md`, commits the bump back to `main` (with `[skip ci]`), then publishes to npm with provenance, tags `vX.Y.Z`, and creates a matching GitHub Release. All in one workflow run. - -Pushes without a changeset don't release. Trivial changes (typos, internal refactors that don't affect users) don't need one. - -After a release fires, your local `main` is one commit behind the bot's bump commit β€” `git pull` to catch up. - -**One-time setup before the first release:** add `NPM_TOKEN` (an npm "Granular Access Token" with read+write on this package) as a repo secret on GitHub. - -### Hosting independence - -GitHub is a convenience layer here, not a dependency. The release machinery is layered: - -| Layer | Where it lives | GitHub-specific? | -|---|---|---| -| `.changeset/*.md` files, `CHANGELOG.md`, version bumps | In the repo, managed by `@changesets/cli` (pure JS) | No | -| Publish target | npmjs.com (or any npm-compatible registry via `publishConfig.registry`) | No | -| Bot that opens "Version Packages" PRs and creates Releases | `.github/workflows/release.yml` using `changesets/action@v1` | **Yes β€” the only GitHub-specific piece** | -| Source hosting | git remote | Yes | - -To move the project off GitHub: - -1. Repoint the git remote to a new host (GitLab, Forgejo, Gitea, sourcehut, self-hosted, …). -2. Replace `.github/workflows/release.yml` with equivalent CI on that host (GitLab CI, Forgejo Actions, Drone, Jenkins, …) that runs `pnpm changeset version` on push-to-`main` and `pnpm publish` when there are no pending changesets. Or skip CI entirely and use the manual flow below. - -The `.changeset/` directory, `CHANGELOG.md` format, version-bump logic, and npm publish step are unchanged across hosts. - -### Manual release (no CI, no forge integration) - -If you want to publish from a laptop β€” because the CI is unavailable, you don't have the project on a forge yet, or you simply prefer local control: - -```sh -pnpm changeset # write a changeset describing the change (or hand-author the .md) -pnpm changeset version # bumps package.json, regenerates CHANGELOG.md, deletes consumed changesets -git commit -am "chore(release): version packages" -git tag "v$(node -p "require('./package.json').version")" -git push --follow-tags -pnpm publish --access public -``` - -Same artifacts, same CHANGELOG entries, same npm package as the automated flow. - ## Contributors πŸ‘€ **Adil Shaikh (https://adils.me)** From c899689aac3b017fc686717136da9a5940aa28bc Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 18:45:03 +0500 Subject: [PATCH 28/30] feat(dist): add install.sh + bun-compiled standalone binaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audience expansion: users no longer need Node.js to install or use the CLI. Two parallel distribution channels, both fed by the same release event: 1. npm β€” for JS/TS projects (existing) 2. install.sh + standalone binary β€” for everyone else (new) How it works - New `install.sh` at the repo root detects platform (Darwin/Linux, arm64/x64), resolves the latest release tag via GitHub's API, and downloads the matching binary to `$HOME/.local/bin/ohlc`. PATH hint emitted if the install dir isn't on PATH. Flags: `--version` to pin, `--bin-dir` to customize destination. - `release.yml` extended with a parallel `binaries` matrix job that runs only when an actual release fired. For each of darwin-arm64, darwin-x64, linux-x64, linux-arm64, and windows-x64, the matching runner installs Bun, runs `bun build --compile --target=...` against `src/cli.ts`, and uploads the resulting self-contained binary as a release asset. Each binary is ~60MB (Bun runtime is bundled). - README's Install section now leads with the curl-pipe-sh path; the npm path is listed below for library consumers. Locally verified - `bun build --compile --target=bun-darwin-arm64 src/cli.ts` produces a working 60MB binary that responds to `--version`, `--help`, pipe input, file input, all output shapes, and reads its version from the bundled package.json (single source of truth preserved). - `install.sh` syntax-checks clean (`bash -n`) and `--help` renders the documented usage. --- .changeset/working-cli-and-modern-tooling.md | 4 + .github/workflows/release.yml | 60 ++++++++++- README.md | 18 +++- install.sh | 101 +++++++++++++++++++ 4 files changed, 177 insertions(+), 6 deletions(-) create mode 100755 install.sh diff --git a/.changeset/working-cli-and-modern-tooling.md b/.changeset/working-cli-and-modern-tooling.md index 16f5e16..d1cd61c 100644 --- a/.changeset/working-cli-and-modern-tooling.md +++ b/.changeset/working-cli-and-modern-tooling.md @@ -8,6 +8,10 @@ Working CLI, vitest, modernized tooling. Closes #8. - `engines.node` bumped from `>=20.12.2` to `>=22.12.0` (current LTS floor). The runtime API surface is unchanged β€” this is purely an install-constraint update. Library consumers on Node 22+ see no behavioural difference. +**Distribution** + +- New `install.sh` for non-Node users: `curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh` installs a self-contained CLI binary (no Node.js required at install or runtime). Per-platform binaries are built via `bun build --compile` and attached to the GitHub Release: `darwin-arm64`, `darwin-x64`, `linux-x64`, `linux-arm64`, `windows-x64`. + **CLI** (was a non-functional stub in 1.x; now ships) - `--input-format ` honors the requested format (was a no-op heuristic). diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1f6bb74..3a6da3b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,8 +7,10 @@ # CLI to bump `package.json#version`, regenerate `CHANGELOG.md`, and delete # the consumed changeset files. It commits and pushes those changes to main # (with `[skip ci]` so the bot's own commit doesn't re-trigger this workflow), -# then publishes to npm with provenance, tags `vX.Y.Z`, and creates a -# matching GitHub Release. +# then publishes to npm with provenance, tags `vX.Y.Z`, creates a matching +# GitHub Release, builds standalone CLI binaries for every supported +# platform via `bun build --compile`, and uploads them as release assets so +# `install.sh` can fetch them. # # - If there are no pending changesets, the workflow exits cleanly. Nothing # to release. @@ -34,6 +36,9 @@ jobs: permissions: contents: write # push the bump commit + tag, create GH Release id-token: write # npm provenance (OIDC) + outputs: + released: ${{ steps.release.outputs.released }} + tag: ${{ steps.release.outputs.tag }} steps: - uses: actions/checkout@v4 with: @@ -41,7 +46,7 @@ jobs: - uses: pnpm/action-setup@v4 with: - version: 9 + version: 10 - uses: actions/setup-node@v4 with: @@ -50,12 +55,11 @@ jobs: registry-url: https://registry.npmjs.org - run: pnpm install --frozen-lockfile - - run: pnpm run build - - run: pnpm test - name: Apply pending changesets and publish + id: release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -68,6 +72,7 @@ jobs: if [[ -z $(git status --porcelain) ]]; then echo "No pending changesets β€” nothing to release." + echo "released=false" >> "$GITHUB_OUTPUT" exit 0 fi @@ -95,3 +100,48 @@ jobs: gh release create "${TAG}" \ --title "${TAG}" \ --notes-file /tmp/release-notes.md + + echo "released=true" >> "$GITHUB_OUTPUT" + echo "tag=${TAG}" >> "$GITHUB_OUTPUT" + + # Build standalone CLI binaries (no Node required at install time) and + # attach them to the GH Release. Runs only when the previous job actually + # released. Each platform builds natively via bun-compile. + binaries: + needs: release + if: needs.release.outputs.released == 'true' + permissions: + contents: write # upload release assets + strategy: + fail-fast: false + matrix: + include: + - { runner: macos-14, target: bun-darwin-arm64, asset: ohlc-darwin-arm64 } + - { runner: macos-13, target: bun-darwin-x64, asset: ohlc-darwin-x64 } + - { runner: ubuntu-24.04, target: bun-linux-x64, asset: ohlc-linux-x64 } + - { runner: ubuntu-24.04-arm,target: bun-linux-arm64, asset: ohlc-linux-arm64 } + - { runner: windows-2022, target: bun-windows-x64, asset: ohlc-windows-x64.exe } + runs-on: ${{ matrix.runner }} + steps: + - uses: actions/checkout@v4 + with: + ref: main # use the post-release commit so we bundle the bumped version + + - uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Compile binary + shell: bash + run: | + set -euo pipefail + bun install --frozen-lockfile + bun build --compile --target=${{ matrix.target }} src/cli.ts --outfile ${{ matrix.asset }} + ls -lh ${{ matrix.asset }} + + - name: Upload to release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + gh release upload "${{ needs.release.outputs.tag }}" "${{ matrix.asset }}" --clobber diff --git a/README.md b/README.md index 9f0f820..0eb3c4e 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,26 @@ Resample (inter-convert) trade, ticks or OHLCV data to different time frames ## Install +### CLI β€” no Node.js required + +macOS / Linux: + ```sh -npm install --save ohlc-resample +curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh ``` +Installs a self-contained binary to `~/.local/bin/ohlc`. Pin a version with `--version v2.0.0` or change the install dir with `--bin-dir /usr/local/bin`. + +Windows: download `ohlc-windows-x64.exe` from the [latest release](https://github.com/adiled/ohlc-resample/releases/latest). + +### Library β€” for Node.js / TypeScript projects + +```sh +npm install ohlc-resample # or pnpm add / yarn add / bun add +``` + +Requires Node.js β‰₯22.12. + ## Supported formats - OHLCV (CCXT format) `[[time,open,high,low,close,volume]]` diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..5770de6 --- /dev/null +++ b/install.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env sh +# Install the `ohlc` CLI on macOS or Linux. +# +# Usage: +# curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh +# curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh -s -- --bin-dir /usr/local/bin +# +# The script downloads a self-contained binary for your platform from the +# latest GitHub Release. No Node.js required. +# +# Flags: +# --version Pin a specific release tag (default: latest). +# --bin-dir Install destination (default: $HOME/.local/bin). + +set -eu + +REPO="adiled/ohlc-resample" +BIN_NAME="ohlc" +BIN_DIR="${HOME}/.local/bin" +VERSION="latest" + +while [ $# -gt 0 ]; do + case "$1" in + --version) VERSION="$2"; shift 2 ;; + --bin-dir) BIN_DIR="$2"; shift 2 ;; + -h|--help) + cat <<'USAGE' +Install the ohlc CLI (no Node.js required). + + curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh + +Flags: + --version Pin a specific release tag (default: latest) + --bin-dir Install destination (default: $HOME/.local/bin) +USAGE + exit 0 + ;; + *) printf 'unknown flag: %s\n' "$1" >&2; exit 1 ;; + esac +done + +# Detect platform +case "$(uname -s)" in + Darwin) os=darwin ;; + Linux) os=linux ;; + *) printf 'unsupported OS: %s\nFor Windows, download from https://github.com/%s/releases\n' "$(uname -s)" "$REPO" >&2; exit 1 ;; +esac + +case "$(uname -m)" in + arm64|aarch64) arch=arm64 ;; + x86_64|amd64) arch=x64 ;; + *) printf 'unsupported architecture: %s\n' "$(uname -m)" >&2; exit 1 ;; +esac + +asset="${BIN_NAME}-${os}-${arch}" + +# Resolve version β†’ tag +if [ "$VERSION" = "latest" ]; then + tag=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" \ + | sed -n 's/.*"tag_name": "\([^"]*\)".*/\1/p' | head -1) + if [ -z "$tag" ]; then + printf 'failed to resolve latest release tag\n' >&2 + exit 1 + fi +else + tag="$VERSION" +fi + +url="https://github.com/${REPO}/releases/download/${tag}/${asset}" + +printf 'β†’ Downloading %s %s for %s/%s\n' "$BIN_NAME" "$tag" "$os" "$arch" + +mkdir -p "$BIN_DIR" +tmp="$(mktemp)" +trap 'rm -f "$tmp"' EXIT + +if ! curl -fSL --progress-bar -o "$tmp" "$url"; then + printf '\nfailed to download %s\nIf the release for %s does not include a %s asset, file an issue: https://github.com/%s/issues\n' "$url" "$tag" "$asset" "$REPO" >&2 + exit 1 +fi + +dest="${BIN_DIR}/${BIN_NAME}" +mv "$tmp" "$dest" +chmod +x "$dest" +trap - EXIT + +printf 'βœ“ Installed %s to %s\n' "$BIN_NAME" "$dest" + +# PATH hint +case ":$PATH:" in + *":$BIN_DIR:"*) ;; + *) + printf '\nNote: %s is not on your PATH.\nAdd this to your shell rc:\n export PATH="%s:$PATH"\n' "$BIN_DIR" "$BIN_DIR" + ;; +esac + +# Sanity check +if [ -x "$dest" ]; then + ver="$("$dest" --version 2>/dev/null || true)" + [ -n "$ver" ] && printf '\n%s --version β†’ %s\n' "$BIN_NAME" "$ver" +fi From 43672e6bcdb3077dde4c43dfdb75c8544e323c58 Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 18:59:29 +0500 Subject: [PATCH 29/30] refactor(dist): drop bun-compile, install.sh now BYO-Nodes if needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Constraint clarified: Node is the runtime everywhere. No third-party JS runtimes (Bun, Deno, …) at dev, in CI, in shipped artifacts, or in installer-provided runtimes. Distribution model - Single source of truth: the npm package. - `install.sh` runs client-side. If the host has Node β‰₯22.12, it uses it. Otherwise it downloads the official Node binary distribution from nodejs.org into `${INSTALL_DIR}/runtime/`, then `npm install`s the package into `${INSTALL_DIR}/lib/` and writes a `${BIN_DIR}/ohlc` launcher that exec's ` "$@"`. - No per-platform binaries are built or published. Reverts - The `binaries` matrix job in release.yml (was building per-platform binaries via `bun build --compile`). - The README copy that advertised "no Node.js required." Bug fixed in install.sh during this rewrite - The bundled `npm` script's `#!/usr/bin/env node` shebang failed when `node` wasn't on `PATH`. Fix: prepend the chosen Node's bin dir to `PATH` for the install call. Verified end-to-end - Host-Node path: install.sh detected my host Node 22.17.1, npm-installed the package, launcher resolves to host Node. - BYO-Node path: with `PATH=/usr/bin:/bin` (no Node on PATH), install.sh downloaded Node 22.12.0 from nodejs.org, npm-installed the package using the bundled Node, launcher exec's the bundled Node correctly. AGENTS.md (gitignored) now documents this constraint up top so future agents don't reach for Bun (or Deno, or anything else) to solve a distribution problem. --- .changeset/working-cli-and-modern-tooling.md | 2 +- .github/workflows/release.yml | 61 +------- README.md | 8 +- install.sh | 140 +++++++++++++------ 4 files changed, 108 insertions(+), 103 deletions(-) diff --git a/.changeset/working-cli-and-modern-tooling.md b/.changeset/working-cli-and-modern-tooling.md index d1cd61c..000207e 100644 --- a/.changeset/working-cli-and-modern-tooling.md +++ b/.changeset/working-cli-and-modern-tooling.md @@ -10,7 +10,7 @@ Working CLI, vitest, modernized tooling. Closes #8. **Distribution** -- New `install.sh` for non-Node users: `curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh` installs a self-contained CLI binary (no Node.js required at install or runtime). Per-platform binaries are built via `bun build --compile` and attached to the GitHub Release: `darwin-arm64`, `darwin-x64`, `linux-x64`, `linux-arm64`, `windows-x64`. +- New `install.sh` for non-Node users: `curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh`. The installer uses your existing Node β‰₯22.12 if present; otherwise it downloads the official Node binary distribution from nodejs.org into `~/.ohlc/runtime/` and uses that. The package itself is the only release artifact β€” no per-platform binaries. **CLI** (was a non-functional stub in 1.x; now ships) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3a6da3b..17c36f7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,16 +7,19 @@ # CLI to bump `package.json#version`, regenerate `CHANGELOG.md`, and delete # the consumed changeset files. It commits and pushes those changes to main # (with `[skip ci]` so the bot's own commit doesn't re-trigger this workflow), -# then publishes to npm with provenance, tags `vX.Y.Z`, creates a matching -# GitHub Release, builds standalone CLI binaries for every supported -# platform via `bun build --compile`, and uploads them as release assets so -# `install.sh` can fetch them. +# then publishes to npm with provenance, tags `vX.Y.Z`, and creates a +# matching GitHub Release. # # - If there are no pending changesets, the workflow exits cleanly. Nothing # to release. # # All of this happens in a single workflow run from one push to main. # +# The npm tarball is the only release artifact. `install.sh` (run client-side +# by users) handles platform-specific work, including bringing a Node runtime +# along when the user doesn't have one. No per-platform binaries are built or +# uploaded. +# # One-time setup: # - In repo Settings β†’ Secrets and variables β†’ Actions, add `NPM_TOKEN` # (an npm "Granular Access Token" with read+write on this package). @@ -36,9 +39,6 @@ jobs: permissions: contents: write # push the bump commit + tag, create GH Release id-token: write # npm provenance (OIDC) - outputs: - released: ${{ steps.release.outputs.released }} - tag: ${{ steps.release.outputs.tag }} steps: - uses: actions/checkout@v4 with: @@ -59,7 +59,6 @@ jobs: - run: pnpm test - name: Apply pending changesets and publish - id: release env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} @@ -72,7 +71,6 @@ jobs: if [[ -z $(git status --porcelain) ]]; then echo "No pending changesets β€” nothing to release." - echo "released=false" >> "$GITHUB_OUTPUT" exit 0 fi @@ -100,48 +98,3 @@ jobs: gh release create "${TAG}" \ --title "${TAG}" \ --notes-file /tmp/release-notes.md - - echo "released=true" >> "$GITHUB_OUTPUT" - echo "tag=${TAG}" >> "$GITHUB_OUTPUT" - - # Build standalone CLI binaries (no Node required at install time) and - # attach them to the GH Release. Runs only when the previous job actually - # released. Each platform builds natively via bun-compile. - binaries: - needs: release - if: needs.release.outputs.released == 'true' - permissions: - contents: write # upload release assets - strategy: - fail-fast: false - matrix: - include: - - { runner: macos-14, target: bun-darwin-arm64, asset: ohlc-darwin-arm64 } - - { runner: macos-13, target: bun-darwin-x64, asset: ohlc-darwin-x64 } - - { runner: ubuntu-24.04, target: bun-linux-x64, asset: ohlc-linux-x64 } - - { runner: ubuntu-24.04-arm,target: bun-linux-arm64, asset: ohlc-linux-arm64 } - - { runner: windows-2022, target: bun-windows-x64, asset: ohlc-windows-x64.exe } - runs-on: ${{ matrix.runner }} - steps: - - uses: actions/checkout@v4 - with: - ref: main # use the post-release commit so we bundle the bumped version - - - uses: oven-sh/setup-bun@v2 - with: - bun-version: latest - - - name: Compile binary - shell: bash - run: | - set -euo pipefail - bun install --frozen-lockfile - bun build --compile --target=${{ matrix.target }} src/cli.ts --outfile ${{ matrix.asset }} - ls -lh ${{ matrix.asset }} - - - name: Upload to release - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - shell: bash - run: | - gh release upload "${{ needs.release.outputs.tag }}" "${{ matrix.asset }}" --clobber diff --git a/README.md b/README.md index 0eb3c4e..e985dbc 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Resample (inter-convert) trade, ticks or OHLCV data to different time frames ## Install -### CLI β€” no Node.js required +### CLI macOS / Linux: @@ -34,11 +34,9 @@ macOS / Linux: curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh ``` -Installs a self-contained binary to `~/.local/bin/ohlc`. Pin a version with `--version v2.0.0` or change the install dir with `--bin-dir /usr/local/bin`. +Installs the `ohlc` CLI to `~/.local/bin`. If you don't already have a recent enough Node, the installer downloads one for you and uses it. Pin a specific version with `--version 2.0.0`. -Windows: download `ohlc-windows-x64.exe` from the [latest release](https://github.com/adiled/ohlc-resample/releases/latest). - -### Library β€” for Node.js / TypeScript projects +### Library ```sh npm install ohlc-resample # or pnpm add / yarn add / bun add diff --git a/install.sh b/install.sh index 5770de6..37c96dd 100755 --- a/install.sh +++ b/install.sh @@ -1,37 +1,47 @@ #!/usr/bin/env sh # Install the `ohlc` CLI on macOS or Linux. # +# Brings its own Node.js if you don't have a recent enough one already. +# Single source of truth: the npm package. No per-platform binaries. +# # Usage: # curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh -# curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh -s -- --bin-dir /usr/local/bin -# -# The script downloads a self-contained binary for your platform from the -# latest GitHub Release. No Node.js required. # # Flags: -# --version Pin a specific release tag (default: latest). -# --bin-dir Install destination (default: $HOME/.local/bin). +# --version Pin the npm version to install (default: latest). +# --bin-dir Where to place the `ohlc` launcher (default: $HOME/.local/bin). +# --install-dir Where to place runtime + lib (default: $HOME/.ohlc). set -eu -REPO="adiled/ohlc-resample" -BIN_NAME="ohlc" +PKG=ohlc-resample +BIN_NAME=ohlc + +VERSION=latest BIN_DIR="${HOME}/.local/bin" -VERSION="latest" +INSTALL_DIR="${HOME}/.ohlc" + +# Pinned Node version we'll fetch when the host's Node is missing or too old. +# Must satisfy the package's `engines.node`. +NODE_VERSION=22.12.0 +MIN_NODE_MAJOR=22 +MIN_NODE_MINOR=12 while [ $# -gt 0 ]; do case "$1" in - --version) VERSION="$2"; shift 2 ;; - --bin-dir) BIN_DIR="$2"; shift 2 ;; + --version) VERSION="$2"; shift 2 ;; + --bin-dir) BIN_DIR="$2"; shift 2 ;; + --install-dir) INSTALL_DIR="$2"; shift 2 ;; -h|--help) cat <<'USAGE' -Install the ohlc CLI (no Node.js required). +Install the ohlc CLI. Brings its own Node.js if needed. curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh Flags: - --version Pin a specific release tag (default: latest) - --bin-dir Install destination (default: $HOME/.local/bin) + --version Pin the npm version (default: latest) + --bin-dir Launcher destination (default: $HOME/.local/bin) + --install-dir Runtime + lib destination (default: $HOME/.ohlc) USAGE exit 0 ;; @@ -41,9 +51,9 @@ done # Detect platform case "$(uname -s)" in - Darwin) os=darwin ;; - Linux) os=linux ;; - *) printf 'unsupported OS: %s\nFor Windows, download from https://github.com/%s/releases\n' "$(uname -s)" "$REPO" >&2; exit 1 ;; + Darwin) os=darwin; archive_ext=tar.gz ;; + Linux) os=linux; archive_ext=tar.xz ;; + *) printf 'unsupported OS: %s\n' "$(uname -s)" >&2; exit 1 ;; esac case "$(uname -m)" in @@ -52,39 +62,83 @@ case "$(uname -m)" in *) printf 'unsupported architecture: %s\n' "$(uname -m)" >&2; exit 1 ;; esac -asset="${BIN_NAME}-${os}-${arch}" +mkdir -p "$BIN_DIR" "$INSTALL_DIR" + +# Decide which Node to use. +NODE="" +NPM="" + +version_ge() { + # version_ge "22.12.0" "22.12" β†’ returns 0 if first β‰₯ MIN_NODE_MAJOR.MIN_NODE_MINOR + v=$1 + major=$(echo "$v" | cut -d. -f1) + minor=$(echo "$v" | cut -d. -f2) + if [ "$major" -gt "$MIN_NODE_MAJOR" ]; then return 0; fi + if [ "$major" -eq "$MIN_NODE_MAJOR" ] && [ "$minor" -ge "$MIN_NODE_MINOR" ]; then return 0; fi + return 1 +} + +if command -v node >/dev/null 2>&1; then + host_v=$(node -p 'process.versions.node' 2>/dev/null || echo "0.0.0") + if version_ge "$host_v"; then + NODE=$(command -v node) + NPM=$(command -v npm) + printf 'βœ“ Using host Node %s (%s)\n' "$host_v" "$NODE" + else + printf 'β†’ Host Node is %s, need β‰₯%d.%d. Downloading a bundled Node…\n' "$host_v" "$MIN_NODE_MAJOR" "$MIN_NODE_MINOR" + fi +fi -# Resolve version β†’ tag -if [ "$VERSION" = "latest" ]; then - tag=$(curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest" \ - | sed -n 's/.*"tag_name": "\([^"]*\)".*/\1/p' | head -1) - if [ -z "$tag" ]; then - printf 'failed to resolve latest release tag\n' >&2 +# Bring our own Node if the host's isn't suitable. +if [ -z "$NODE" ]; then + url="https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-${os}-${arch}.${archive_ext}" + printf 'β†’ Fetching %s\n' "$url" + + rt_dir="${INSTALL_DIR}/runtime" + rm -rf "$rt_dir" + mkdir -p "$rt_dir" + + tmp=$(mktemp) + trap 'rm -f "$tmp"' EXIT + if ! curl -fSL --progress-bar -o "$tmp" "$url"; then + printf 'failed to download Node %s for %s/%s\n' "$NODE_VERSION" "$os" "$arch" >&2 exit 1 fi -else - tag="$VERSION" -fi -url="https://github.com/${REPO}/releases/download/${tag}/${asset}" + tar -xf "$tmp" -C "$rt_dir" --strip-components=1 + rm "$tmp" + trap - EXIT -printf 'β†’ Downloading %s %s for %s/%s\n' "$BIN_NAME" "$tag" "$os" "$arch" + NODE="$rt_dir/bin/node" + NPM="$rt_dir/bin/npm" + printf 'βœ“ Node %s installed at %s\n' "$NODE_VERSION" "$rt_dir" +fi -mkdir -p "$BIN_DIR" -tmp="$(mktemp)" -trap 'rm -f "$tmp"' EXIT +# Install the package using whichever Node we picked. Extend PATH so npm's +# `#!/usr/bin/env node` shebang resolves to the chosen Node when it's bundled. +lib_dir="${INSTALL_DIR}/lib" +mkdir -p "$lib_dir" +[ -f "${lib_dir}/package.json" ] || printf '{"name":"ohlc-installer","private":true}\n' > "${lib_dir}/package.json" -if ! curl -fSL --progress-bar -o "$tmp" "$url"; then - printf '\nfailed to download %s\nIf the release for %s does not include a %s asset, file an issue: https://github.com/%s/issues\n' "$url" "$tag" "$asset" "$REPO" >&2 - exit 1 +if [ "$VERSION" = "latest" ]; then + spec="$PKG" +else + spec="${PKG}@${VERSION}" fi -dest="${BIN_DIR}/${BIN_NAME}" -mv "$tmp" "$dest" -chmod +x "$dest" -trap - EXIT +printf 'β†’ Installing %s into %s\n' "$spec" "$lib_dir" +node_bin_dir=$(dirname "$NODE") +PATH="${node_bin_dir}:${PATH}" "$NPM" install --prefix "$lib_dir" "$spec" --silent --no-audit --no-fund --no-progress + +# Write the launcher. +launcher="${BIN_DIR}/${BIN_NAME}" +cat > "$launcher" </dev/null || true)" - [ -n "$ver" ] && printf '\n%s --version β†’ %s\n' "$BIN_NAME" "$ver" +if [ -x "$launcher" ]; then + v="$("$launcher" --version 2>/dev/null || true)" + [ -n "$v" ] && printf '\n%s --version β†’ %s\n' "$BIN_NAME" "$v" fi From f705ea4a704c50eb32e9e67ddf428b6d8de5781c Mon Sep 17 00:00:00 2001 From: Adil Date: Sat, 9 May 2026 23:07:16 +0500 Subject: [PATCH 30/30] feat(install): add --uninstall mode Same script, two modes. Uninstall removes the launcher (`$BIN_DIR/ohlc`) and the install dir (`$INSTALL_DIR`, runtime + lib). Both removals are gated by sanity checks: the launcher must reference our package's `cli.js`; the install dir must contain `lib/node_modules/$PKG` or a `runtime/` we wrote. Pass `--force` to override the gate. Verified locally: - Real install + --uninstall round-trip cleanly removes everything. - A planted foreign launcher and unrelated dir are refused without --force; --force removes them. - Re-running --uninstall on an empty target is a clean no-op. README updated with the uninstall one-liner under the Install section. AGENTS.md notes the safety gate. --- README.md | 6 ++++++ install.sh | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e985dbc..ea279d1 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,12 @@ curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh Installs the `ohlc` CLI to `~/.local/bin`. If you don't already have a recent enough Node, the installer downloads one for you and uses it. Pin a specific version with `--version 2.0.0`. +To uninstall: + +```sh +curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh -s -- --uninstall +``` + ### Library ```sh diff --git a/install.sh b/install.sh index 37c96dd..18c8bb2 100755 --- a/install.sh +++ b/install.sh @@ -1,25 +1,33 @@ #!/usr/bin/env sh -# Install the `ohlc` CLI on macOS or Linux. +# Install (or uninstall) the `ohlc` CLI on macOS or Linux. # # Brings its own Node.js if you don't have a recent enough one already. # Single source of truth: the npm package. No per-platform binaries. # # Usage: # curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh +# curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh -s -- --uninstall # -# Flags: +# Install flags: # --version Pin the npm version to install (default: latest). # --bin-dir Where to place the `ohlc` launcher (default: $HOME/.local/bin). # --install-dir Where to place runtime + lib (default: $HOME/.ohlc). +# +# Uninstall flags: +# --uninstall Remove the launcher and the install dir. +# --force Remove the directories even if they don't look like +# this installer wrote them. set -eu PKG=ohlc-resample BIN_NAME=ohlc +MODE=install VERSION=latest BIN_DIR="${HOME}/.local/bin" INSTALL_DIR="${HOME}/.ohlc" +FORCE=0 # Pinned Node version we'll fetch when the host's Node is missing or too old. # Must satisfy the package's `engines.node`. @@ -32,16 +40,26 @@ while [ $# -gt 0 ]; do --version) VERSION="$2"; shift 2 ;; --bin-dir) BIN_DIR="$2"; shift 2 ;; --install-dir) INSTALL_DIR="$2"; shift 2 ;; + --uninstall) MODE=uninstall; shift ;; + --force) FORCE=1; shift ;; -h|--help) cat <<'USAGE' -Install the ohlc CLI. Brings its own Node.js if needed. +Install (or uninstall) the ohlc CLI. Brings its own Node.js if needed. +Install: curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh -Flags: +Uninstall: + curl -fsSL https://github.com/adiled/ohlc-resample/raw/main/install.sh | sh -s -- --uninstall + +Install flags: --version Pin the npm version (default: latest) --bin-dir Launcher destination (default: $HOME/.local/bin) --install-dir Runtime + lib destination (default: $HOME/.ohlc) + +Uninstall flags: + --uninstall Switch to uninstall mode + --force Remove dirs even if they don't look like this installer wrote them USAGE exit 0 ;; @@ -62,6 +80,40 @@ case "$(uname -m)" in *) printf 'unsupported architecture: %s\n' "$(uname -m)" >&2; exit 1 ;; esac +# ---- Uninstall ---- +if [ "$MODE" = "uninstall" ]; then + launcher="${BIN_DIR}/${BIN_NAME}" + removed_any=0 + + if [ -e "$launcher" ]; then + # Sanity check: is it our launcher? Our launcher refs the package path. + if [ "$FORCE" -eq 1 ] || grep -q "node_modules/${PKG}/dist/cli.js" "$launcher" 2>/dev/null; then + rm -f "$launcher" + printf 'βœ“ Removed launcher %s\n' "$launcher" + removed_any=1 + else + printf 'Refusing to remove %s (does not look like our launcher).\nPass --force to override.\n' "$launcher" >&2 + fi + fi + + if [ -d "$INSTALL_DIR" ]; then + # Sanity check: does it look like our install dir? + if [ "$FORCE" -eq 1 ] || [ -d "${INSTALL_DIR}/lib/node_modules/${PKG}" ] || [ -d "${INSTALL_DIR}/runtime" ]; then + rm -rf "$INSTALL_DIR" + printf 'βœ“ Removed install dir %s\n' "$INSTALL_DIR" + removed_any=1 + else + printf 'Refusing to remove %s (does not look like our install dir).\nPass --force to override.\n' "$INSTALL_DIR" >&2 + fi + fi + + if [ "$removed_any" -eq 0 ]; then + printf 'Nothing to uninstall (no launcher at %s and no install dir at %s).\n' "$launcher" "$INSTALL_DIR" + fi + exit 0 +fi + +# ---- Install ---- mkdir -p "$BIN_DIR" "$INSTALL_DIR" # Decide which Node to use.