From c9f357a13791601e17318d26052f6004298f8c3c Mon Sep 17 00:00:00 2001 From: Julien Ripouteau Date: Fri, 6 Nov 2026 20:50:05 +0000 Subject: [PATCH 1/2] feat: use module.registerHooks() instead of deprecated module.register() Node.js 26 emits a runtime deprecation (DEP0205) for module.register(). hot.init() now registers synchronous in-thread hooks with module.registerHooks() on Node.js >= 22.22.3, 24.11.1, 25.1.0 and 26, and falls back to module.register() on older versions, whose registerHooks() breaks CommonJS loading when combined with module.register() hooks such as ts-node's. The same HotHookLoader serves both modes. With in-thread hooks, the chokidar watcher runs in a dedicated worker so it neither keeps the process alive nor misses changes during startup. Closes #18 Amp-Thread-ID: https://ampcode.com/threads/T-01a1b212-dc0a-7380-bad5-624903b77b96 --- .changeset/sync-module-hooks.md | 7 + .github/workflows/check.yml | 3 +- README.md | 2 +- .../hot_hook/src/dynamic_import_checker.ts | 16 +- packages/hot_hook/src/hot.ts | 77 +++++++-- packages/hot_hook/src/loader.ts | 155 +++++++++++------- packages/hot_hook/src/maybe_async.ts | 10 ++ packages/hot_hook/src/watcher_thread.ts | 58 +++++++ packages/hot_hook/tests/register.spec.ts | 69 ++++++++ 9 files changed, 313 insertions(+), 84 deletions(-) create mode 100644 .changeset/sync-module-hooks.md create mode 100644 packages/hot_hook/src/maybe_async.ts create mode 100644 packages/hot_hook/src/watcher_thread.ts diff --git a/.changeset/sync-module-hooks.md b/.changeset/sync-module-hooks.md new file mode 100644 index 0000000..4edc53a --- /dev/null +++ b/.changeset/sync-module-hooks.md @@ -0,0 +1,7 @@ +--- +'hot-hook': minor +--- + +Use synchronous `module.registerHooks()` on Node.js >= 22.22.3, 24.11.1, 25.1.0 and 26 instead of the deprecated `module.register()` (DEP0205). Older Node.js versions fall back to `module.register()`, since their `registerHooks()` breaks CommonJS loading when combined with `module.register()` hooks such as ts-node's. + +With in-thread hooks, `require()` calls also go through hot-hook. diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 7ed0f0c..0dca79e 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -49,7 +49,8 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest] - node: [22, 24] + # 22.15 uses the `module.register()` fallback, see `canUseSyncHooks()` + node: ['22.15', 22, 24, 26] runs-on: ${{ matrix.os }} timeout-minutes: 10 diff --git a/README.md b/README.md index df0c3a7..80af081 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ await hot.init({ }) ``` -The `hot.init` function internally call [`register`](https://nodejs.org/api/module.html#moduleregisterspecifier-parenturl-options) from `node:module` to hook into the module loading process. This is why you need to call it as early as possible, otherwise modules imported before the call to `hot.init` will not benefit from hot module replacement. +The `hot.init` function internally calls [`registerHooks`](https://nodejs.org/api/module.html#moduleregisterhooksoptions) from `node:module` to hook into the module loading process. On Node.js versions older than 22.22.3, 24.11.1 or 25.1.0, it falls back to [`register`](https://nodejs.org/api/module.html#moduleregisterspecifier-parenturl-options). This is why you need to call it as early as possible, otherwise modules imported before the call to `hot.init` will not benefit from hot module replacement. Next, you need to include the types for `import.meta.hot` in your project. To do this, add the following code in a `.d.ts` file or in the `types` property of your `tsconfig.json`. diff --git a/packages/hot_hook/src/dynamic_import_checker.ts b/packages/hot_hook/src/dynamic_import_checker.ts index 3965018..25d80fe 100644 --- a/packages/hot_hook/src/dynamic_import_checker.ts +++ b/packages/hot_hook/src/dynamic_import_checker.ts @@ -1,5 +1,11 @@ -import { readFile } from 'node:fs/promises' -import { parseImports } from 'parse-imports' +import { readFileSync } from 'node:fs' +import { parseImportsSync, wasmLoadPromise } from 'parse-imports' + +/** + * `parseImportsSync` needs the lexer WASM to be loaded. The check runs inside + * module hooks, which are synchronous with `module.registerHooks()`. + */ +await wasmLoadPromise /** * This class is responsible for checking if a given specifier @@ -13,14 +19,14 @@ import { parseImports } from 'parse-imports' export class DynamicImportChecker { private cache: Map> = new Map() - async ensureFileIsImportedDynamicallyFromParent(parentPath: string, specifier: string) { + ensureFileIsImportedDynamicallyFromParent(parentPath: string, specifier: string) { const cacheKey = parentPath if (this.cache.has(cacheKey) && this.cache.get(cacheKey)!.has(specifier)) { return this.cache.get(cacheKey)!.get(specifier)! } - const parentCode = await readFile(parentPath, 'utf-8') - const imports = [...(await parseImports(parentCode))] + const parentCode = readFileSync(parentPath, 'utf-8') + const imports = [...parseImportsSync(parentCode)] const matchingImport = imports.find((importStatement) => { return importStatement.moduleSpecifier.value === specifier diff --git a/packages/hot_hook/src/hot.ts b/packages/hot_hook/src/hot.ts index d80fbd4..30e8767 100644 --- a/packages/hot_hook/src/hot.ts +++ b/packages/hot_hook/src/hot.ts @@ -1,9 +1,26 @@ -import { register } from 'node:module' +import module from 'node:module' import { MessageChannel } from 'node:worker_threads' +import type { LoadHookSync, ResolveHookSync } from 'node:module' import debug from './debug.js' import type { InitOptions, InitializeHookOptions, MessageChannelMessage } from './types.js' +/** + * Whether this Node.js version can run hot-hook with `module.registerHooks()`. + * + * `registerHooks()` exists since 22.15, but until 22.22.3, 24.11.1 and 25.1.0, + * a synchronous `load` hook fails on CommonJS modules when hooks from + * `module.register()` are also registered, like ts-node's or older tsx's. + */ +function canUseSyncHooks() { + const [major, minor, patch] = process.versions.node.split('.').map(Number) + if (major >= 26) return true + + const minimum = ({ 22: [22, 3], 24: [11, 1], 25: [1, 0] } as Record)[major] + if (!minimum) return false + return minor > minimum[0] || (minor === minimum[0] && patch >= minimum[1]) +} + class Hot { #options!: InitOptions #messageChannel!: MessageChannel @@ -72,26 +89,50 @@ class Hot { /** * First, we setup a message channel to be able to communicate - * between the hook and the application process since hooks - * are running in a worker thread + * between the hook and the application process, since with the + * `module.register()` fallback hooks are running in a worker thread */ this.#messageChannel = new MessageChannel() - register('hot-hook/loader', { - parentURL: import.meta.url, - transferList: [this.#messageChannel.port2], - data: { - root: this.#options.root, - watch: this.#options.watch, - ignore: this.#options.ignore, - restart: this.#options.restart, - boundaries: this.#options.boundaries, - messagePort: this.#messageChannel.port2, - rootDirectory: this.#options.rootDirectory, - throwWhenBoundariesAreNotDynamicallyImported: - this.#options.throwWhenBoundariesAreNotDynamicallyImported, - } satisfies InitializeHookOptions, - }) + const data: InitializeHookOptions = { + root: this.#options.root, + watch: this.#options.watch, + ignore: this.#options.ignore, + restart: this.#options.restart, + boundaries: this.#options.boundaries, + messagePort: this.#messageChannel.port2, + rootDirectory: this.#options.rootDirectory, + throwWhenBoundariesAreNotDynamicallyImported: + this.#options.throwWhenBoundariesAreNotDynamicallyImported, + } + + /** + * Prefer synchronous in-thread hooks since `module.register()` is + * deprecated (DEP0205). The loader then runs on this thread but keeps + * using the message channel, like the off-thread fallback. + */ + if (canUseSyncHooks()) { + const { HotHookLoader } = await import('./loader.js') + const loader = new HotHookLoader(data) + + /** + * Safe casts: hooks return synchronously when `nextResolve`/`nextLoad` + * do, which is always the case with `registerHooks()` + */ + module.registerHooks({ + resolve: loader.resolve as ResolveHookSync, + load: loader.load as LoadHookSync, + }) + + this.#messageChannel.port2.unref() + await loader.whenWatcherReady() + } else { + module.register('hot-hook/loader', { + parentURL: import.meta.url, + transferList: [this.#messageChannel.port2], + data, + }) + } this.#messageChannel.port1.on('message', this.#onMessage.bind(this)) this.#messageChannel.port1.unref() diff --git a/packages/hot_hook/src/loader.ts b/packages/hot_hook/src/loader.ts index 9d9d78b..2842766 100644 --- a/packages/hot_hook/src/loader.ts +++ b/packages/hot_hook/src/loader.ts @@ -1,13 +1,21 @@ +import chokidar from 'chokidar' import { fileURLToPath } from 'node:url' -import chokidar, { type FSWatcher } from 'chokidar' import { access, realpath } from 'node:fs/promises' import type { MessagePort } from 'node:worker_threads' import { resolve as pathResolve, dirname } from 'node:path' -import type { InitializeHook, LoadHook, ResolveHook } from 'node:module' +import type { + LoadHook, + ResolveHook, + InitializeHook, + ResolveFnOutput, + ResolveHookContext, +} from 'node:module' import debug from './debug.js' import { Matcher } from './matcher.js' +import { then } from './maybe_async.js' import DependencyTree from './dependency_tree.js' +import { WatcherThread } from './watcher_thread.js' import { shiftInlineSourceMap } from './source_map.js' import type { InitializeHookOptions } from './types.js' import { DynamicImportChecker } from './dynamic_import_checker.js' @@ -18,50 +26,60 @@ export class HotHookLoader { #projectRoot!: string #reloadMatcher!: Matcher #messagePort?: MessagePort - #watcher?: FSWatcher + #watcher?: { add(paths: string | string[]): unknown } + #offThread: boolean #pathIgnoredMatcher!: Matcher #dependencyTree: DependencyTree #hardcodedBoundaryMatcher!: Matcher #dynamicImportChecker!: DynamicImportChecker #boundFileChangeHandler = this.#onFileChange.bind(this) + #watcherReady: Promise = Promise.resolve() - constructor(options: InitializeHookOptions) { + /** + * `offThread` is true when hooks run on the `module.register()` hooks thread + */ + constructor(options: InitializeHookOptions, offThread = false) { this.#options = options + this.#offThread = offThread this.#messagePort = options.messagePort this.#projectRoot = options.rootDirectory! - if (options.root) this.#initialize(options.root) - this.#dependencyTree = new DependencyTree({ root: options.root }) this.#dynamicImportChecker = new DynamicImportChecker() + + /** + * Start watching the `restart` files right away when the project root is + * known, so the initial scan can complete before the application runs. + */ + if (options.root || options.rootDirectory) this.#initialize(options.root) + this.#messagePort?.on('message', (message) => this.#onMessage(message)) } /** - * Initialize the class with the provided root path. + * Resolves once the watcher has scanned the files it watches so far. + * + * Waiting for it avoids missing changes made right after the application + * starts. */ - #initialize(root: string) { - this.#projectRoot = this.#projectRoot ?? dirname(root) - this.#reloadMatcher = new Matcher(this.#projectRoot, this.#options.restart || []) - this.#pathIgnoredMatcher = new Matcher(this.#projectRoot, this.#options.ignore) - this.#hardcodedBoundaryMatcher = new Matcher(this.#projectRoot, this.#options.boundaries) - - if (this.#options.watch !== false) { - this.#cleanupWatcher() - this.#watcher = this.#createWatcher().add([root, ...(this.#options.restart || [])]) - } + whenWatcherReady() { + return this.#watcherReady } /** - * Clean up the existing watcher and its event listeners + * Initialize the matchers and the watcher. Called again with the root path + * once it is resolved. */ - #cleanupWatcher() { - if (!this.#watcher) return + #initialize(root?: string) { + this.#projectRoot = this.#projectRoot ?? dirname(root!) + this.#reloadMatcher = new Matcher(this.#projectRoot, this.#options.restart || []) + this.#pathIgnoredMatcher = new Matcher(this.#projectRoot, this.#options.ignore) + this.#hardcodedBoundaryMatcher = new Matcher(this.#projectRoot, this.#options.boundaries) + + if (this.#options.watch === false) return - this.#watcher.off('change', this.#boundFileChangeHandler) - this.#watcher.off('unlink', this.#boundFileChangeHandler) - this.#watcher.close() - this.#watcher = undefined + this.#watcher ??= this.#createWatcher(this.#options.restart || []) + if (root) this.#watcher.add(root) } /** @@ -164,10 +182,12 @@ export class HotHookLoader { } /** - * Create the chokidar watcher instance. + * Create the watcher. With in-thread hooks it runs on its own thread, see + * `WatcherThread`. The off-thread hooks thread already plays that role. */ - #createWatcher() { - const watcher = chokidar.watch([]) + #createWatcher(paths: string[]) { + const watcher = this.#offThread ? chokidar.watch(paths) : new WatcherThread(paths) + this.#watcherReady = new Promise((resolve) => watcher.once('ready', () => resolve())) watcher.on('change', this.#boundFileChangeHandler) watcher.on('unlink', this.#boundFileChangeHandler) @@ -210,43 +230,49 @@ export class HotHookLoader { * The load hook. * We use it mainly for adding the import.meta.hot object to the module. */ - load: LoadHook = async (url, context, nextLoad) => { + load: LoadHook = (url, context, nextLoad) => { const parsedUrl = new URL(url) if (parsedUrl.searchParams.has('hot-hook')) { parsedUrl.searchParams.delete('hot-hook') url = parsedUrl.href } + /** + * Copy instead of deleting: in-thread hooks receive frozen import attributes + */ if (context.importAttributes?.hot) { - delete context.importAttributes.hot + const { hot: _hot, ...importAttributes } = context.importAttributes + context = { ...context, importAttributes } } - const result = await nextLoad(url, context) - if (result.format !== 'module') return result + return then(nextLoad(url, context), (result) => { + if (result.format !== 'module') return result - /** - * Decode explicitly: `source` can be a Uint8Array, and `toString()` - * would produce its comma-separated bytes - */ - const source = - typeof result.source === 'string' ? result.source : new TextDecoder().decode(result.source) + /** + * Decode explicitly: `source` can be a Uint8Array, e.g. when a + * `module.register()` hook runs after in-thread hooks, and `toString()` + * would produce its comma-separated bytes + */ + const source = + typeof result.source === 'string' ? result.source : new TextDecoder().decode(result.source) - /** - * A module can only access its `import.meta` by writing it in its own - * source (`eval` and `new Function` can't), so modules without it can't - * observe `import.meta.hot` and are loaded unchanged. Matching only - * `import.meta.hot` would miss accesses like `"hot" in import.meta` - * used by @adonisjs/fold. - */ - if (!source.includes('import.meta')) return result + /** + * A module can only access its `import.meta` by writing it in its own + * source (`eval` and `new Function` can't), so modules without it can't + * observe `import.meta.hot` and are loaded unchanged. Matching only + * `import.meta.hot` would miss accesses like `"hot" in import.meta` + * used by @adonisjs/fold. + */ + if (!source.includes('import.meta')) return result - /** - * The helpers are prepended on line 1, so shift the module's inline - * source map (from tsx, ts-node, ...) to keep positions exact. - */ - const hotSource = this.#getImportMetaHotSource() - result.source = shiftInlineSourceMap(hotSource + source, hotSource.length) - return result + /** + * The helpers are prepended on line 1, so shift the module's inline + * source map (from tsx, ts-node, ...) to keep positions exact. + */ + const hotSource = this.#getImportMetaHotSource() + result.source = shiftInlineSourceMap(hotSource + source, hotSource.length) + return result + }) } /** @@ -255,14 +281,28 @@ export class HotHookLoader { * - Adding the hot-hook query parameter to the URL ( to getting a fresh version ) * - And adding files to the watcher */ - resolve: ResolveHook = async (specifier, context, nextResolve) => { + resolve: ResolveHook = (specifier, context, nextResolve) => { const parentUrl = (context.parentURL && new URL(context.parentURL)) as URL if (parentUrl?.searchParams.has('hot-hook')) { parentUrl.searchParams.delete('hot-hook') context = { ...context, parentURL: parentUrl.href } } - const result = await nextResolve(specifier, context) + return then(nextResolve(specifier, context), (result) => + this.#onResolved(specifier, context, parentUrl, result), + ) + } + + /** + * Track the resolved file in the dependency tree and the watcher, and + * add the version query parameter to its URL + */ + #onResolved( + specifier: string, + context: ResolveHookContext, + parentUrl: URL | undefined, + result: ResolveFnOutput, + ): ResolveFnOutput { const resultUrl = new URL(result.url) if (resultUrl.protocol !== 'file:') { @@ -294,10 +334,7 @@ export class HotHookLoader { * from the parent file. Otherwise, hot-hook can't invalidate the file */ const isImportedDynamically = - await this.#dynamicImportChecker.ensureFileIsImportedDynamicallyFromParent( - parentPath, - specifier, - ) + this.#dynamicImportChecker.ensureFileIsImportedDynamicallyFromParent(parentPath, specifier) /** * Throw an error if not dynamically imported and the option is set @@ -332,7 +369,7 @@ export class HotHookLoader { let loader!: HotHookLoader export const initialize: InitializeHook = async (data: InitializeHookOptions) => { - loader = new HotHookLoader(data) + loader = new HotHookLoader(data, true) } export const load: LoadHook = (...args) => loader?.load(...args) export const resolve: ResolveHook = (...args) => loader?.resolve(...args) diff --git a/packages/hot_hook/src/maybe_async.ts b/packages/hot_hook/src/maybe_async.ts new file mode 100644 index 0000000..3ebeee0 --- /dev/null +++ b/packages/hot_hook/src/maybe_async.ts @@ -0,0 +1,10 @@ +/** + * Applies `fn` to `value`, or to its resolved value when it is a promise. + * + * This lets the same hooks run synchronously with `module.registerHooks()`, + * where `nextResolve`/`nextLoad` return plain objects, and asynchronously with + * the `module.register()` fallback, where they return promises. + */ +export function then(value: T | Promise, fn: (value: T) => R): R | Promise { + return value instanceof Promise ? value.then(fn) : fn(value) +} diff --git a/packages/hot_hook/src/watcher_thread.ts b/packages/hot_hook/src/watcher_thread.ts new file mode 100644 index 0000000..3796801 --- /dev/null +++ b/packages/hot_hook/src/watcher_thread.ts @@ -0,0 +1,58 @@ +import chokidar from 'chokidar' +import { EventEmitter } from 'node:events' +import { Worker, parentPort, workerData } from 'node:worker_threads' + +import debug from './debug.js' + +/** + * Runs a chokidar watcher on a dedicated worker thread and re-emits its + * `change`, `unlink` and `ready` events. + * + * Used with in-thread hooks: on the main thread, the watcher would keep the + * process alive and could only scan files while the application is idle. + * The worker is unref'd after its initial scan, so it does not keep the + * process alive. + */ +export class WatcherThread extends EventEmitter { + #worker: Worker + + constructor(paths: string[]) { + super() + + /** + * Empty `execArgv` so preloads like `--import=hot-hook/register` don't run + * again in the worker + */ + this.#worker = new Worker(new URL(import.meta.url), { + execArgv: [], + workerData: { hotHookWatcherPaths: paths }, + }) + this.#worker.on('message', ({ event, path }) => this.emit(event, path)) + this.#worker.on('error', (error) => debug('Watcher thread error %O', error)) + + /** + * Never leave `hot.init()` waiting if the worker dies before its scan + */ + this.#worker.once('exit', () => this.emit('ready')) + + /** + * Keep the process alive until the initial scan is done, so that + * `hot.init()` can wait for it + */ + this.once('ready', () => this.#worker.unref()) + } + + add(paths: string | string[]) { + this.#worker.postMessage(paths) + return this + } +} + +if (workerData?.hotHookWatcherPaths) { + const watcher = chokidar.watch(workerData.hotHookWatcherPaths) + watcher.on('change', (path) => parentPort!.postMessage({ event: 'change', path })) + watcher.on('unlink', (path) => parentPort!.postMessage({ event: 'unlink', path })) + watcher.on('ready', () => parentPort!.postMessage({ event: 'ready' })) + watcher.on('error', (error) => debug('Watcher error %O', error)) + parentPort!.on('message', (paths) => watcher.add(paths)) +} diff --git a/packages/hot_hook/tests/register.spec.ts b/packages/hot_hook/tests/register.spec.ts index e854688..93d9057 100644 --- a/packages/hot_hook/tests/register.spec.ts +++ b/packages/hot_hook/tests/register.spec.ts @@ -1,5 +1,6 @@ import { join } from 'node:path' import { pEvent } from 'p-event' +import pTimeout from 'p-timeout' import supertest from 'supertest' import { test } from '@japa/runner' import { setTimeout } from 'node:timers/promises' @@ -45,6 +46,46 @@ test.group('Register', () => { await supertest('http://localhost:3333').get('/').expect(200).expect('Hello World! Updated new') }) + test('works after a loader registered with module.register()', async ({ fs }) => { + await fakeInstall(fs.basePath) + + /** + * Like ts-node, preloaded before hot-hook + */ + await fs.create( + 'async-loader.js', + `import { register } from 'node:module' + register('data:text/javascript,export async function load(url, context, next) { return next(url, context) }')`, + ) + + await fs.createJson('package.json', { type: 'module' }) + await fs.create( + 'server.js', + `import * as http from 'http' + + const server = http.createServer(async (request, response) => { + const app = await import('./app.js', import.meta.hot?.boundary) + await app.default(request, response) + }) + + server.listen(3333, () => console.log('Server is running'))`, + ) + + await createHandlerFile({ path: 'app.js', response: 'Hello World!' }) + + const server = runProcess('server.js', { + cwd: fs.basePath, + nodeOptions: ['--import=./async-loader.js', '--import=hot-hook/register'], + }) + + await server.waitForOutput('Server is running') + await supertest('http://localhost:3333').get('/').expect(200).expect('Hello World!') + + await createHandlerFile({ path: 'app.js', response: 'Hello World! Updated' }) + await setTimeout(100) + await supertest('http://localhost:3333').get('/').expect(200).expect('Hello World! Updated') + }) + test('send full reload message', async ({ fs, assert }) => { await fakeInstall(fs.basePath) @@ -301,4 +342,32 @@ test.group('Register', () => { await setTimeout(100) await supertest('http://localhost:3333').get('/').expect(200).expect('Hello World! Updated') }) + + test('exits when the application is done, without deprecation warnings', async ({ + fs, + assert, + }) => { + await fakeInstall(fs.basePath) + + await fs.createJson('package.json', { + type: 'module', + hotHook: { boundaries: ['./app.js'] }, + }) + await fs.create('server.js', `await import('./app.js'); console.log('done')`) + await createHandlerFile({ path: 'app.js', response: 'Hello World!' }) + + const server = runProcess('server.js', { + cwd: fs.basePath, + nodeOptions: ['--import=hot-hook/register'], + }) + + let stderr = '' + server.child.stderr?.on('data', (data) => (stderr += data)) + + await server.waitForOutput('done') + await pTimeout(server.waitForExit(), { milliseconds: 2000 }) + + assert.equal(server.child.exitCode, 0) + assert.notInclude(stderr, 'DEP0205') + }) }) From 4aa84287802356e7c70f7e9f5e2b8967e865aa43 Mon Sep 17 00:00:00 2001 From: Julien Ripouteau Date: Fri, 6 Nov 2026 21:01:24 +0000 Subject: [PATCH 2/2] chore: upgrade c8 to v12 to run on Node.js 26 c8 10 depends on yargs 17.7.2, which fails to load on Node.js 26 ("require is not defined in ES module scope"). Amp-Thread-ID: https://ampcode.com/threads/T-01a1b212-dc0a-7380-bad5-624903b77b96 --- package.json | 2 +- pnpm-lock.yaml | 299 +++++++++++++++++++------------------------------ 2 files changed, 117 insertions(+), 184 deletions(-) diff --git a/package.json b/package.json index c005d6e..06c1b19 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@types/fs-extra": "^11.0.4", "@types/node": "^22.19.2", "@types/supertest": "^6.0.3", - "c8": "^10.1.3", + "c8": "^12.0.0", "del-cli": "^6.0.0", "desm": "^1.3.1", "eslint": "^9.39.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 76e1de9..9f53a05 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -42,8 +42,8 @@ importers: specifier: ^6.0.3 version: 6.0.3 c8: - specifier: ^10.1.3 - version: 10.1.3 + specifier: ^12.0.0 + version: 12.0.0 del-cli: specifier: ^6.0.0 version: 6.0.0 @@ -1057,10 +1057,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'} @@ -1189,9 +1185,6 @@ packages: '@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==} @@ -1244,10 +1237,6 @@ packages: '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} - '@pkgjs/parseargs@0.11.0': - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - '@pkgr/core@0.1.2': resolution: {integrity: sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -2015,6 +2004,10 @@ packages: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} + ansi-regex@6.5.0: + resolution: {integrity: sha512-zhvbbbdt1kbw7EJ9OQoxmQcuaNR9P5kTj7e/YdmOSU10aHWbycofJxA6jKfoEy3vlLdctOF9ZHaxLtmSm998wQ==} + engines: {node: '>=12'} + ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -2091,6 +2084,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + 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'} @@ -2108,6 +2105,10 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@5.0.12: + resolution: {integrity: sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==} + engines: {node: 20 || >=22} + braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} @@ -2129,9 +2130,9 @@ packages: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} - c8@10.1.3: - resolution: {integrity: sha512-LvcyrOAaOnrrlMpW22n690PUvxiq4Uf9WMhQwNJ9vgagkL/ph1+D4uvjvDA5XCbykrc0sx+ay6pVi9YZ1GnhyA==} - engines: {node: '>=18'} + c8@12.0.0: + resolution: {integrity: sha512-4zpJvrd1nKWutnnKC2pXkFmb6iM1l+ffN//o1CzlTNwW7GSOs9a1xrLqkC48nU8oEkjmPZLPiwMsIaOvoF4Pqg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} hasBin: true peerDependencies: monocart-coverage-reports: ^2 @@ -2243,9 +2244,9 @@ packages: resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} engines: {node: '>=18'} - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + cliui@9.0.1: + resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} + engines: {node: '>=20'} clone-deep@4.0.1: resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} @@ -2511,9 +2512,6 @@ packages: duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -2530,9 +2528,6 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} @@ -2587,10 +2582,6 @@ packages: engines: {node: '>=18'} hasBin: true - escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -2742,6 +2733,7 @@ packages: eslint@9.39.2: resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true peerDependencies: jiti: '*' @@ -2989,6 +2981,10 @@ packages: resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} engines: {node: '>=18'} + get-east-asian-width@1.7.0: + resolution: {integrity: sha512-XjH1AECxf0giL2V1aU8vKyRR2ppRUb5c0EvT7zuJTokQ74bNo52zOtghqdWIqrhUD79fo3x0WfKZdOqxF6LG1Q==} + engines: {node: '>=18'} + get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} @@ -3032,9 +3028,9 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob@10.4.5: - resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} - hasBin: true + glob@13.0.7: + resolution: {integrity: sha512-wfsFgXQ8A3SEI9XGf7Nl3Y9l7ffSrGh7SUCT7vU/2CzYPep9kjxAn1S40F9OPKxAMGCVl7HtNlJhrCJUeUq83g==} + engines: {node: 18 || 20 || >=22} globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} @@ -3298,9 +3294,6 @@ packages: resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} engines: {node: '>=8'} - jackspeak@3.4.3: - resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - jest-diff@25.5.0: resolution: {integrity: sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==} engines: {node: '>= 8.3'} @@ -3491,10 +3484,6 @@ packages: loupe@3.1.0: resolution: {integrity: sha512-qKl+FrLXUhFuHUoDJG7f8P8gEMHq9NFS0c6ghXG1J0rldmZFQZoNVv/vyirE9qwCIhWZDsvEFd1sbFu3GvRQFg==} - lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} - engines: {node: 14 || >=16.14} - lru-cache@11.2.4: resolution: {integrity: sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==} engines: {node: 20 || >=22} @@ -3502,10 +3491,6 @@ packages: lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - magic-string@0.30.11: resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} @@ -3603,6 +3588,10 @@ packages: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -3613,8 +3602,8 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} mkdirp@3.0.1: @@ -3789,9 +3778,6 @@ packages: 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.0: resolution: {integrity: sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog==} @@ -3850,9 +3836,9 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} + 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==} @@ -4085,10 +4071,6 @@ packages: resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} hasBin: true - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -4167,11 +4149,6 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} - hasBin: true - semver@7.7.2: resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} engines: {node: '>=10'} @@ -4325,10 +4302,6 @@ packages: 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'} - string-width@7.1.0: resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} engines: {node: '>=18'} @@ -4337,6 +4310,10 @@ packages: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} + string-width@8.3.0: + resolution: {integrity: sha512-ZbmZM0JCihQN91dWnxoipT2KOEyHqEyfRXUyjuRhW8b/xnqPDoq4gWEVApTVa9db2wN8mmoikgFBbjh71+cGeQ==} + engines: {node: '>=20'} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -4345,6 +4322,10 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -4440,9 +4421,9 @@ packages: resolution: {integrity: sha512-rcdty1xZ2/BkWa4ANjWRp4JGpda2quksXIHgn5TMjNBPZfwzJIgR68DKfSYiTL+CZWowDX/sbOo5ME/FRURvYQ==} engines: {node: '>=18'} - test-exclude@7.0.1: - resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} - engines: {node: '>=18'} + test-exclude@8.0.0: + resolution: {integrity: sha512-ZOffsNrXYggvU1mDGHk54I96r26P8SyMjO5slMKSc7+IWmtB/MQKnEC2fP51imB3/pT6YK5cT5E8f+Dd9KdyOQ==} + engines: {node: 20 || >=22} thread-stream@3.1.0: resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} @@ -4643,6 +4624,7 @@ packages: uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028). hasBin: true v8-compile-cache-lib@3.0.1: @@ -4761,14 +4743,6 @@ packages: wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - 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'} - wrap-ansi@9.0.0: resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} engines: {node: '>=18'} @@ -4787,16 +4761,17 @@ packages: yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - 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'} + yargs-parser@22.0.0: + resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} + + yargs@18.2.0: + resolution: {integrity: sha512-9OpKOLeaoNFecEp7P6iYbzze/5CqWoH7N3SMs/6y1XF4nMvFMspEGZzJ6uFi9MmQwXhyzqYoSEKO3tvA3Z/o2w==} + engines: {node: ^20.19.0 || ^22.12.0 || >=23} yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} @@ -5034,7 +5009,7 @@ snapshots: '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/trace-mapping': 0.3.31 '@antfu/install-pkg@0.4.1': dependencies: @@ -5108,7 +5083,7 @@ snapshots: dependencies: '@babel/types': 7.26.0 '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/trace-mapping': 0.3.31 jsesc: 2.5.2 '@babel/generator@7.28.5': @@ -5733,15 +5708,6 @@ snapshots: optionalDependencies: '@types/node': 22.19.2 - '@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 - '@istanbuljs/schema@0.1.3': {} '@japa/assert@3.0.0(@japa/runner@3.1.4)(openapi-types@12.1.3)': @@ -5884,19 +5850,19 @@ snapshots: '@jridgewell/gen-mapping@0.3.13': dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/remapping@2.3.5': dependencies: '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/trace-mapping': 0.3.31 '@jridgewell/resolve-uri@3.1.2': {} @@ -5908,15 +5874,10 @@ snapshots: '@jridgewell/sourcemap-codec@1.5.5': {} - '@jridgewell/trace-mapping@0.3.25': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - '@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 '@jridgewell/trace-mapping@0.3.9': dependencies: @@ -6004,9 +5965,6 @@ snapshots: '@pinojs/redact@0.4.0': {} - '@pkgjs/parseargs@0.11.0': - optional: true - '@pkgr/core@0.1.2': {} '@pkgr/core@0.2.4': {} @@ -6538,7 +6496,7 @@ snapshots: fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 - semver: 7.6.0 + semver: 7.7.2 ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -6834,6 +6792,8 @@ snapshots: ansi-regex@6.0.1: {} + ansi-regex@6.5.0: {} + ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 @@ -6917,6 +6877,8 @@ snapshots: balanced-match@1.0.2: {} + balanced-match@4.0.4: {} + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 @@ -6934,6 +6896,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.12: + dependencies: + balanced-match: 4.0.4 + braces@3.0.2: dependencies: fill-range: 7.0.1 @@ -6953,7 +6919,7 @@ snapshots: bytes@3.1.2: {} - c8@10.1.3: + c8@12.0.0: dependencies: '@bcoe/v8-coverage': 1.0.2 '@istanbuljs/schema': 0.1.3 @@ -6962,9 +6928,9 @@ snapshots: istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-reports: 3.1.7 - test-exclude: 7.0.1 + test-exclude: 8.0.0 v8-to-istanbul: 9.2.0 - yargs: 17.7.2 + yargs: 18.2.0 yargs-parser: 21.1.1 cac@6.7.14: {} @@ -7064,13 +7030,13 @@ snapshots: cli-truncate@4.0.0: dependencies: slice-ansi: 5.0.0 - string-width: 7.1.0 + string-width: 7.2.0 - cliui@8.0.1: + cliui@9.0.1: dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 + string-width: 7.2.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 clone-deep@4.0.1: dependencies: @@ -7292,8 +7258,6 @@ snapshots: duplexer@0.1.2: {} - eastasianwidth@0.2.0: {} - ee-first@1.1.1: {} electron-to-chromium@1.5.161: {} @@ -7304,8 +7268,6 @@ snapshots: emoji-regex@8.0.0: {} - emoji-regex@9.2.2: {} - encodeurl@2.0.0: {} end-of-stream@1.4.4: @@ -7404,8 +7366,6 @@ snapshots: '@esbuild/win32-ia32': 0.27.1 '@esbuild/win32-x64': 0.27.1 - escalade@3.1.2: {} - escalade@3.2.0: {} escape-string-regexp@1.0.5: {} @@ -7892,6 +7852,8 @@ snapshots: get-east-asian-width@1.2.0: {} + get-east-asian-width@1.7.0: {} + get-func-name@2.0.2: {} get-intrinsic@1.3.0: @@ -7944,14 +7906,11 @@ snapshots: dependencies: is-glob: 4.0.3 - glob@10.4.5: + glob@13.0.7: dependencies: - foreground-child: 3.1.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 + minimatch: 10.2.6 + minipass: 7.1.3 + path-scurry: 2.0.2 globals@11.12.0: {} @@ -8153,12 +8112,6 @@ snapshots: 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 - jest-diff@25.5.0: dependencies: chalk: 3.0.0 @@ -8349,18 +8302,12 @@ snapshots: dependencies: get-func-name: 2.0.2 - lru-cache@10.2.0: {} - lru-cache@11.2.4: {} lru-cache@5.1.1: dependencies: yallist: 3.1.1 - lru-cache@6.0.0: - dependencies: - yallist: 4.0.0 - magic-string@0.30.11: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -8375,7 +8322,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.6.0 + semver: 7.7.2 make-error@1.3.6: {} @@ -8437,6 +8384,10 @@ snapshots: min-indent@1.0.1: {} + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.12 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -8447,7 +8398,7 @@ snapshots: minimist@1.2.8: {} - minipass@7.1.2: {} + minipass@7.1.3: {} mkdirp@3.0.1: {} @@ -8612,8 +8563,6 @@ snapshots: p-try@2.2.0: {} - package-json-from-dist@1.0.1: {} - package-manager-detector@0.2.0: {} package-manager-detector@1.3.0: {} @@ -8665,10 +8614,10 @@ snapshots: path-parse@1.0.7: {} - path-scurry@1.11.1: + path-scurry@2.0.2: dependencies: - lru-cache: 10.2.0 - minipass: 7.1.2 + lru-cache: 11.2.4 + minipass: 7.1.3 path-type@4.0.0: {} @@ -8915,8 +8864,6 @@ snapshots: dependencies: jsesc: 0.5.0 - require-directory@2.1.1: {} - require-from-string@2.0.2: {} resolve-from@4.0.0: {} @@ -8994,10 +8941,6 @@ snapshots: semver@6.3.1: {} - semver@7.6.0: - dependencies: - lru-cache: 6.0.0 - semver@7.7.2: {} serialize-error@11.0.3: @@ -9145,12 +9088,6 @@ snapshots: 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 - string-width@7.1.0: dependencies: emoji-regex: 10.3.0 @@ -9163,6 +9100,11 @@ snapshots: get-east-asian-width: 1.2.0 strip-ansi: 7.1.0 + string-width@8.3.0: + dependencies: + get-east-asian-width: 1.7.0 + strip-ansi: 7.2.0 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -9171,6 +9113,10 @@ snapshots: dependencies: ansi-regex: 6.0.1 + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.5.0 + strip-bom@3.0.0: {} strip-final-newline@3.0.0: {} @@ -9254,11 +9200,11 @@ snapshots: terminal-size@4.0.0: {} - test-exclude@7.0.1: + test-exclude@8.0.0: dependencies: '@istanbuljs/schema': 0.1.3 - glob: 10.4.5 - minimatch: 9.0.5 + glob: 13.0.7 + minimatch: 10.2.6 thread-stream@3.1.0: dependencies: @@ -9480,7 +9426,7 @@ snapshots: v8-to-istanbul@9.2.0: dependencies: - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/trace-mapping': 0.3.31 '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 @@ -9569,22 +9515,10 @@ snapshots: wordwrap@1.0.0: {} - 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 - wrap-ansi@9.0.0: dependencies: ansi-styles: 6.2.1 - string-width: 7.1.0 + string-width: 7.2.0 strip-ansi: 7.1.0 wrappy@1.0.2: {} @@ -9595,19 +9529,18 @@ snapshots: yallist@3.1.1: {} - yallist@4.0.0: {} - yargs-parser@21.1.1: {} - yargs@17.7.2: + yargs-parser@22.0.0: {} + + yargs@18.2.0: dependencies: - cliui: 8.0.1 - escalade: 3.1.2 + cliui: 9.0.1 + escalade: 3.2.0 get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 + string-width: 8.3.0 y18n: 5.0.8 - yargs-parser: 21.1.1 + yargs-parser: 22.0.0 yn@3.1.1: {}