From de9fa6bf9959b365ddc89e071dacfd8b10810d22 Mon Sep 17 00:00:00 2001 From: Mihhail Solovjov Date: Wed, 18 Mar 2026 19:26:12 +0200 Subject: [PATCH 1/5] perf(filesystem): add async parallel directory scanning for package.json files Introduces findAllPackageJsonFilesAsync with bounded parallel directory traversal to improve scanning performance for large repositories. Uses configurable concurrency (default 16, max 64) with proper timeout handling via Promise.race. The existing synchronous function is updated with throttled progress reporting to reduce overhead. --- src/core/package-detector.ts | 42 ++++--- src/utils/filesystem.ts | 184 ++++++++++++++++++++++++++++- test/unit/utils/filesystem.test.ts | 108 ++++++++++++++++- 3 files changed, 317 insertions(+), 17 deletions(-) diff --git a/src/core/package-detector.ts b/src/core/package-detector.ts index dce063d..e93c686 100644 --- a/src/core/package-detector.ts +++ b/src/core/package-detector.ts @@ -3,7 +3,7 @@ import { PackageInfo, PackageJson, UpgradeOptions } from '../types' import { findPackageJson, readPackageJson, - findAllPackageJsonFiles, + findAllPackageJsonFilesAsync, collectAllDependenciesAsync, findClosestMinorVersion, } from '../utils' @@ -45,7 +45,7 @@ export class PackageDetector { // Always check all package.json files recursively with timeout protection this.showProgress('🔍 Scanning repository for package.json files...') const tScan = Date.now() - const allPackageJsonFiles = this.findPackageJsonFilesWithTimeout(30000) // 30 second timeout + const allPackageJsonFiles = await this.findPackageJsonFilesWithTimeout(30000) // 30 second timeout debugLog.perf('PackageDetector', `file scan (${allPackageJsonFiles.length} files)`, tScan, { files: allPackageJsonFiles, }) @@ -222,20 +222,34 @@ export class PackageDetector { } } - private findPackageJsonFilesWithTimeout(timeoutMs: number): string[] { - // Synchronous file search with depth limiting and symlink protection - // The timeout parameter is kept for future async implementation + private async findPackageJsonFilesWithTimeout(timeoutMs: number): Promise { try { - return findAllPackageJsonFiles( - this.cwd, - this.excludePatterns, - 10, - (currentDir: string, foundCount: number) => { - // Show scanning progress with current directory and count - const truncatedDir = currentDir.length > 50 ? '...' + currentDir.slice(-47) : currentDir - this.showProgress(`🔍 Scanning ${truncatedDir} (found ${foundCount})`) + let timeoutId: NodeJS.Timeout | undefined + + try { + return await Promise.race([ + findAllPackageJsonFilesAsync( + this.cwd, + this.excludePatterns, + 10, + (currentDir: string, foundCount: number) => { + // Show scanning progress with current directory and count + const truncatedDir = currentDir.length > 50 ? '...' + currentDir.slice(-47) : currentDir + this.showProgress(`🔍 Scanning ${truncatedDir} (found ${foundCount})`) + } + ), + new Promise((_, reject) => { + timeoutId = setTimeout(() => { + reject(new Error(`Scan timed out after ${timeoutMs}ms`)) + }, timeoutMs) + timeoutId.unref?.() + }), + ]) + } finally { + if (timeoutId) { + clearTimeout(timeoutId) } - ) + } } catch (err) { throw new Error( `Failed to scan for package.json files: ${err}. Try using --exclude patterns to skip problematic directories.` diff --git a/src/utils/filesystem.ts b/src/utils/filesystem.ts index 7f2d4cc..47ebc14 100644 --- a/src/utils/filesystem.ts +++ b/src/utils/filesystem.ts @@ -59,6 +59,10 @@ export interface CollectDependenciesOptions { includeOptionalDeps?: boolean } +export interface PackageJsonScanOptions { + concurrency?: number +} + /** * Collects all dependencies from multiple package.json files. * Always includes regular dependencies and devDependencies. @@ -164,6 +168,8 @@ export function findAllPackageJsonFiles( const packageJsonFiles: string[] = [] const visitedPaths = new Set() let directoriesScanned = 0 + let lastProgressAt = 0 + const progressIntervalMs = 250 // Compile regex patterns for exclude filtering const excludeRegexes = excludePatterns.map((pattern) => new RegExp(pattern, 'i')) @@ -172,6 +178,19 @@ export function findAllPackageJsonFiles( return excludeRegexes.some((regex) => regex.test(relativePath)) } + function reportProgress(currentDir: string, force: boolean = false): void { + if (!onProgress) return + + const now = Date.now() + if (!force && now - lastProgressAt < progressIntervalMs) { + return + } + + lastProgressAt = now + const relativePath = relative(rootDir, currentDir) || '.' + onProgress(relativePath, packageJsonFiles.length) + } + function traverseDirectory(dir: string, depth: number = 0): void { // Prevent infinite recursion with depth limit if (depth > maxDepth) { @@ -190,13 +209,13 @@ export function findAllPackageJsonFiles( // Report progress every 10 directories or on first scan if (onProgress && (directoriesScanned % 10 === 0 || directoriesScanned === 1)) { - const relativePath = relative(rootDir, dir) || '.' - onProgress(relativePath, packageJsonFiles.length) + reportProgress(dir, true) } const files = readdirSync(dir) for (const file of files) { + reportProgress(dir) const fullPath = join(dir, file) const relativePath = relative(rootDir, fullPath) @@ -246,3 +265,164 @@ export function findAllPackageJsonFiles( traverseDirectory(rootDir) return packageJsonFiles } + +/** + * Find all package.json files recursively with bounded parallel directory traversal. + */ +export async function findAllPackageJsonFilesAsync( + rootDir: string = process.cwd(), + excludePatterns: string[] = [], + maxDepth: number = 10, + onProgress?: (current: string, found: number) => void, + options: PackageJsonScanOptions = {} +): Promise { + const packageJsonFiles: string[] = [] + const visitedPaths = new Set() + let directoriesScanned = 0 + let lastProgressAt = 0 + const progressIntervalMs = 250 + const concurrency = Math.max(1, Math.min(options.concurrency ?? 16, 64)) + + const excludeRegexes = excludePatterns.map((pattern) => new RegExp(pattern, 'i')) + + function shouldExcludePath(relativePath: string): boolean { + return excludeRegexes.some((regex) => regex.test(relativePath)) + } + + function reportProgress(currentDir: string, force: boolean = false): void { + if (!onProgress) return + + const now = Date.now() + if (!force && now - lastProgressAt < progressIntervalMs) { + return + } + + lastProgressAt = now + const relativePath = relative(rootDir, currentDir) || '.' + onProgress(relativePath, packageJsonFiles.length) + } + + const pending: Array<{ dir: string; depth: number }> = [] + let activeTasks = 0 + let failedError: unknown = null + let resolveDone: (() => void) | null = null + let rejectDone: ((error: unknown) => void) | null = null + + const done = new Promise((resolve, reject) => { + resolveDone = resolve + rejectDone = reject + }) + + function finishIfIdle(): void { + if (pending.length === 0 && activeTasks === 0) { + resolveDone?.() + } + } + + function schedule(dir: string, depth: number): void { + pending.push({ dir, depth }) + pump() + } + + async function processDirectory(dir: string, depth: number): Promise { + if (depth > maxDepth) { + return + } + + let realPath: string + try { + realPath = await fsPromises.realpath(dir) + } catch { + return + } + + if (visitedPaths.has(realPath)) { + return + } + visitedPaths.add(realPath) + + directoriesScanned++ + if (directoriesScanned % 10 === 0 || directoriesScanned === 1) { + reportProgress(dir, true) + } + + let files: string[] + try { + files = await fsPromises.readdir(dir) + } catch { + return + } + + for (const file of files) { + reportProgress(dir) + + const fullPath = join(dir, file) + const relativePath = relative(rootDir, fullPath) + + if (shouldExcludePath(relativePath)) { + continue + } + + let stat + try { + stat = await fsPromises.stat(fullPath) + } catch { + continue + } + + const skipDirs = [ + 'node_modules', + '.git', + 'dist', + 'build', + '.next', + 'coverage', + '.cache', + 'out', + '.output', + '.nuxt', + '.vercel', + '.netlify', + 'lib', + 'es', + 'esm', + 'cjs', + ] + + if (stat.isDirectory() && !file.startsWith('.') && !skipDirs.includes(file)) { + schedule(fullPath, depth + 1) + } else if (file === 'package.json' && stat.isFile()) { + packageJsonFiles.push(fullPath) + } + } + } + + function pump(): void { + while (activeTasks < concurrency && pending.length > 0 && !failedError) { + const next = pending.shift() + if (!next) break + + activeTasks++ + void processDirectory(next.dir, next.depth) + .catch((error) => { + if (!failedError) { + failedError = error + rejectDone?.(error) + } + }) + .finally(() => { + activeTasks-- + if (failedError) { + return + } + pump() + finishIfIdle() + }) + } + } + + schedule(rootDir, 0) + await done + + return packageJsonFiles +} diff --git a/test/unit/utils/filesystem.test.ts b/test/unit/utils/filesystem.test.ts index 8684ad9..3e4829e 100644 --- a/test/unit/utils/filesystem.test.ts +++ b/test/unit/utils/filesystem.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, beforeEach, afterEach } from 'vitest' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { mkdirSync, writeFileSync, rmSync, existsSync, mkdtempSync } from 'fs' import { join } from 'path' import { tmpdir } from 'os' @@ -9,6 +9,7 @@ import { collectAllDependencies, collectAllDependenciesAsync, findAllPackageJsonFiles, + findAllPackageJsonFilesAsync, findWorkspaceRoot, } from '../../../src/utils/filesystem' @@ -295,6 +296,34 @@ describe('filesystem utils', () => { expect(progressCalls.length).toBeGreaterThan(0) }) + it('should keep reporting progress while scanning a large directory', () => { + writeFileSync(join(testDir, 'package.json'), '{}') + + const largeDir = join(testDir, 'large-dir') + mkdirSync(largeDir, { recursive: true }) + for (let i = 0; i < 20; i++) { + writeFileSync(join(largeDir, `file-${i}.txt`), 'content') + } + + const progressCalls: Array<{ current: string; found: number }> = [] + let now = 0 + const dateNowSpy = vi.spyOn(Date, 'now').mockImplementation(() => { + now += 100 + return now + }) + + try { + findAllPackageJsonFiles(testDir, [], 10, (current, found) => { + progressCalls.push({ current, found }) + }) + } finally { + dateNowSpy.mockRestore() + } + + expect(progressCalls.length).toBeGreaterThan(1) + expect(progressCalls.some((call) => call.current === 'large-dir')).toBe(true) + }) + it('should respect max depth limit', () => { // Create deeply nested structure let currentDir = testDir @@ -311,6 +340,83 @@ describe('filesystem utils', () => { }) }) + describe('findAllPackageJsonFilesAsync()', () => { + it('should find package.json files recursively', async () => { + writeFileSync(join(testDir, 'package.json'), '{}') + + const packagesDir = join(testDir, 'packages') + mkdirSync(join(packagesDir, 'pkg-a'), { recursive: true }) + mkdirSync(join(packagesDir, 'pkg-b'), { recursive: true }) + + writeFileSync(join(packagesDir, 'pkg-a', 'package.json'), '{}') + writeFileSync(join(packagesDir, 'pkg-b', 'package.json'), '{}') + + const result = await findAllPackageJsonFilesAsync(testDir) + + expect(result).toHaveLength(3) + expect(result).toContain(join(testDir, 'package.json')) + expect(result).toContain(join(packagesDir, 'pkg-a', 'package.json')) + expect(result).toContain(join(packagesDir, 'pkg-b', 'package.json')) + }) + + it('should skip node_modules directories and exclude patterns', async () => { + writeFileSync(join(testDir, 'package.json'), '{}') + + const nodeModulesDir = join(testDir, 'node_modules', 'some-package') + const excludedDir = join(testDir, 'skip-me') + mkdirSync(nodeModulesDir, { recursive: true }) + mkdirSync(excludedDir, { recursive: true }) + + writeFileSync(join(nodeModulesDir, 'package.json'), '{}') + writeFileSync(join(excludedDir, 'package.json'), '{}') + + const result = await findAllPackageJsonFilesAsync(testDir, ['^skip-me']) + + expect(result).toEqual([join(testDir, 'package.json')]) + }) + + it('should call progress callback while scanning large directories', async () => { + writeFileSync(join(testDir, 'package.json'), '{}') + + const largeDir = join(testDir, 'large-dir') + mkdirSync(largeDir, { recursive: true }) + for (let i = 0; i < 20; i++) { + writeFileSync(join(largeDir, `file-${i}.txt`), 'content') + } + + const progressCalls: Array<{ current: string; found: number }> = [] + let now = 0 + const dateNowSpy = vi.spyOn(Date, 'now').mockImplementation(() => { + now += 100 + return now + }) + + try { + await findAllPackageJsonFilesAsync(testDir, [], 10, (current, found) => { + progressCalls.push({ current, found }) + }) + } finally { + dateNowSpy.mockRestore() + } + + expect(progressCalls.length).toBeGreaterThan(1) + expect(progressCalls.some((call) => call.current === 'large-dir')).toBe(true) + }) + + it('should respect max depth limit', async () => { + let currentDir = testDir + for (let i = 0; i < 15; i++) { + currentDir = join(currentDir, `level-${i}`) + mkdirSync(currentDir, { recursive: true }) + writeFileSync(join(currentDir, 'package.json'), '{}') + } + + const result = await findAllPackageJsonFilesAsync(testDir, [], 5) + + expect(result.length).toBeLessThan(15) + }) + }) + describe('findWorkspaceRoot()', () => { it('should find workspace root with pnpm', () => { writeFileSync( From 0e6da7032a0c75cfdbb8eacdcd502cec9bc6eae6 Mon Sep 17 00:00:00 2001 From: Mihhail Solovjov Date: Wed, 18 Mar 2026 19:27:02 +0200 Subject: [PATCH 2/5] refactor(filesystem): extract skip directory logic into reusable function Added SKIP_DIRS constant and shouldSkipDirectory() helper to consolidate directory skipping logic. Replaced inline skipDirs arrays in findAllPackageJsonFiles and findAllPackageJsonFilesAsync. Added tests for hidden directory skipping. --- src/utils/filesystem.ts | 58 ++++++++++-------------------- test/unit/utils/filesystem.test.ts | 24 +++++++++++++ 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/utils/filesystem.ts b/src/utils/filesystem.ts index 47ebc14..7ff62c1 100644 --- a/src/utils/filesystem.ts +++ b/src/utils/filesystem.ts @@ -63,6 +63,22 @@ export interface PackageJsonScanOptions { concurrency?: number } +const SKIP_DIRS = new Set([ + 'node_modules', + 'dist', + 'build', + 'coverage', + 'out', + 'lib', + 'es', + 'esm', + 'cjs', +]) + +function shouldSkipDirectory(name: string): boolean { + return name.startsWith('.') || SKIP_DIRS.has(name) +} + /** * Collects all dependencies from multiple package.json files. * Always includes regular dependencies and devDependencies. @@ -232,26 +248,7 @@ export function findAllPackageJsonFiles( continue } - // Skip common build and dependency directories - const skipDirs = [ - 'node_modules', - '.git', - 'dist', - 'build', - '.next', - 'coverage', - '.cache', - 'out', - '.output', - '.nuxt', - '.vercel', - '.netlify', - 'lib', - 'es', - 'esm', - 'cjs', - ] - if (stat.isDirectory() && !file.startsWith('.') && !skipDirs.includes(file)) { + if (stat.isDirectory() && !shouldSkipDirectory(file)) { traverseDirectory(fullPath, depth + 1) } else if (file === 'package.json' && stat.isFile()) { packageJsonFiles.push(fullPath) @@ -370,26 +367,7 @@ export async function findAllPackageJsonFilesAsync( continue } - const skipDirs = [ - 'node_modules', - '.git', - 'dist', - 'build', - '.next', - 'coverage', - '.cache', - 'out', - '.output', - '.nuxt', - '.vercel', - '.netlify', - 'lib', - 'es', - 'esm', - 'cjs', - ] - - if (stat.isDirectory() && !file.startsWith('.') && !skipDirs.includes(file)) { + if (stat.isDirectory() && !shouldSkipDirectory(file)) { schedule(fullPath, depth + 1) } else if (file === 'package.json' && stat.isFile()) { packageJsonFiles.push(fullPath) diff --git a/test/unit/utils/filesystem.test.ts b/test/unit/utils/filesystem.test.ts index 3e4829e..57f6bdb 100644 --- a/test/unit/utils/filesystem.test.ts +++ b/test/unit/utils/filesystem.test.ts @@ -266,6 +266,18 @@ describe('filesystem utils', () => { expect(result[0]).toBe(join(testDir, 'package.json')) }) + it('should skip hidden directories', () => { + writeFileSync(join(testDir, 'package.json'), '{}') + + const hiddenDir = join(testDir, '.turbo', 'nested-package') + mkdirSync(hiddenDir, { recursive: true }) + writeFileSync(join(hiddenDir, 'package.json'), '{}') + + const result = findAllPackageJsonFiles(testDir) + + expect(result).toEqual([join(testDir, 'package.json')]) + }) + it('should skip directories matching exclude patterns', () => { writeFileSync(join(testDir, 'package.json'), '{}') @@ -375,6 +387,18 @@ describe('filesystem utils', () => { expect(result).toEqual([join(testDir, 'package.json')]) }) + it('should skip hidden directories', async () => { + writeFileSync(join(testDir, 'package.json'), '{}') + + const hiddenDir = join(testDir, '.turbo', 'nested-package') + mkdirSync(hiddenDir, { recursive: true }) + writeFileSync(join(hiddenDir, 'package.json'), '{}') + + const result = await findAllPackageJsonFilesAsync(testDir) + + expect(result).toEqual([join(testDir, 'package.json')]) + }) + it('should call progress callback while scanning large directories', async () => { writeFileSync(join(testDir, 'package.json'), '{}') From d2a9e11ce2bdd8c05b6f6fd7085bb73152811279 Mon Sep 17 00:00:00 2001 From: Mihhail Solovjov Date: Wed, 18 Mar 2026 19:36:26 +0200 Subject: [PATCH 3/5] feat(cli): add --max-depth option to control package.json scan depth Allow users to configure the maximum directory depth for package.json discovery via --max-depth CLI flag. Defaults to 10 if not specified. Also added validation to ensure the value is a non-negative integer. --- README.md | 9 +++++++++ src/cli.ts | 15 ++++++++++++--- src/core/package-detector.ts | 7 +++++-- src/types.ts | 1 + 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bc2f0e1..09b97a5 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,12 @@ Upgrade your dependencies interactively. Works with npm, yarn, pnpm, and bun. npx inup ``` +Scan deeper package layouts: + +```bash +npx inup --max-depth 15 +``` + Or install globally: ```bash @@ -50,7 +56,10 @@ inup [options] -d, --dir Run in specific directory -e, --exclude Skip directories (comma-separated regex) +-i, --ignore Ignore packages (comma-separated, glob supported) +--max-depth Maximum scan depth for package discovery (default: 10) --package-manager Force package manager (npm, yarn, pnpm, bun) +--debug Write verbose debug logs ``` ## 🔒 Privacy diff --git a/src/cli.ts b/src/cli.ts index 2084b98..ccd11eb 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -21,14 +21,12 @@ program .option('-d, --dir ', 'specify directory to run in', process.cwd()) .option('-e, --exclude ', 'exclude paths matching regex patterns (comma-separated)', '') .option('-i, --ignore ', 'ignore packages (comma-separated, supports glob patterns like @babel/*)') + .option('--max-depth ', 'maximum directory depth for package.json discovery', '10') .option('--package-manager ', 'manually specify package manager (npm, yarn, pnpm, bun)') .option('--debug', 'write verbose debug log to /tmp/inup-debug-YYYY-MM-DD.log') .action(async (options) => { console.log(chalk.bold.blue(`🚀 `) + chalk.bold.red(`i`) + chalk.bold.yellow(`n`) + chalk.bold.blue(`u`) + chalk.bold.magenta(`p`) + `\n`) - // Check for updates in the background (non-blocking) - const updateCheckPromise = checkForUpdateAsync('inup', packageJson.version) - const cwd = resolve(options.dir) if (options.debug || process.env.INUP_DEBUG === '1') { @@ -56,6 +54,16 @@ program : [] const ignorePackages = [...new Set([...cliIgnorePatterns, ...(projectConfig.ignore || [])])] + const maxDepth = Number.parseInt(options.maxDepth, 10) + if (!Number.isInteger(maxDepth) || maxDepth < 0) { + console.error(chalk.red(`Invalid max depth: ${options.maxDepth}`)) + console.error(chalk.yellow('Expected a non-negative integer, for example: --max-depth 10')) + process.exit(1) + } + + // Check for updates in the background (non-blocking) + const updateCheckPromise = checkForUpdateAsync('inup', packageJson.version) + // Validate package manager if provided let packageManager: PackageManager | undefined if (options.packageManager) { @@ -71,6 +79,7 @@ program const upgrader = new UpgradeRunner({ cwd, excludePatterns, + maxDepth, ignorePackages, packageManager, debug: options.debug || process.env.INUP_DEBUG === '1', diff --git a/src/core/package-detector.ts b/src/core/package-detector.ts index e93c686..aa8004e 100644 --- a/src/core/package-detector.ts +++ b/src/core/package-detector.ts @@ -18,11 +18,13 @@ export class PackageDetector { private cwd: string private excludePatterns: string[] private ignorePackages: string[] + private maxDepth: number constructor(options?: UpgradeOptions) { this.cwd = options?.cwd || process.cwd() this.excludePatterns = options?.excludePatterns || [] this.ignorePackages = options?.ignorePackages || [] + this.maxDepth = options?.maxDepth ?? 10 this.packageJsonPath = findPackageJson(this.cwd) if (this.packageJsonPath) { this.packageJson = readPackageJson(this.packageJsonPath) @@ -231,10 +233,11 @@ export class PackageDetector { findAllPackageJsonFilesAsync( this.cwd, this.excludePatterns, - 10, + this.maxDepth, (currentDir: string, foundCount: number) => { // Show scanning progress with current directory and count - const truncatedDir = currentDir.length > 50 ? '...' + currentDir.slice(-47) : currentDir + const truncatedDir = + currentDir.length > 50 ? '...' + currentDir.slice(-47) : currentDir this.showProgress(`🔍 Scanning ${truncatedDir} (found ${foundCount})`) } ), diff --git a/src/types.ts b/src/types.ts index 7f8a228..2894824 100644 --- a/src/types.ts +++ b/src/types.ts @@ -70,6 +70,7 @@ export interface PackageManagerInfo { export interface UpgradeOptions { cwd?: string excludePatterns?: string[] + maxDepth?: number // Maximum package.json scan depth, defaults to 10 packageManager?: PackageManager // Manual override for package manager ignorePackages?: string[] // Package names/patterns to ignore (from .inuprc or --ignore flag) debug?: boolean // Write verbose debug log to /tmp/inup-debug-YYYY-MM-DD.log From f5979e65b32de233a3f512b789b1a8573efd2dc8 Mon Sep 17 00:00:00 2001 From: Mihhail Solovjov Date: Wed, 18 Mar 2026 19:37:46 +0200 Subject: [PATCH 4/5] build(deps): update @types/node to ^24.12.0 --- package.json | 2 +- pnpm-lock.yaml | 178 ++++++++++++++++++++++++------------------------- 2 files changed, 90 insertions(+), 90 deletions(-) diff --git a/package.json b/package.json index 5fb47da..b7135bd 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "devDependencies": { "@types/inquirer": "^9.0.9", "@types/keypress.js": "^2.1.3", - "@types/node": "^24.10.1", + "@types/node": "^24.12.0", "@types/semver": "^7.7.1", "@vitest/coverage-v8": "^3.2.4", "prettier": "^3.8.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6a4f7bd..2adcb45 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,7 +19,7 @@ importers: version: 4.0.0 inquirer: specifier: ^13.3.2 - version: 13.3.2(@types/node@24.10.1) + version: 13.3.2(@types/node@24.12.0) keypress: specifier: ^0.2.1 version: 0.2.1 @@ -40,14 +40,14 @@ importers: specifier: ^2.1.3 version: 2.1.3 '@types/node': - specifier: ^24.10.1 - version: 24.10.1 + specifier: ^24.12.0 + version: 24.12.0 '@types/semver': specifier: ^7.7.1 version: 7.7.1 '@vitest/coverage-v8': specifier: ^3.2.4 - version: 3.2.4(vitest@3.2.4(@types/node@24.10.1)) + version: 3.2.4(vitest@3.2.4(@types/node@24.12.0)) prettier: specifier: ^3.8.1 version: 3.8.1 @@ -56,7 +56,7 @@ importers: version: 5.9.3 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@24.10.1) + version: 3.2.4(@types/node@24.12.0) packages: @@ -553,8 +553,8 @@ packages: '@types/keypress.js@2.1.3': resolution: {integrity: sha512-jv+1ObzMLgR6Jl5MB29mHn8HfY251/IEz3EFm6du4gSyIe6zSEHC5Tjay/UoGCYfvYmWDsDZtsItwiSdFnLzWQ==} - '@types/node@24.10.1': - resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} + '@types/node@24.12.0': + resolution: {integrity: sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==} '@types/semver@7.7.1': resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} @@ -1171,122 +1171,122 @@ snapshots: '@inquirer/ansi@2.0.4': {} - '@inquirer/checkbox@5.1.2(@types/node@24.10.1)': + '@inquirer/checkbox@5.1.2(@types/node@24.12.0)': dependencies: '@inquirer/ansi': 2.0.4 - '@inquirer/core': 11.1.7(@types/node@24.10.1) + '@inquirer/core': 11.1.7(@types/node@24.12.0) '@inquirer/figures': 2.0.4 - '@inquirer/type': 4.0.4(@types/node@24.10.1) + '@inquirer/type': 4.0.4(@types/node@24.12.0) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 - '@inquirer/confirm@6.0.10(@types/node@24.10.1)': + '@inquirer/confirm@6.0.10(@types/node@24.12.0)': dependencies: - '@inquirer/core': 11.1.7(@types/node@24.10.1) - '@inquirer/type': 4.0.4(@types/node@24.10.1) + '@inquirer/core': 11.1.7(@types/node@24.12.0) + '@inquirer/type': 4.0.4(@types/node@24.12.0) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 - '@inquirer/core@11.1.7(@types/node@24.10.1)': + '@inquirer/core@11.1.7(@types/node@24.12.0)': dependencies: '@inquirer/ansi': 2.0.4 '@inquirer/figures': 2.0.4 - '@inquirer/type': 4.0.4(@types/node@24.10.1) + '@inquirer/type': 4.0.4(@types/node@24.12.0) cli-width: 4.1.0 fast-wrap-ansi: 0.2.0 mute-stream: 3.0.0 signal-exit: 4.1.0 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 - '@inquirer/editor@5.0.10(@types/node@24.10.1)': + '@inquirer/editor@5.0.10(@types/node@24.12.0)': dependencies: - '@inquirer/core': 11.1.7(@types/node@24.10.1) - '@inquirer/external-editor': 2.0.4(@types/node@24.10.1) - '@inquirer/type': 4.0.4(@types/node@24.10.1) + '@inquirer/core': 11.1.7(@types/node@24.12.0) + '@inquirer/external-editor': 2.0.4(@types/node@24.12.0) + '@inquirer/type': 4.0.4(@types/node@24.12.0) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 - '@inquirer/expand@5.0.10(@types/node@24.10.1)': + '@inquirer/expand@5.0.10(@types/node@24.12.0)': dependencies: - '@inquirer/core': 11.1.7(@types/node@24.10.1) - '@inquirer/type': 4.0.4(@types/node@24.10.1) + '@inquirer/core': 11.1.7(@types/node@24.12.0) + '@inquirer/type': 4.0.4(@types/node@24.12.0) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 - '@inquirer/external-editor@2.0.4(@types/node@24.10.1)': + '@inquirer/external-editor@2.0.4(@types/node@24.12.0)': dependencies: chardet: 2.1.1 iconv-lite: 0.7.2 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 '@inquirer/figures@2.0.4': {} - '@inquirer/input@5.0.10(@types/node@24.10.1)': + '@inquirer/input@5.0.10(@types/node@24.12.0)': dependencies: - '@inquirer/core': 11.1.7(@types/node@24.10.1) - '@inquirer/type': 4.0.4(@types/node@24.10.1) + '@inquirer/core': 11.1.7(@types/node@24.12.0) + '@inquirer/type': 4.0.4(@types/node@24.12.0) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 - '@inquirer/number@4.0.10(@types/node@24.10.1)': + '@inquirer/number@4.0.10(@types/node@24.12.0)': dependencies: - '@inquirer/core': 11.1.7(@types/node@24.10.1) - '@inquirer/type': 4.0.4(@types/node@24.10.1) + '@inquirer/core': 11.1.7(@types/node@24.12.0) + '@inquirer/type': 4.0.4(@types/node@24.12.0) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 - '@inquirer/password@5.0.10(@types/node@24.10.1)': + '@inquirer/password@5.0.10(@types/node@24.12.0)': dependencies: '@inquirer/ansi': 2.0.4 - '@inquirer/core': 11.1.7(@types/node@24.10.1) - '@inquirer/type': 4.0.4(@types/node@24.10.1) + '@inquirer/core': 11.1.7(@types/node@24.12.0) + '@inquirer/type': 4.0.4(@types/node@24.12.0) optionalDependencies: - '@types/node': 24.10.1 - - '@inquirer/prompts@8.3.2(@types/node@24.10.1)': - dependencies: - '@inquirer/checkbox': 5.1.2(@types/node@24.10.1) - '@inquirer/confirm': 6.0.10(@types/node@24.10.1) - '@inquirer/editor': 5.0.10(@types/node@24.10.1) - '@inquirer/expand': 5.0.10(@types/node@24.10.1) - '@inquirer/input': 5.0.10(@types/node@24.10.1) - '@inquirer/number': 4.0.10(@types/node@24.10.1) - '@inquirer/password': 5.0.10(@types/node@24.10.1) - '@inquirer/rawlist': 5.2.6(@types/node@24.10.1) - '@inquirer/search': 4.1.6(@types/node@24.10.1) - '@inquirer/select': 5.1.2(@types/node@24.10.1) + '@types/node': 24.12.0 + + '@inquirer/prompts@8.3.2(@types/node@24.12.0)': + dependencies: + '@inquirer/checkbox': 5.1.2(@types/node@24.12.0) + '@inquirer/confirm': 6.0.10(@types/node@24.12.0) + '@inquirer/editor': 5.0.10(@types/node@24.12.0) + '@inquirer/expand': 5.0.10(@types/node@24.12.0) + '@inquirer/input': 5.0.10(@types/node@24.12.0) + '@inquirer/number': 4.0.10(@types/node@24.12.0) + '@inquirer/password': 5.0.10(@types/node@24.12.0) + '@inquirer/rawlist': 5.2.6(@types/node@24.12.0) + '@inquirer/search': 4.1.6(@types/node@24.12.0) + '@inquirer/select': 5.1.2(@types/node@24.12.0) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 - '@inquirer/rawlist@5.2.6(@types/node@24.10.1)': + '@inquirer/rawlist@5.2.6(@types/node@24.12.0)': dependencies: - '@inquirer/core': 11.1.7(@types/node@24.10.1) - '@inquirer/type': 4.0.4(@types/node@24.10.1) + '@inquirer/core': 11.1.7(@types/node@24.12.0) + '@inquirer/type': 4.0.4(@types/node@24.12.0) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 - '@inquirer/search@4.1.6(@types/node@24.10.1)': + '@inquirer/search@4.1.6(@types/node@24.12.0)': dependencies: - '@inquirer/core': 11.1.7(@types/node@24.10.1) + '@inquirer/core': 11.1.7(@types/node@24.12.0) '@inquirer/figures': 2.0.4 - '@inquirer/type': 4.0.4(@types/node@24.10.1) + '@inquirer/type': 4.0.4(@types/node@24.12.0) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 - '@inquirer/select@5.1.2(@types/node@24.10.1)': + '@inquirer/select@5.1.2(@types/node@24.12.0)': dependencies: '@inquirer/ansi': 2.0.4 - '@inquirer/core': 11.1.7(@types/node@24.10.1) + '@inquirer/core': 11.1.7(@types/node@24.12.0) '@inquirer/figures': 2.0.4 - '@inquirer/type': 4.0.4(@types/node@24.10.1) + '@inquirer/type': 4.0.4(@types/node@24.12.0) optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 - '@inquirer/type@4.0.4(@types/node@24.10.1)': + '@inquirer/type@4.0.4(@types/node@24.12.0)': optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 '@isaacs/cliui@8.0.2': dependencies: @@ -1407,7 +1407,7 @@ snapshots: '@types/keypress.js@2.1.3': {} - '@types/node@24.10.1': + '@types/node@24.12.0': dependencies: undici-types: 7.16.0 @@ -1415,9 +1415,9 @@ snapshots: '@types/through@0.0.33': dependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 - '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/node@24.10.1))': + '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/node@24.12.0))': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 @@ -1432,7 +1432,7 @@ snapshots: std-env: 3.10.0 test-exclude: 7.0.1 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/node@24.10.1) + vitest: 3.2.4(@types/node@24.12.0) transitivePeerDependencies: - supports-color @@ -1444,13 +1444,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@7.3.1(@types/node@24.10.1))': + '@vitest/mocker@3.2.4(vite@7.3.1(@types/node@24.12.0))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.3.1(@types/node@24.10.1) + vite: 7.3.1(@types/node@24.12.0) '@vitest/pretty-format@3.2.4': dependencies: @@ -1626,17 +1626,17 @@ snapshots: dependencies: safer-buffer: 2.1.2 - inquirer@13.3.2(@types/node@24.10.1): + inquirer@13.3.2(@types/node@24.12.0): dependencies: '@inquirer/ansi': 2.0.4 - '@inquirer/core': 11.1.7(@types/node@24.10.1) - '@inquirer/prompts': 8.3.2(@types/node@24.10.1) - '@inquirer/type': 4.0.4(@types/node@24.10.1) + '@inquirer/core': 11.1.7(@types/node@24.12.0) + '@inquirer/prompts': 8.3.2(@types/node@24.12.0) + '@inquirer/type': 4.0.4(@types/node@24.12.0) mute-stream: 3.0.0 run-async: 4.0.6 rxjs: 7.8.2 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 is-fullwidth-code-point@3.0.0: {} @@ -1848,13 +1848,13 @@ snapshots: undici@7.24.4: {} - vite-node@3.2.4(@types/node@24.10.1): + vite-node@3.2.4(@types/node@24.12.0): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.3.1(@types/node@24.10.1) + vite: 7.3.1(@types/node@24.12.0) transitivePeerDependencies: - '@types/node' - jiti @@ -1869,7 +1869,7 @@ snapshots: - tsx - yaml - vite@7.3.1(@types/node@24.10.1): + vite@7.3.1(@types/node@24.12.0): dependencies: esbuild: 0.27.2 fdir: 6.5.0(picomatch@4.0.3) @@ -1878,14 +1878,14 @@ snapshots: rollup: 4.57.0 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 fsevents: 2.3.3 - vitest@3.2.4(@types/node@24.10.1): + vitest@3.2.4(@types/node@24.12.0): dependencies: '@types/chai': 5.2.3 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@24.10.1)) + '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@24.12.0)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -1903,11 +1903,11 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.3.1(@types/node@24.10.1) - vite-node: 3.2.4(@types/node@24.10.1) + vite: 7.3.1(@types/node@24.12.0) + vite-node: 3.2.4(@types/node@24.12.0) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 24.10.1 + '@types/node': 24.12.0 transitivePeerDependencies: - jiti - less From b29a052d53ebee1504575b243123b66281ab1a01 Mon Sep 17 00:00:00 2001 From: Mihhail Solovjov Date: Wed, 18 Mar 2026 19:40:41 +0200 Subject: [PATCH 5/5] build(deps): upgrade vitest to v4.1.0 - Update vitest and @vitest/coverage-v8 from ^3.2.4 to ^4.1.0 - Refactor Pool mock in jsdelivr-registry retry test to use named mock class --- package.json | 4 +- pnpm-lock.yaml | 649 ++++-------------- .../jsdelivr-registry.retries.test.ts | 9 +- 3 files changed, 134 insertions(+), 528 deletions(-) diff --git a/package.json b/package.json index b7135bd..06ba736 100644 --- a/package.json +++ b/package.json @@ -57,10 +57,10 @@ "@types/keypress.js": "^2.1.3", "@types/node": "^24.12.0", "@types/semver": "^7.7.1", - "@vitest/coverage-v8": "^3.2.4", + "@vitest/coverage-v8": "^4.1.0", "prettier": "^3.8.1", "typescript": "^5.9.3", - "vitest": "^3.2.4" + "vitest": "^4.1.0" }, "dependencies": { "chalk": "^5.6.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2adcb45..5cfa91e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -46,8 +46,8 @@ importers: specifier: ^7.7.1 version: 7.7.1 '@vitest/coverage-v8': - specifier: ^3.2.4 - version: 3.2.4(vitest@3.2.4(@types/node@24.12.0)) + specifier: ^4.1.0 + version: 4.1.0(vitest@4.1.0(@types/node@24.12.0)(vite@7.3.1(@types/node@24.12.0))) prettier: specifier: ^3.8.1 version: 3.8.1 @@ -55,15 +55,11 @@ importers: specifier: ^5.9.3 version: 5.9.3 vitest: - specifier: ^3.2.4 - version: 3.2.4(@types/node@24.12.0) + specifier: ^4.1.0 + version: 4.1.0(@types/node@24.12.0)(vite@7.3.1(@types/node@24.12.0)) 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'} @@ -72,13 +68,13 @@ packages: resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.6': - resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==} + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/types@7.28.6': - resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} '@bcoe/v8-coverage@1.0.2': @@ -375,17 +371,6 @@ packages: '@types/node': optional: true - '@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.13': - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -396,10 +381,6 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - '@rollup/rollup-android-arm-eabi@4.57.0': resolution: {integrity: sha512-tPgXB6cDTndIe1ah7u6amCI1T0SsnlOuKgg10Xh3uizJk4e5M1JGaUMk7J4ciuAUcFpbOiNhm2XIjP9ON0dUqA==} cpu: [arm] @@ -538,6 +519,9 @@ 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==} @@ -562,79 +546,53 @@ packages: '@types/through@0.0.33': resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==} - '@vitest/coverage-v8@3.2.4': - resolution: {integrity: sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ==} + '@vitest/coverage-v8@4.1.0': + resolution: {integrity: sha512-nDWulKeik2bL2Va/Wl4x7DLuTKAXa906iRFooIRPR+huHkcvp9QDkPQ2RJdmjOFrqOqvNfoSQLF68deE3xC3CQ==} peerDependencies: - '@vitest/browser': 3.2.4 - vitest: 3.2.4 + '@vitest/browser': 4.1.0 + vitest: 4.1.0 peerDependenciesMeta: '@vitest/browser': optional: true - '@vitest/expect@3.2.4': - resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + '@vitest/expect@4.1.0': + resolution: {integrity: sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==} - '@vitest/mocker@3.2.4': - resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + '@vitest/mocker@4.1.0': + resolution: {integrity: sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==} peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0-0 peerDependenciesMeta: msw: optional: true vite: optional: true - '@vitest/pretty-format@3.2.4': - resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} - - '@vitest/runner@3.2.4': - resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} + '@vitest/pretty-format@4.1.0': + resolution: {integrity: sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==} - '@vitest/snapshot@3.2.4': - resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} + '@vitest/runner@4.1.0': + resolution: {integrity: sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==} - '@vitest/spy@3.2.4': - resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + '@vitest/snapshot@4.1.0': + resolution: {integrity: sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==} - '@vitest/utils@3.2.4': - resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + '@vitest/spy@4.1.0': + resolution: {integrity: sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==} - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-regex@6.2.2: - resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} - engines: {node: '>=12'} - - ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - - ansi-styles@6.2.3: - resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} - engines: {node: '>=12'} + '@vitest/utils@4.1.0': + resolution: {integrity: sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==} assertion-error@2.0.1: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} - ast-v8-to-istanbul@0.3.10: - resolution: {integrity: sha512-p4K7vMz2ZSk3wN8l5o3y2bJAoZXT3VuJI5OLTATY/01CYWumWvwkUw0SqDBnNq6IiTO3qDa1eSQDibAV8g7XOQ==} - - balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - brace-expansion@2.0.2: - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} - - cac@6.7.14: - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} - engines: {node: '>=8'} + ast-v8-to-istanbul@1.0.0: + resolution: {integrity: sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==} - chai@5.3.3: - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} engines: {node: '>=18'} chalk@5.6.2: @@ -644,57 +602,23 @@ packages: chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} - check-error@2.1.3: - resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} - engines: {node: '>= 16'} - cli-width@4.1.0: resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} engines: {node: '>= 12'} - 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.3: resolution: {integrity: sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==} engines: {node: '>=20'} - cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - 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'} - - 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==} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} env-paths@4.0.0: resolution: {integrity: sha512-pxP8eL2SwwaTRi/KHYwLYXinDs7gL3jxFcBYmEdYfZmZXbaVDvdppd0XBU8qVz03rDfKZMXg1omHCbsJjZrMsw==} engines: {node: '>=20'} - es-module-lexer@1.7.0: - resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-module-lexer@2.0.0: + resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} esbuild@0.27.2: resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} @@ -726,20 +650,11 @@ packages: picomatch: optional: true - foreground-child@3.3.1: - resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} - engines: {node: '>=14'} - 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@10.5.0: - resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} - 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 - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} @@ -760,17 +675,10 @@ packages: '@types/node': optional: true - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - is-safe-filename@0.1.1: resolution: {integrity: sha512-4SrR7AdnY11LHfDKTZY1u6Ga3RuxZdl3YKWWShO5iyuG5h8QS4GD2tOb04peBJ5I7pXbR+CGBNEhTcwK+FzN3g==} engines: {node: '>=20'} - isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -779,50 +687,26 @@ 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.2.0: resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} engines: {node: '>=8'} - jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - - js-tokens@9.0.1: - resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + js-tokens@10.0.0: + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} keypress@0.2.1: resolution: {integrity: sha512-HjorDJFNhnM4SicvaUXac0X77NiskggxJdesG72+O5zBKpSqKFCrqmndKVqpu3pFqkla0St6uGk8Ju0sCurrmg==} - loupe@3.2.1: - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - 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==} engines: {node: '>=10'} - 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==} - engines: {node: '>=16 || 14 >=14.17'} - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - mute-stream@3.0.0: resolution: {integrity: sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw==} engines: {node: ^20.17.0 || >=22.9.0} @@ -835,24 +719,12 @@ packages: nanospinner@1.2.2: resolution: {integrity: sha512-Zt/AmG6qRU3e+WnzGGLuMCEAO/dAu45stNbHY223tUxldaDAeE+FxSPsd9Q+j+paejmm0ZbrNVs5Sraqy3dRxA==} - package-json-from-dist@1.0.1: - resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - - 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'} + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - pathval@2.0.1: - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} - engines: {node: '>= 14.16'} - picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -889,14 +761,6 @@ packages: 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'} - siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} @@ -911,56 +775,26 @@ 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'} - - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - - strip-ansi@7.1.2: - resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} - engines: {node: '>=12'} - - strip-literal@3.1.0: - resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + std-env@4.0.0: + resolution: {integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==} supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - test-exclude@7.0.1: - resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} - 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==} + tinyexec@1.0.4: + resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==} + engines: {node: '>=18'} tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} - tinypool@1.1.1: - resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} - engines: {node: ^18.0.0 || >=20.0.0} - - tinyrainbow@2.0.0: - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} - engines: {node: '>=14.0.0'} - - tinyspy@4.0.4: - resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + tinyrainbow@3.1.0: + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} tslib@2.8.1: @@ -978,11 +812,6 @@ packages: resolution: {integrity: sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w==} engines: {node: '>=20.18.1'} - vite-node@3.2.4: - resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} - hasBin: true - vite@7.3.1: resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1023,26 +852,33 @@ packages: yaml: optional: true - vitest@3.2.4: - resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + vitest@4.1.0: + resolution: {integrity: sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@types/debug': ^4.1.12 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 - '@vitest/browser': 3.2.4 - '@vitest/ui': 3.2.4 + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.0 + '@vitest/browser-preview': 4.1.0 + '@vitest/browser-webdriverio': 4.1.0 + '@vitest/ui': 4.1.0 happy-dom: '*' jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0-0 peerDependenciesMeta: '@edge-runtime/vm': optional: true - '@types/debug': + '@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/ui': optional: true @@ -1051,40 +887,22 @@ packages: jsdom: optional: true - 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'} - - 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.13 - '@jridgewell/trace-mapping': 0.3.31 - '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.28.5': {} - '@babel/parser@7.28.6': + '@babel/parser@7.29.2': dependencies: - '@babel/types': 7.28.6 + '@babel/types': 7.29.0 - '@babel/types@7.28.6': + '@babel/types@7.29.0': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 @@ -1288,22 +1106,6 @@ snapshots: optionalDependencies: '@types/node': 24.12.0 - '@isaacs/cliui@8.0.2': - dependencies: - string-width: 5.1.2 - string-width-cjs: string-width@4.2.3 - strip-ansi: 7.1.2 - strip-ansi-cjs: strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: wrap-ansi@7.0.0 - - '@istanbuljs/schema@0.1.3': {} - - '@jridgewell/gen-mapping@0.3.13': - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 - '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.5.5': {} @@ -1313,9 +1115,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@pkgjs/parseargs@0.11.0': - optional: true - '@rollup/rollup-android-arm-eabi@4.57.0': optional: true @@ -1391,6 +1190,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.57.0': optional: true + '@standard-schema/spec@1.1.0': {} + '@types/chai@5.2.3': dependencies: '@types/deep-eql': 4.0.2 @@ -1417,140 +1218,86 @@ snapshots: dependencies: '@types/node': 24.12.0 - '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@types/node@24.12.0))': + '@vitest/coverage-v8@4.1.0(vitest@4.1.0(@types/node@24.12.0)(vite@7.3.1(@types/node@24.12.0)))': dependencies: - '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 - ast-v8-to-istanbul: 0.3.10 - debug: 4.4.3 + '@vitest/utils': 4.1.0 + 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.2.0 - magic-string: 0.30.21 - magicast: 0.3.5 - std-env: 3.10.0 - test-exclude: 7.0.1 - tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/node@24.12.0) - transitivePeerDependencies: - - supports-color + magicast: 0.5.2 + obug: 2.1.1 + std-env: 4.0.0 + tinyrainbow: 3.1.0 + vitest: 4.1.0(@types/node@24.12.0)(vite@7.3.1(@types/node@24.12.0)) - '@vitest/expect@3.2.4': + '@vitest/expect@4.1.0': dependencies: + '@standard-schema/spec': 1.1.0 '@types/chai': 5.2.3 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 - chai: 5.3.3 - tinyrainbow: 2.0.0 + '@vitest/spy': 4.1.0 + '@vitest/utils': 4.1.0 + chai: 6.2.2 + tinyrainbow: 3.1.0 - '@vitest/mocker@3.2.4(vite@7.3.1(@types/node@24.12.0))': + '@vitest/mocker@4.1.0(vite@7.3.1(@types/node@24.12.0))': dependencies: - '@vitest/spy': 3.2.4 + '@vitest/spy': 4.1.0 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: vite: 7.3.1(@types/node@24.12.0) - '@vitest/pretty-format@3.2.4': + '@vitest/pretty-format@4.1.0': dependencies: - tinyrainbow: 2.0.0 + tinyrainbow: 3.1.0 - '@vitest/runner@3.2.4': + '@vitest/runner@4.1.0': dependencies: - '@vitest/utils': 3.2.4 + '@vitest/utils': 4.1.0 pathe: 2.0.3 - strip-literal: 3.1.0 - '@vitest/snapshot@3.2.4': + '@vitest/snapshot@4.1.0': dependencies: - '@vitest/pretty-format': 3.2.4 + '@vitest/pretty-format': 4.1.0 + '@vitest/utils': 4.1.0 magic-string: 0.30.21 pathe: 2.0.3 - '@vitest/spy@3.2.4': - dependencies: - tinyspy: 4.0.4 - - '@vitest/utils@3.2.4': - dependencies: - '@vitest/pretty-format': 3.2.4 - loupe: 3.2.1 - tinyrainbow: 2.0.0 - - ansi-regex@5.0.1: {} + '@vitest/spy@4.1.0': {} - ansi-regex@6.2.2: {} - - ansi-styles@4.3.0: + '@vitest/utils@4.1.0': dependencies: - color-convert: 2.0.1 - - ansi-styles@6.2.3: {} + '@vitest/pretty-format': 4.1.0 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 assertion-error@2.0.1: {} - ast-v8-to-istanbul@0.3.10: + ast-v8-to-istanbul@1.0.0: dependencies: '@jridgewell/trace-mapping': 0.3.31 estree-walker: 3.0.3 - js-tokens: 9.0.1 - - balanced-match@1.0.2: {} + js-tokens: 10.0.0 - brace-expansion@2.0.2: - dependencies: - balanced-match: 1.0.2 - - 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: {} chalk@5.6.2: {} chardet@2.1.1: {} - check-error@2.1.3: {} - cli-width@4.1.0: {} - color-convert@2.0.1: - dependencies: - color-name: 1.1.4 - - color-name@1.1.4: {} - commander@14.0.3: {} - cross-spawn@7.0.6: - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - deep-eql@5.0.2: {} - - eastasianwidth@0.2.0: {} - - emoji-regex@8.0.0: {} - - emoji-regex@9.2.2: {} + convert-source-map@2.0.0: {} env-paths@4.0.0: dependencies: is-safe-filename: 0.1.1 - es-module-lexer@1.7.0: {} + es-module-lexer@2.0.0: {} esbuild@0.27.2: optionalDependencies: @@ -1601,23 +1348,9 @@ snapshots: optionalDependencies: picomatch: 4.0.3 - foreground-child@3.3.1: - dependencies: - cross-spawn: 7.0.6 - signal-exit: 4.1.0 - fsevents@2.3.3: optional: true - glob@10.5.0: - 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 - has-flag@4.0.0: {} html-escaper@2.0.2: {} @@ -1638,12 +1371,8 @@ snapshots: optionalDependencies: '@types/node': 24.12.0 - is-fullwidth-code-point@3.0.0: {} - is-safe-filename@0.1.1: {} - isexe@2.0.0: {} - istanbul-lib-coverage@3.2.2: {} istanbul-lib-report@3.0.1: @@ -1652,55 +1381,29 @@ snapshots: make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@5.0.6: - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - debug: 4.4.3 - istanbul-lib-coverage: 3.2.2 - transitivePeerDependencies: - - supports-color - 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 - - js-tokens@9.0.1: {} + js-tokens@10.0.0: {} keypress@0.2.1: {} - loupe@3.2.1: {} - - lru-cache@10.4.3: {} - magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 - magicast@0.3.5: + magicast@0.5.2: dependencies: - '@babel/parser': 7.28.6 - '@babel/types': 7.28.6 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 source-map-js: 1.2.1 make-dir@4.0.0: dependencies: semver: 7.7.4 - minimatch@9.0.5: - dependencies: - brace-expansion: 2.0.2 - - minipass@7.1.2: {} - - ms@2.1.3: {} - mute-stream@3.0.0: {} nanoid@3.3.11: {} @@ -1709,19 +1412,10 @@ snapshots: dependencies: picocolors: 1.1.1 - package-json-from-dist@1.0.1: {} - - path-key@3.1.1: {} - - path-scurry@1.11.1: - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 + obug@2.1.1: {} pathe@2.0.3: {} - pathval@2.0.1: {} - picocolors@1.1.1: {} picomatch@4.0.3: {} @@ -1775,12 +1469,6 @@ snapshots: semver@7.7.4: {} - shebang-command@2.0.0: - dependencies: - shebang-regex: 3.0.0 - - shebang-regex@3.0.0: {} - siginfo@2.0.0: {} signal-exit@4.1.0: {} @@ -1789,56 +1477,22 @@ 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.2 - - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - - strip-ansi@7.1.2: - dependencies: - ansi-regex: 6.2.2 - - strip-literal@3.1.0: - dependencies: - js-tokens: 9.0.1 + std-env@4.0.0: {} supports-color@7.2.0: dependencies: has-flag: 4.0.0 - test-exclude@7.0.1: - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 10.5.0 - minimatch: 9.0.5 - tinybench@2.9.0: {} - tinyexec@0.3.2: {} + tinyexec@1.0.4: {} tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 - tinypool@1.1.1: {} - - tinyrainbow@2.0.0: {} - - tinyspy@4.0.4: {} + tinyrainbow@3.1.0: {} tslib@2.8.1: {} @@ -1848,27 +1502,6 @@ snapshots: undici@7.24.4: {} - vite-node@3.2.4(@types/node@24.12.0): - dependencies: - cac: 6.7.14 - debug: 4.4.3 - es-module-lexer: 1.7.0 - pathe: 2.0.3 - vite: 7.3.1(@types/node@24.12.0) - transitivePeerDependencies: - - '@types/node' - - jiti - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - vite@7.3.1(@types/node@24.12.0): dependencies: esbuild: 0.27.2 @@ -1881,64 +1514,34 @@ snapshots: '@types/node': 24.12.0 fsevents: 2.3.3 - vitest@3.2.4(@types/node@24.12.0): + vitest@4.1.0(@types/node@24.12.0)(vite@7.3.1(@types/node@24.12.0)): dependencies: - '@types/chai': 5.2.3 - '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@24.12.0)) - '@vitest/pretty-format': 3.2.4 - '@vitest/runner': 3.2.4 - '@vitest/snapshot': 3.2.4 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 - chai: 5.3.3 - debug: 4.4.3 + '@vitest/expect': 4.1.0 + '@vitest/mocker': 4.1.0(vite@7.3.1(@types/node@24.12.0)) + '@vitest/pretty-format': 4.1.0 + '@vitest/runner': 4.1.0 + '@vitest/snapshot': 4.1.0 + '@vitest/spy': 4.1.0 + '@vitest/utils': 4.1.0 + es-module-lexer: 2.0.0 expect-type: 1.3.0 magic-string: 0.30.21 + obug: 2.1.1 pathe: 2.0.3 picomatch: 4.0.3 - std-env: 3.10.0 + std-env: 4.0.0 tinybench: 2.9.0 - tinyexec: 0.3.2 + tinyexec: 1.0.4 tinyglobby: 0.2.15 - tinypool: 1.1.1 - tinyrainbow: 2.0.0 + tinyrainbow: 3.1.0 vite: 7.3.1(@types/node@24.12.0) - vite-node: 3.2.4(@types/node@24.12.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 24.12.0 transitivePeerDependencies: - - jiti - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - - 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 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrap-ansi@8.1.0: - dependencies: - ansi-styles: 6.2.3 - string-width: 5.1.2 - strip-ansi: 7.1.2 diff --git a/test/unit/services/jsdelivr-registry.retries.test.ts b/test/unit/services/jsdelivr-registry.retries.test.ts index 41dbf04..850f3e0 100644 --- a/test/unit/services/jsdelivr-registry.retries.test.ts +++ b/test/unit/services/jsdelivr-registry.retries.test.ts @@ -3,11 +3,14 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' const requestMock = vi.fn() const closeMock = vi.fn() const getAllPackageDataMock = vi.fn() +const PoolMock = vi.fn( + class MockPool { + close = closeMock + } +) vi.mock('undici', () => ({ - Pool: vi.fn().mockImplementation(() => ({ - close: closeMock, - })), + Pool: PoolMock, request: requestMock, }))