diff --git a/deps/undici/src/changelogs/v7.30.2.md b/deps/undici/src/changelogs/v7.30.2.md new file mode 100644 index 000000000000..f2c3eb1a1a26 --- /dev/null +++ b/deps/undici/src/changelogs/v7.30.2.md @@ -0,0 +1,27 @@ +# undici 7.30.2 security fixes + +This release fixes six vulnerabilities. + +## CVE-2026-116592 / GHSA-mqg3-3v4r-cm32 (high) + +Undici 7.30.1 could cache the final response from a redirect chain under the original request key without applying the origin, cache policy, freshness, or `Vary` requirements of every intermediate hop. This could poison a cache or expose one user's response to another user. The fix validates every redirect hop, combines their `Vary` fields, limits freshness and stale serving to the most restrictive hop, and invalidates persistent SQLite entries written by vulnerable releases. + +## CVE-2026-120474 / GHSA-7xg3-fphp-28hg (medium) + +In Undici 7.x, a shared cache used with `compose(redirect(), cache())` could store a credential-dependent response from a same-origin redirect under the original URL. A later authenticated or unauthenticated request could then receive another user's response. Redirected requests carrying `Authorization`, `Cookie`, or `Proxy-Authorization` are no longer stored under the original alias key. + +## CVE-2026-116630 / GHSA-5rm8-gv32-r954 (medium) + +In Undici 7.x, a cross-origin redirect during cache revalidation could let a `304 Not Modified` response from the redirect target validate a cached response from the original origin. Undici now checks that the revalidation target matches the cached URL and that any returned validator matches the stored representation before replaying the cached body. + +## CVE-2026-120415 / GHSA-9v6h-8rgp-m69f (medium) + +In Undici 7.x, the redirect interceptor did not strip credentials correctly when request headers were supplied as an array of `[name, value]` pairs. With a header-normalizing interceptor outside `redirect()`, credentials could be sent to a cross-origin redirect target. Undici now handles both tuple arrays and flat header arrays when removing sensitive headers. + +## CVE-2026-120222 / GHSA-3g9m-rv3r-w5w2 (medium) + +In Undici 7.x, a downstream handler exception during cache replay could escape as an uncaught exception or unhandled promise rejection and terminate the process. This included `dump` size-limit failures, excessive `Content-Encoding` values in `decompress`, asynchronous cache-store failures, and cached-body replay after a `304`. These failures are now reported as request errors. + +## CVE-2026-120423 / GHSA-r4pc-4jcp-7pqc (medium) + +Undici 7.15.0 through 7.30.1 could skip Subresource Integrity verification when valid integrity metadata was separated or surrounded by ASCII whitespace other than a space, including a horizontal tab. Integrity metadata is now split on all ASCII whitespace before SHA-256, SHA-384, or SHA-512 verification. diff --git a/deps/undici/src/lib/cache/sqlite-cache-store.js b/deps/undici/src/lib/cache/sqlite-cache-store.js index 4da06c2dc27c..c5ba2def21e5 100644 --- a/deps/undici/src/lib/cache/sqlite-cache-store.js +++ b/deps/undici/src/lib/cache/sqlite-cache-store.js @@ -5,7 +5,9 @@ const { assertCacheKey, assertCacheValue } = require('../util/cache.js') let DatabaseSync -const VERSION = 3 +// Bump when entries written by an older cache policy are unsafe to reuse. +// Version 4 invalidates entries that may have been poisoned through redirects. +const VERSION = 4 // 2gb const MAX_ENTRY_SIZE = 2 * 1000 * 1000 * 1000 diff --git a/deps/undici/src/lib/core/request.js b/deps/undici/src/lib/core/request.js index 4b5887d746e9..683fb5d223fd 100644 --- a/deps/undici/src/lib/core/request.js +++ b/deps/undici/src/lib/core/request.js @@ -123,7 +123,7 @@ class Request { this.method = method - this.typeOfService = typeOfService ?? 0 + this.typeOfService = typeOfService this.abort = null diff --git a/deps/undici/src/lib/core/util.js b/deps/undici/src/lib/core/util.js index 767d586b93a8..2a730a86cd95 100644 --- a/deps/undici/src/lib/core/util.js +++ b/deps/undici/src/lib/core/util.js @@ -507,6 +507,26 @@ function parseRawHeaders (headers) { return ret } +/** + * @param {Record} headers + * @returns {Buffer[]} + */ +function toRawHeaders (headers) { + const rawHeaders = [] + + for (const [name, value] of Object.entries(headers)) { + if (Array.isArray(value)) { + for (const entry of value) { + rawHeaders.push(Buffer.from(name, 'latin1'), Buffer.from(`${entry}`, 'latin1')) + } + } else { + rawHeaders.push(Buffer.from(name, 'latin1'), Buffer.from(`${value}`, 'latin1')) + } + } + + return rawHeaders +} + /** * @param {string[]} headers * @param {Buffer[]} headers @@ -961,6 +981,7 @@ module.exports = { removeAllListeners, errorRequest, parseRawHeaders, + toRawHeaders, encodeRawHeaders, parseHeaders, parseKeepAliveTimeout, diff --git a/deps/undici/src/lib/dispatcher/client-h1.js b/deps/undici/src/lib/dispatcher/client-h1.js index dd01b7af83a3..385f59e8aa29 100644 --- a/deps/undici/src/lib/dispatcher/client-h1.js +++ b/deps/undici/src/lib/dispatcher/client-h1.js @@ -61,6 +61,7 @@ const removeAllListeners = util.removeAllListeners const kIdleSocketValidation = Symbol('kIdleSocketValidation') const kIdleSocketValidationTimeout = Symbol('kIdleSocketValidationTimeout') const kSocketUsed = Symbol('kSocketUsed') +const kTypeOfService = Symbol('kTypeOfService') let extractBody @@ -1109,6 +1110,32 @@ function shouldSendContentLength (method) { return method !== 'GET' && method !== 'HEAD' && method !== 'OPTIONS' && method !== 'TRACE' && method !== 'CONNECT' } +function setTypeOfService (socket, request) { + if (typeof socket.setTypeOfService !== 'function') { + return + } + + const typeOfService = request.typeOfService + + if (typeOfService === undefined) { + return + } + + const currentTypeOfService = socket[kTypeOfService] + + if (currentTypeOfService === typeOfService) { + return + } + + try { + socket.setTypeOfService(typeOfService) + socket[kTypeOfService] = typeOfService + } catch { + // QoS marking is best-effort. setTypeOfService() can throw synchronously on + // some platforms depending on socket state, but that must not abort the request. + } +} + /** * @param {import('./client.js')} client * @param {import('../core/request.js')} request @@ -1248,9 +1275,7 @@ function writeH1 (client, request) { socket[kBlocking] = true } - if (socket.setTypeOfService) { - socket.setTypeOfService(request.typeOfService) - } + setTypeOfService(socket, request) let header = `${method} ${path} HTTP/1.1\r\n` diff --git a/deps/undici/src/lib/handler/cache-handler.js b/deps/undici/src/lib/handler/cache-handler.js index 1c58abdd845a..87c767621ce6 100644 --- a/deps/undici/src/lib/handler/cache-handler.js +++ b/deps/undici/src/lib/handler/cache-handler.js @@ -10,6 +10,17 @@ const { isInvalidOrWildcardVaryHeader, isEtagUsable } = require('../util/cache') + +/** + * A suppressed redirect hop recorded by the redirect handler. Carried on + * {@link kRedirectCacheControl} and inspected by the cache handler before the + * final response is stored under the original request key. + * + * @typedef {object} RedirectHop + * @property {number} statusCode The hop's response status code (e.g. 302). + * @property {import('../../types/header.d.ts').IncomingHttpHeaders} headers The hop's response headers. + * @property {number} receivedAt The time the hop's response headers were received. + */ const { parseHttpDate } = require('../util/date.js') function noop () {} @@ -43,6 +54,10 @@ const NOT_UNDERSTOOD_STATUS_CODES = [ const MAX_RESPONSE_AGE = 2147483647000 +// Retention for revalidation-only entries (zero freshness lifetime but a +// validator present); each successful revalidation re-stores the entry. +const REVALIDATION_ONLY_RETENTION = 86400000 // 24 hours + function trimOWS (value) { return value.replace(/^[\t ]+|[\t ]+$/g, '') } @@ -57,6 +72,16 @@ function arrayIncludes (array, value) { return false } +function appendVaryValues (target, varyValue) { + if (Array.isArray(varyValue)) { + for (let i = 0; i < varyValue.length; i++) { + target.push(varyValue[i]) + } + } else if (varyValue != null) { + target.push(varyValue) + } +} + function appendConnectionHeaderTokens (headersToRemove, connectionHeader) { const values = Array.isArray(connectionHeader) ? connectionHeader : [connectionHeader] @@ -129,6 +154,25 @@ function invalidateUnsafeRequest (store, cacheKey, resHeaders) { deleteLocationTargets(store, cacheKey, resHeaders['content-location']) } +/** + * Whether the original request carried a credential that is not reflected in + * the cache key. The memory/sqlite stores key an entry on origin, method, path + * and `vary` only, so a credentialed request that is redirected to a resource + * that varies per principal must not be stored under the original (alias) key: + * a later caller would be served the first principal's body. The set mirrors the + * request credentials the redirect handler strips across origins (`authorization`, + * `cookie`, `proxy-authorization`). + * + * @param {import('../../types/header.d.ts').IncomingHttpHeaders | undefined} headers + * @returns {boolean} + */ +function requestCarriesCredentials (headers) { + return headers != null && ( + Object.hasOwn(headers, 'authorization') || + Object.hasOwn(headers, 'cookie') || + Object.hasOwn(headers, 'proxy-authorization') + ) +} /** * @typedef {import('../../types/dispatcher.d.ts').default.DispatchHandler} DispatchHandler * @@ -168,11 +212,19 @@ class CacheHandler { /** * The URLs visited while following redirects, shared by reference from the * redirect handler through the request context. Carries the suppressed hops' - * cache-control under {@link kRedirectCacheControl}. + * status/headers under {@link kRedirectCacheControl}. * @type {URL[] | undefined} */ #history + #replaying304 = false + #suppress304End = false + + /** + * @type {{ controller: import('../../types/dispatcher.d.ts').default.DispatchController, trailers: import('../../types/header.d.ts').IncomingHttpHeaders } | undefined} + */ + #pending304End + /** * @param {import('../../types/cache-interceptor.d.ts').default.CacheHandlerOptions} opts * @param {import('../../types/cache-interceptor.d.ts').default.CacheKey} cacheKey @@ -189,6 +241,9 @@ class CacheHandler { onRequestStart (controller, context) { this.#writeStream?.destroy() this.#writeStream = undefined + this.#replaying304 = false + this.#suppress304End = false + this.#pending304End = undefined // The redirect handler mutates this shared history as redirects are // followed, allowing the cache to identify the response's actual origin. this.#history = context?.history @@ -231,29 +286,62 @@ class CacheHandler { return downstreamOnHeaders() } - // Never store a response produced by a different origin under the original - // request's cache key. - if (this.#history && this.#history.length > 0) { - const finalUrl = this.#history[this.#history.length - 1] - if (!sameOrigin(finalUrl.origin, this.#cacheKey.origin)) { - return downstreamOnHeaders() - } + // A credential-bearing request that was redirected must not have the final + // hop's response stored under the original request's key. The cache key + // does not include the credential, and the redirect target may vary per + // principal (e.g. `/me` -> `/profile/{user}`), so replaying the body under + // the alias key would leak one principal's data to another — or to an + // unauthenticated caller — from a shared cache. The final hop's permissive + // cache-control (e.g. `public`) does not authorize this: the credential was + // presented to the original hop, not the resource that actually produced + // the body. Fail closed. A history with more than one entry means at least + // one redirect was actually followed (a single non-redirected hop records + // exactly one entry), so a plain revalidation is not mistaken for a redirect. + if ( + this.#history && this.#history.length > 1 && + requestCarriesCredentials(this.#cacheKey.headers) + ) { + return downstreamOnHeaders() } - // Preserve restrictive cache policy from suppressed redirect responses. - const redirectCacheControl = this.#history?.[kRedirectCacheControl] - if (redirectCacheControl) { - for (const hopCacheControl of redirectCacheControl) { - const hopDirectives = hopCacheControl ? parseCacheControlHeader(hopCacheControl) : {} - if ( - hopDirectives['no-store'] === true || - (this.#cacheType === 'shared' && hopDirectives.private === true) - ) { + // A cross-origin redirect can change the origin that actually produced the + // final response. Keying that response on the original (trusted) origin + // would let a redirect target control an entry for a URL the application + // trusts. Every hop in the redirect chain must stay on the cache key's + // origin. An intermediate cross-origin hop can bounce back to the trusted + // origin (or to any cacheable asset there) even when the final response + // comes from the trusted origin, so checking only the final URL is not + // enough. + if (this.#history && this.#history.length > 0) { + for (const hopUrl of this.#history) { + if (!sameOrigin(hopUrl.origin, this.#cacheKey.origin)) { return downstreamOnHeaders() } } } + // A redirect hop that is not forwarded can still carry a storage policy + // (for example `no-store`, `private` for a shared cache, `no-cache`, + // `must-revalidate`, zero freshness, or `Vary: *`) that the final response + // body does not inherit. Honor it, otherwise a redirect that must not be + // stored (or that selects a private/authenticated target) could be + // laundered into a cacheable final response under the original key. + const now = Date.now() + const redirectHopInfo = this.#history?.[kRedirectCacheControl] + const redirectPolicy = redirectHopInfo?.length > 0 + ? getRedirectPolicy( + this.#cacheType, + this.#cacheKey.method, + redirectHopInfo, + this.#cacheKey.headers, + this.#cacheByDefault, + now + ) + : undefined + if (redirectHopInfo?.length > 0 && redirectPolicy === undefined) { + return downstreamOnHeaders() + } + const cacheControlHeader = resHeaders['cache-control'] const cacheControlDirectives = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {} @@ -286,7 +374,6 @@ class CacheHandler { return downstreamOnHeaders() } - const now = Date.now() const resAge = Object.hasOwn(resHeaders, 'age') ? getAge(resHeaders.age) : undefined if (resAge !== undefined && resAge >= MAX_RESPONSE_AGE) { // Response considered stale @@ -303,10 +390,18 @@ class CacheHandler { const apparentAge = resDate ? Math.max(0, now - resDate.getTime()) : 0 const currentAge = Math.max(apparentAge, resAge ?? 0) + const hasValidator = + (typeof resHeaders.etag === 'string' && isEtagUsable(resHeaders.etag)) || + typeof resHeaders['last-modified'] === 'string' + const staleAt = - determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives) ?? + determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives, hasValidator) ?? this.#cacheByDefault - if (staleAt === undefined || currentAge >= staleAt) { + // Zero freshness lifetime but a validator: stale from the start, yet still + // storable since each reuse is preceded by a revalidation request. + // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2.4 + const revalidationOnly = staleAt === 0 && hasValidator + if (staleAt === undefined || (currentAge >= staleAt && !revalidationOnly)) { if (cacheControlHeader || staleAt !== undefined) { deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey) } @@ -315,24 +410,65 @@ class CacheHandler { } const baseTime = now - currentAge - const absoluteStaleAt = staleAt + baseTime - if (now >= absoluteStaleAt) { + let absoluteStaleAt = staleAt + baseTime + if (redirectPolicy !== undefined) { + absoluteStaleAt = Math.min(absoluteStaleAt, redirectPolicy.staleAt) + } + if (now >= absoluteStaleAt && !revalidationOnly) { // Response is already stale deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey) return downstreamOnHeaders() } + // Union the `Vary` of every suppressed redirect hop with the final + // response's `Vary`. A 3xx hop that negotiates its target on `Authorization` + // / `Cookie` (or any other header) must make the stored entry vary on those + // headers too, or an authenticated user's private response would be served + // to unrelated callers. let varyDirectives - if (this.#cacheKey.headers && resHeaders.vary) { - varyDirectives = parseVaryHeader(resHeaders.vary, this.#cacheKey.headers) - if (!varyDirectives) { - // Parse error - return downstreamOnHeaders() + const combinedVary = [] + if (redirectHopInfo) { + for (const hop of redirectHopInfo) { + appendVaryValues(combinedVary, hop?.headers?.vary) + } + } + appendVaryValues(combinedVary, resHeaders.vary) + if (combinedVary.length > 0) { + for (const varyHeader of combinedVary) { + if (hasVaryStar(varyHeader)) { + // `Vary: *` means the response can never be reused (RFC 9111 §4.1) + return downstreamOnHeaders() + } + } + if (this.#cacheKey.headers) { + varyDirectives = parseVaryHeader(combinedVary, this.#cacheKey.headers) + if (!varyDirectives) { + // Parse error + return downstreamOnHeaders() + } + } + } + + // When the entry was folded from a redirect chain, the final response's + // stale-serving directives (RFC 5861) must not outlive the hops' freshness. + // A hop that grants no `stale-while-revalidate` / `stale-if-error` caps + // stale serving at its freshness, so the final response cannot launder a + // stale-serving window past the hop-bounded `staleAt`. Drop those directives + // (and keep the `proxy-revalidate` the hop policy may require) so the entry + // revalidates at `staleAt` instead of being served stale for the final + // response's window. + let effectiveCacheControlDirectives = cacheControlDirectives + if (redirectPolicy !== undefined) { + effectiveCacheControlDirectives = { ...cacheControlDirectives } + delete effectiveCacheControlDirectives['stale-while-revalidate'] + delete effectiveCacheControlDirectives['stale-if-error'] + if (redirectPolicy.requiresRevalidation === true) { + effectiveCacheControlDirectives['proxy-revalidate'] = true } } const cachedAt = baseTime - const deleteAt = determineDeleteAt(baseTime, now, cacheControlDirectives, absoluteStaleAt) + const deleteAt = determineDeleteAt(baseTime, now, effectiveCacheControlDirectives, absoluteStaleAt) const strippedHeaders = stripNecessaryHeaders(resHeaders, cacheControlDirectives) /** @@ -343,7 +479,7 @@ class CacheHandler { statusMessage, headers: strippedHeaders, vary: varyDirectives, - cacheControlDirectives, + cacheControlDirectives: effectiveCacheControlDirectives, cachedAt, staleAt: absoluteStaleAt, deleteAt @@ -352,10 +488,51 @@ class CacheHandler { // Not modified, re-use the cached value // https://www.rfc-editor.org/rfc/rfc9111.html#name-handling-304-not-modified if (statusCode === 304) { + this.#replaying304 = true + let done = false + const finish304 = () => { + if (done) { + return + } + done = true + this.#replaying304 = false + if (this.#pending304End) { + const { controller, trailers } = this.#pending304End + this.#pending304End = undefined + this.#writeStream?.end() + this.#handler.onResponseEnd?.(controller, trailers) + } + } + + // The cached body below is replayed to the downstream handler from later + // stream ticks (or an iterator loop), outside the dispatcher's own error + // handling, so a throwing downstream handler must be converged to a + // per-request error instead of escaping as an uncaught exception. + const failReplay = (err) => { + if (done) { + return + } + done = true + this.#replaying304 = false + this.#suppress304End = true + this.#pending304End = undefined + this.#writeStream?.destroy() + // The v7 handler API has no downstream block/release controller. Keep + // the origin response lifecycle independent, suppress its completion, + // and report the replay failure directly downstream. + try { + this.#handler.onResponseError?.(controller, err) + } catch { + // Never let a missing legacy error callback escape this async replay. + } + } + const handle304 = (cachedValue) => { if (!cachedValue) { // Do not create a new cache entry, as a 304 won't have a body - so cannot be cached. - return downstreamOnHeaders() + downstreamOnHeaders() + finish304() + return } // Re-use the cached value: statuscode, statusmessage, headers and body @@ -370,6 +547,7 @@ class CacheHandler { this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value) if (!this.#writeStream || !cachedValue?.body) { + finish304() return } @@ -377,13 +555,21 @@ class CacheHandler { const bodyIterator = cachedValue.body.values() const streamCachedBody = () => { - for (const chunk of bodyIterator) { - const full = this.#writeStream.write(chunk) === false - this.#handler.onResponseData?.(controller, chunk) - // when stream is full stop writing until we get a 'drain' event - if (full) { - break + if (done) { + return + } + try { + for (const chunk of bodyIterator) { + const full = this.#writeStream?.write(chunk) === false + this.#handler.onResponseData?.(controller, chunk) + // when stream is full stop writing until we get a 'drain' event + if (full) { + return + } } + finish304() + } catch (err) { + failReplay(err) } } @@ -391,6 +577,8 @@ class CacheHandler { .on('error', function () { handler.#writeStream = undefined handler.#store.delete(handler.#cacheKey) + // Keep replaying downstream without the store. + streamCachedBody() }) .on('drain', () => { streamCachedBody() @@ -398,6 +586,8 @@ class CacheHandler { .on('close', function () { if (handler.#writeStream === this) { handler.#writeStream = undefined + // Keep replaying downstream without the store. + streamCachedBody() } }) @@ -406,15 +596,22 @@ class CacheHandler { // Readable stream body (e.g. from async/remote cache stores) cachedValue.body .on('data', (chunk) => { - this.#writeStream.write(chunk) - this.#handler.onResponseData?.(controller, chunk) + try { + this.#writeStream?.write(chunk) + this.#handler.onResponseData?.(controller, chunk) + } catch (err) { + cachedValue.body.destroy() + failReplay(err) + } }) .on('end', () => { - this.#writeStream.end() + this.#writeStream?.end() + finish304() }) .on('error', () => { this.#writeStream = undefined this.#store.delete(this.#cacheKey) + finish304() }) this.#writeStream @@ -427,6 +624,8 @@ class CacheHandler { handler.#writeStream = undefined } }) + } else { + finish304() } } @@ -435,7 +634,9 @@ class CacheHandler { */ const result = this.#store.get(this.#cacheKey) if (result && typeof result.then === 'function') { - result.then(handle304) + result.then(handle304, () => handle304(undefined)).catch((err) => { + failReplay(err) + }) } else { handle304(result) } @@ -482,11 +683,21 @@ class CacheHandler { } onResponseEnd (controller, trailers) { + if (this.#suppress304End) { + this.#suppress304End = false + return + } + if (this.#replaying304) { + this.#pending304End = { controller, trailers } + return + } this.#writeStream?.end() this.#handler.onResponseEnd?.(controller, trailers) } onResponseError (controller, err) { + this.#replaying304 = false + this.#pending304End = undefined this.#writeStream?.destroy(err) this.#writeStream = undefined this.#handler.onResponseError?.(controller, err) @@ -604,6 +815,139 @@ function canCacheResponse (cacheType, method, statusCode, resHeaders, cacheContr return true } +/** + * Determine the absolute freshness deadline imposed by all suppressed redirect + * hops. Returning `undefined` means at least one hop cannot safely be folded + * into the final response under the original request key. + * + * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType + * @param {string} method + * @param {RedirectHop[]} redirectHops + * @param {import('../../types/header.d.ts').IncomingHttpHeaders} reqHeaders + * @param {number | undefined} cacheByDefault + * @param {number} now + * @returns {{ staleAt: number, requiresRevalidation: boolean } | undefined} + */ +function getRedirectPolicy (cacheType, method, redirectHops, reqHeaders, cacheByDefault, now) { + let staleAt = Infinity + let requiresRevalidation = false + + for (const hop of redirectHops) { + const hopPolicy = getRedirectHopPolicy(cacheType, method, hop, reqHeaders, cacheByDefault) + if (hopPolicy === undefined || hopPolicy.staleAt <= now) { + return undefined + } + + staleAt = Math.min(staleAt, hopPolicy.staleAt) + requiresRevalidation ||= hopPolicy.requiresRevalidation + } + + return { staleAt, requiresRevalidation } +} + +/** + * Calculate one redirect hop's absolute freshness deadline using the same age, + * date, expiration, invalid-directive, and heuristic rules as a final response. + * + * @param {import('../../types/cache-interceptor.d.ts').default.CacheOptions['type']} cacheType + * @param {string} method + * @param {RedirectHop} hop + * @param {import('../../types/header.d.ts').IncomingHttpHeaders} reqHeaders + * @param {number | undefined} cacheByDefault + * @returns {{ staleAt: number, requiresRevalidation: boolean } | undefined} + */ +function getRedirectHopPolicy (cacheType, method, hop, reqHeaders, cacheByDefault) { + if (!Number.isInteger(hop?.statusCode) || !Number.isFinite(hop?.receivedAt)) { + return undefined + } + + const hopHeaders = hop.headers ?? {} + const cacheControlHeader = hopHeaders['cache-control'] + const hopCacheControl = cacheControlHeader + ? parseCacheControlHeader(cacheControlHeader) + : {} + + // https://www.rfc-editor.org/rfc/rfc9111.html#section-4.1-5 + if (hopHeaders.vary && hasVaryStar(hopHeaders.vary)) { + return undefined + } + + if (hopCacheControl['no-store'] === true) { + return undefined + } + + // A qualified `private` directive still marks the named fields as private. + // Folding a redirect that says `private="location"` would preserve the + // private target choice in the final body even though a shared cache is not + // allowed to store that Location field. + if (cacheType === 'shared' && Object.hasOwn(hopCacheControl, 'private')) { + return undefined + } + + // These directives require the hop to be revalidated before reuse. Since the + // cache stores only the final response, it cannot independently validate the + // suppressed redirect response. + if ( + Object.hasOwn(hopCacheControl, 'no-cache') || + hopCacheControl['must-revalidate'] === true || + (cacheType === 'shared' && hopCacheControl['proxy-revalidate'] === true) + ) { + return undefined + } + + const heuristicallyCacheable = + hopHeaders['last-modified'] && + arrayIncludes(HEURISTICALLY_CACHEABLE_STATUS_CODES, hop.statusCode) + if ( + !cacheControlHeader && + !hopHeaders.expires && + !heuristicallyCacheable && + !cacheByDefault + ) { + return undefined + } + + if (!canCacheResponse(cacheType, method, hop.statusCode, hopHeaders, hopCacheControl, reqHeaders)) { + return undefined + } + + const age = Object.hasOwn(hopHeaders, 'age') ? getAge(hopHeaders.age) : undefined + if (age !== undefined && age >= MAX_RESPONSE_AGE) { + return undefined + } + + const responseDate = Object.hasOwn(hopHeaders, 'date') ? getDate(hopHeaders.date) : undefined + if (responseDate === null) { + return undefined + } + + const apparentAge = responseDate ? Math.max(0, hop.receivedAt - responseDate.getTime()) : 0 + const currentAge = Math.max(apparentAge, age ?? 0) + const hasValidator = + (typeof hopHeaders.etag === 'string' && isEtagUsable(hopHeaders.etag)) || + typeof hopHeaders['last-modified'] === 'string' + const freshnessLifetime = + determineStaleAt( + cacheType, + hop.receivedAt, + age, + hopHeaders, + responseDate, + hopCacheControl, + hasValidator + ) ?? cacheByDefault + + if (freshnessLifetime === undefined) { + return undefined + } + + return { + staleAt: hop.receivedAt - currentAge + freshnessLifetime, + // RFC 9111 §5.2.2.10: s-maxage implies proxy-revalidate for shared caches. + requiresRevalidation: cacheType === 'shared' && Object.hasOwn(hopCacheControl, 's-maxage') + } +} + /** * @param {string | string[]} dateHeader * @returns {Date | null | undefined} @@ -658,10 +1002,12 @@ function getAge (ageHeader) { * @param {import('../../types/header.d.ts').IncomingHttpHeaders} resHeaders * @param {Date | undefined} responseDate * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives} cacheControlDirectives + * @param {boolean} hasValidator whether the response has a validator (etag or + * last-modified) that revalidation requests can be made with * * @returns {number | undefined} time that the value is stale at in seconds or undefined if it shouldn't be cached */ -function determineStaleAt (cacheType, now, age, resHeaders, responseDate, cacheControlDirectives) { +function determineStaleAt (cacheType, now, age, resHeaders, responseDate, cacheControlDirectives, hasValidator) { if (cacheType === 'shared') { // Prioritize s-maxage since we're a shared cache // s-maxage > max-age > Expire @@ -735,6 +1081,12 @@ function determineStaleAt (cacheType, now, age, resHeaders, responseDate, cacheC return 31536000000 } + if (cacheControlDirectives['no-cache'] === true && hasValidator) { + // No freshness source, but a validator lets us revalidate before reuse. + // https://www.rfc-editor.org/rfc/rfc9111.html#section-5.2.2.4 + return 0 + } + return undefined } @@ -771,6 +1123,11 @@ function determineDeleteAt (baseTime, cachedAt, cacheControlDirectives, staleAt) // revalidated. if (staleWhileRevalidate === -Infinity && staleIfError === -Infinity && immutable === -Infinity) { const freshnessLifetime = staleAt - baseTime + if (freshnessLifetime <= 0) { + // Revalidation-only entry: no freshness lifetime to size the buffer on, + // so retain it for a bounded window instead. + return cachedAt + REVALIDATION_ONLY_RETENTION + } const datePrecisionPadding = Math.min(Math.max(cachedAt - baseTime, 0), 1000) return staleAt + freshnessLifetime + datePrecisionPadding } diff --git a/deps/undici/src/lib/handler/redirect-handler.js b/deps/undici/src/lib/handler/redirect-handler.js index 4084ad5e25cb..c62e491c9737 100644 --- a/deps/undici/src/lib/handler/redirect-handler.js +++ b/deps/undici/src/lib/handler/redirect-handler.js @@ -47,7 +47,12 @@ class RedirectHandler { this.maxRedirections = maxRedirections this.handler = handler this.history = [] - // Retain cache-control from suppressed redirect hops for an outer cache. + // Per-hop metadata for each intermediate (suppressed) redirect hop: the + // hop's status code and response headers. An outer cache uses it to honor a + // hop's storage policy (e.g. `no-store`, `no-cache`, `Vary: *`) that would + // otherwise be lost because the hop's response is not forwarded. It travels + // as a non-enumerable property of the history array so it reaches the cache + // without becoming part of the public request/response context. Object.defineProperty(this.history, kRedirectCacheControl, { value: [], enumerable: false @@ -135,7 +140,14 @@ class RedirectHandler { return } - this.history[kRedirectCacheControl].push(headers['cache-control']) + // This hop's response is suppressed (only its Location is used). Record its + // status and headers so an outer cache can honor a restrictive policy that + // would otherwise be lost when the final response is stored. + this.history[kRedirectCacheControl].push({ + statusCode, + headers: { ...headers }, + receivedAt: Date.now() + }) const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))) const path = search ? `${pathname}${search}` : pathname @@ -223,9 +235,25 @@ function shouldRemoveHeader (header, removeContent, unknownOrigin) { function cleanRequestHeaders (headers, removeContent, unknownOrigin) { const ret = [] if (Array.isArray(headers)) { - for (let i = 0; i < headers.length; i += 2) { - if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { - ret.push(headers[i], headers[i + 1]) + // Headers may be either a flat alternating [name, value, name, value, ...] + // list or an iterable of [name, value] pairs. A plain JavaScript array of + // tuples (e.g. `Object.entries(headers)`) satisfies the iterable-of-pairs + // public type, so we must distinguish the two representations before + // iterating. Treating every Array as a flat list misreads each tuple as a + // header name/value pair and defeats the cross-origin credential stripping. + if (headers.length > 0 && Array.isArray(headers[0])) { + // Array of [name, value] pairs. + for (const [key, value] of headers) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + ret.push(key, value) + } + } + } else { + // Flat alternating [name, value, name, value, ...] list. + for (let i = 0; i < headers.length; i += 2) { + if (!shouldRemoveHeader(headers[i], removeContent, unknownOrigin)) { + ret.push(headers[i], headers[i + 1]) + } } } } else if (headers && typeof headers === 'object') { diff --git a/deps/undici/src/lib/interceptor/cache.js b/deps/undici/src/lib/interceptor/cache.js index 149cf8904da4..3f724dd2261e 100644 --- a/deps/undici/src/lib/interceptor/cache.js +++ b/deps/undici/src/lib/interceptor/cache.js @@ -6,7 +6,16 @@ const util = require('../core/util') const CacheHandler = require('../handler/cache-handler') const MemoryCacheStore = require('../cache/memory-cache-store') const CacheRevalidationHandler = require('../handler/cache-revalidation-handler') -const { assertCacheStore, assertCacheMethods, makeCacheKey, normalizeHeaders, parseCacheControlHeader, isInvalidOrWildcardVaryHeader } = require('../util/cache.js') +const { + assertCacheStore, + assertCacheMethods, + makeCacheKey, + normalizeHeaders, + parseCacheControlHeader, + isInvalidOrWildcardVaryHeader, + parseVaryHeader, + isEtagUsable +} = require('../util/cache.js') const { AbortError } = require('../core/errors.js') const { parseHttpDate } = require('../util/date.js') @@ -138,6 +147,25 @@ function revalidationResponseUpdatesCacheControl (headers) { return headers['cache-control'] !== undefined } +/** + * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result + * @param {Record | undefined} varyDirectives + * @returns {boolean} + */ +function revalidationResponseAddsVary (result, varyDirectives) { + if (!varyDirectives) { + return false + } + + for (const key in varyDirectives) { + if (result.vary == null || !Object.hasOwn(result.vary, key)) { + return true + } + } + + return false +} + function deleteCachedValue (store, cacheKey) { try { store.delete(cacheKey)?.catch?.(nop) @@ -174,6 +202,47 @@ function makeRevalidationHeaders (opts, result) { return headers } +function revalidationTargetMatchesCacheKey (cacheKey, context) { + const history = context?.history + if (!Array.isArray(history) || history.length === 0) { + return true + } + + try { + const cachedUrl = new URL(cacheKey.path, cacheKey.origin) + const responseUrl = history[history.length - 1] + return responseUrl.origin === cachedUrl.origin && + responseUrl.pathname === cachedUrl.pathname && + responseUrl.search === cachedUrl.search + } catch { + return false + } +} + +function revalidationEtagMatchesCachedValue (result, headers) { + if (!Object.hasOwn(headers, 'etag')) { + return true + } + + const responseEtag = headers.etag + const cachedEtag = result.etag + if ( + typeof responseEtag !== 'string' || + typeof cachedEtag !== 'string' || + !isEtagUsable(responseEtag) || + !isEtagUsable(cachedEtag) + ) { + return false + } + + if (!responseEtag.startsWith('W/')) { + return responseEtag === cachedEtag + } + + const cachedOpaqueTag = cachedEtag.startsWith('W/') ? cachedEtag.slice(2) : cachedEtag + return responseEtag.slice(2) === cachedOpaqueTag +} + /** * @param {import('../../types/cache-interceptor.d.ts').default.GetResult} result * @param {import('../../types/cache-interceptor.d.ts').default.CacheControlDirectives | undefined} cacheControlDirectives @@ -316,21 +385,35 @@ function sendCachedValue (handler, opts, result, age, context, isStale) { stream .on('error', function (err) { + // Never rethrow: this runs from a stream event on a later tick, where a + // throw would crash the process. Like core's Request.onResponseError, + // the error is dropped if the handler has no onResponseError. if (!this.readableEnded) { - if (typeof handler.onResponseError === 'function') { - handler.onResponseError(controller, err) - } else { - throw err - } + handler.onResponseError?.(controller, err) } }) .on('close', function () { if (!this.errored) { - handler.onResponseEnd?.(controller, {}) + try { + handler.onResponseEnd?.(controller, {}) + } catch (err) { + // The stream is already closed, so the error can't be routed + // through it; report it to the handler directly instead. + handler.onResponseError?.(controller, err) + } } }) - handler.onRequestStart?.(controller, context) + // Downstream handler calls below run outside the dispatcher's own error + // handling (on later ticks for the body, or inside a promise callback for + // async stores), so a throw must be converged to a per-request error + // instead of escaping as an uncaught exception. + try { + handler.onRequestStart?.(controller, context) + } catch (err) { + stream.destroy(err) + return + } if (stream.destroyed) { return @@ -346,13 +429,24 @@ function sendCachedValue (handler, opts, result, age, context, isStale) { headers.warning = '110 - "response is stale"' } - handler.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage) + controller.rawHeaders = util.toRawHeaders(headers) + + try { + handler.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage) + } catch (err) { + stream.destroy(err) + return + } if (opts.method === 'HEAD') { stream.destroy() } else { stream.on('data', function (chunk) { - handler.onResponseData?.(controller, chunk) + try { + handler.onResponseData?.(controller, chunk) + } catch (err) { + stream.destroy(err) + } }) } } @@ -450,6 +544,14 @@ function handleResult ( } const headers = makeRevalidationHeaders(opts, result) + const refetch = () => { + if (util.isStream(result.body)) { + result.body.on('error', nop).destroy() + } + + deleteCachedValue(globalOpts.store, cacheKey) + return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler)) + } // We need to revalidate the response return dispatch( @@ -461,17 +563,18 @@ function handleResult ( (success, context, statusCode, headers) => { if (success) { if (statusCode === 304) { - if (revalidationResponseDisallowsCachedReuse(globalOpts.type, headers)) { - if (util.isStream(result.body)) { - result.body.on('error', nop).destroy() - } - - deleteCachedValue(globalOpts.store, cacheKey) - return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler)) + if ( + !revalidationTargetMatchesCacheKey(cacheKey, context) || + !revalidationEtagMatchesCachedValue(result, headers) || + revalidationResponseDisallowsCachedReuse(globalOpts.type, headers) + ) { + return refetch() } if (revalidationResponseUpdatesCacheControl(headers)) { deleteCachedValue(globalOpts.store, cacheKey) + } else if (revalidationResponseAddsVary(result, headers.vary ? parseVaryHeader(headers.vary, opts.headers) : undefined)) { + return refetch() } } @@ -605,6 +708,28 @@ module.exports = (opts = {}) => { reqCacheControl, result )) + .catch((err) => { + // Any throw escaping handleResult on the async-store path (e.g. a + // rejection from store.get() itself, or a throw in a code path not + // converged by sendCachedValue) would otherwise surface as an + // unhandled promise rejection and crash the process. Route it to + // the handler instead, matching the synchronous store path where + // the error propagates to the request() call site. + if (typeof handler.onResponseError === 'function') { + handler.onResponseError({ + rawHeaders: [], + rawTrailers: [], + pause () {}, + resume () {}, + get paused () { return false }, + get aborted () { return false }, + get reason () { return null }, + abort () {} + }, err) + } else { + throw err + } + }) } else { return handleResult( dispatch, diff --git a/deps/undici/src/lib/interceptor/decompress.js b/deps/undici/src/lib/interceptor/decompress.js index 9f7f61ad2a9d..769b7ed12045 100644 --- a/deps/undici/src/lib/interceptor/decompress.js +++ b/deps/undici/src/lib/interceptor/decompress.js @@ -429,7 +429,13 @@ class DecompressHandler extends DecoratorHandler { * @returns {void} */ onResponseStart (controller, statusCode, headers, statusMessage) { - const contentEncoding = headers['content-encoding'] + // Repeated field lines reach us as an array. RFC 9110 section 5.3 lets a + // recipient join them with commas, which yields the single-line form the + // decompression chain already handles. + const rawContentEncoding = headers['content-encoding'] + const contentEncoding = Array.isArray(rawContentEncoding) + ? rawContentEncoding.join(',') + : rawContentEncoding // If content encoding is not supported or status code is in skip list if (this.#shouldSkipDecompression(contentEncoding, statusCode)) { diff --git a/deps/undici/src/lib/llhttp/wasm_build_env.txt b/deps/undici/src/lib/llhttp/wasm_build_env.txt index bc92cff4dfd3..8f7ac48d7c33 100644 --- a/deps/undici/src/lib/llhttp/wasm_build_env.txt +++ b/deps/undici/src/lib/llhttp/wasm_build_env.txt @@ -1,5 +1,5 @@ -> undici@7.30.1 build:wasm +> undici@7.30.2 build:wasm > node build/wasm.js --docker > docker run --rm --platform=linux/x86_64 --user 1001:1001 --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/lib/llhttp,target=/home/node/build/lib/llhttp --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/build,target=/home/node/build/build --mount type=bind,source=/home/runner/work/node/node/deps/undici/src/deps,target=/home/node/build/deps -t ghcr.io/nodejs/wasm-builder@sha256:975f391d907e42a75b8c72eb77c782181e941608687d4d8694c3e9df415a0970 node build/wasm.js diff --git a/deps/undici/src/lib/util/cache.js b/deps/undici/src/lib/util/cache.js index da8ae122873a..b078ea0d936f 100644 --- a/deps/undici/src/lib/util/cache.js +++ b/deps/undici/src/lib/util/cache.js @@ -192,15 +192,48 @@ function normalizeHeaders (opts) { headers = {} if (hasSafeIterator(opts.headers)) { - for (const x of opts.headers) { - if (!Array.isArray(x)) { - throw new Error('opts.headers is not a valid header map') + if (Array.isArray(opts.headers)) { + // Array format: either flat alternating [key, value, ...] or an array + // of [key, value] pairs. + if (Array.isArray(opts.headers[0])) { + for (const x of opts.headers) { + if (!Array.isArray(x)) { + throw new Error('opts.headers is not a valid header map') + } + const [key, val] = x + if (typeof key !== 'string' || typeof val !== 'string') { + throw new Error('opts.headers is not a valid header map') + } + appendHeader(headers, key, val) + } + } else { + if (opts.headers.length % 2 !== 0) { + throw new Error('opts.headers is not a valid header map') + } + for (let i = 0; i < opts.headers.length; i += 2) { + const key = opts.headers[i] + const val = opts.headers[i + 1] + if (typeof key !== 'string' || (typeof val !== 'string' && !Array.isArray(val))) { + throw new Error('opts.headers is not a valid header map') + } + if (typeof val === 'string') { + appendHeader(headers, key, val) + } else { + appendHeader(headers, key, val.map(item => typeof item === 'string' ? item : item.toString('latin1'))) + } + } } - const [key, val] = x - if (typeof key !== 'string' || typeof val !== 'string') { - throw new Error('opts.headers is not a valid header map') + } else { + for (const x of opts.headers) { + if (!Array.isArray(x)) { + throw new Error('opts.headers is not a valid header map') + } + const [key, val] = x + if (typeof key !== 'string' || typeof val !== 'string') { + throw new Error('opts.headers is not a valid header map') + } + appendHeader(headers, key, val) } - appendHeader(headers, key, val) } } else { for (const key of Object.keys(opts.headers)) { diff --git a/deps/undici/src/lib/web/fetch/body.js b/deps/undici/src/lib/web/fetch/body.js index 5d1724965272..c588acce4f02 100644 --- a/deps/undici/src/lib/web/fetch/body.js +++ b/deps/undici/src/lib/web/fetch/body.js @@ -45,7 +45,6 @@ const streamRegistry = new FinalizationRegistry((weakRef) => { function extractBody (object, keepalive = false) { // 1. Let stream be null. let stream = null - let controller = null // 2. If object is a ReadableStream object, then set stream to object. if (webidl.is.ReadableStream(object)) { @@ -58,11 +57,44 @@ function extractBody (object, keepalive = false) { // 4. Otherwise, set stream to a new ReadableStream object, and set // up stream with byte reading support. stream = new ReadableStream({ - pull () {}, - start (c) { - controller = c + start () {}, + async pull (controller) { + // 19.1. Run action. + const result = action() + + const iterator = result?.[Symbol.asyncIterator]?.() + if (iterator == null) { + // 19.2. Whenever one or more bytes are available and stream is not errored, + // enqueue the result of creating a Uint8Array from the available bytes into stream. + if (result?.length && !isErrored(stream)) { + controller.enqueue(typeof result === 'string' ? textEncoder.encode(result) : new Uint8Array(result)) + } + + // 19.3. When running action is done, close stream. + queueMicrotask(() => readableStreamClose(controller)) + return + } + + while (true) { + const { value, done } = await iterator.next() + + // 19.3. When running action is done, close stream. + if (done) { + queueMicrotask(() => readableStreamClose(controller)) + return + } + + // 19.2. Whenever one or more bytes are available and stream is not errored, + // enqueue the result of creating a Uint8Array from the available bytes into stream. + if (value.length && !isErrored(stream)) { + controller.enqueue(new Uint8Array(value)) + return + } + } + }, + cancel (reason) { + return action()[Symbol.asyncIterator]?.().return(reason) }, - cancel () {}, type: 'bytes' }) } @@ -161,7 +193,7 @@ function extractBody (object, keepalive = false) { // Set source to object. source = object - action = async function * () { + const parts = (async function * () { for (const part of blobParts) { if (part.stream) { yield * part.stream() @@ -169,7 +201,8 @@ function extractBody (object, keepalive = false) { yield part } } - } + })() + action = () => parts // Set type to `multipart/form-data; boundary=`, // followed by the multipart/form-data boundary string generated @@ -206,45 +239,21 @@ function extractBody (object, keepalive = false) { webidl.is.ReadableStream(object) ? object : ReadableStreamFrom(object) } - // 11. If source is a byte sequence, then set action to a + // 18. If source is a byte sequence, then set action to a // step that returns source and length to source’s length. if (typeof source === 'string' || isUint8Array(source)) { - action = () => { - length = typeof source === 'string' ? Buffer.byteLength(source) : source.length - return source - } + action = () => source + length = typeof source === 'string' ? Buffer.byteLength(source) : source.length } - // 12. If action is non-null, then run these steps in parallel: - if (action != null) { - ;(async () => { - // 1. Run action. - const result = action() - - // 2. Whenever one or more bytes are available and stream is not errored, - // enqueue the result of creating a Uint8Array from the available bytes into stream. - const iterator = result?.[Symbol.asyncIterator]?.() - if (iterator) { - for await (const bytes of iterator) { - if (isErrored(stream)) break - if (bytes.length) { - controller.enqueue(new Uint8Array(bytes)) - } - } - } else if (result?.length && !isErrored(stream)) { - controller.enqueue(typeof result === 'string' ? textEncoder.encode(result) : new Uint8Array(result)) - } - - // 3. When running action is done, close stream. - queueMicrotask(() => readableStreamClose(controller)) - })() - } + // 19. If action is non-null, then run these steps in parallel: + // Note: this is done in the pull method of the stream created above - // 13. Let body be a body whose stream is stream, source is source, + // 20. Let body be a body whose stream is stream, source is source, // and length is length. const body = { stream, source, length } - // 14. Return (body, type). + // 21. Return (body, type). return [body, type] } diff --git a/deps/undici/src/lib/web/subresource-integrity/subresource-integrity.js b/deps/undici/src/lib/web/subresource-integrity/subresource-integrity.js index f7d165a9534c..a10e08ecc75a 100644 --- a/deps/undici/src/lib/web/subresource-integrity/subresource-integrity.js +++ b/deps/undici/src/lib/web/subresource-integrity/subresource-integrity.js @@ -197,8 +197,8 @@ function parseMetadata (metadata) { /** @type {MetadataList} */ const result = [] - // 2. For each item returned by splitting metadata on spaces: - for (const item of metadata.split(' ')) { + // 2. For each item returned by splitting metadata on ASCII whitespace: + for (const item of metadata.split(/[\t\n\f\r ]+/)) { // 1. Let expression-and-options be the result of splitting item on U+003F (?). const expressionAndOptions = item.split('?', 1) diff --git a/deps/undici/src/package-lock.json b/deps/undici/src/package-lock.json index 38d43f84dd1c..a63b3a04ad51 100644 --- a/deps/undici/src/package-lock.json +++ b/deps/undici/src/package-lock.json @@ -1,12 +1,12 @@ { "name": "undici", - "version": "7.30.1", + "version": "7.30.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "undici", - "version": "7.30.1", + "version": "7.30.2", "license": "MIT", "devDependencies": { "@fastify/busboy": "3.2.0", @@ -101,21 +101,21 @@ } }, "node_modules/@babel/core": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", - "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "version": "7.29.13", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.13.tgz", + "integrity": "sha512-j1nvOQCZYSgp7HLmisnCXFTpVvFODiijQ9QHkORfGKWH6YDtskTEeCJS7eV545GZ9UBzrq0e2xsOd5QQ5PjIqw==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.7", - "@babel/helper-compilation-targets": "^7.29.7", - "@babel/helper-module-transforms": "^7.29.7", - "@babel/helpers": "^7.29.7", - "@babel/parser": "^7.29.7", + "@babel/generator": "^7.29.13", + "@babel/helper-compilation-targets": "^7.29.13", + "@babel/helper-module-transforms": "^7.29.13", + "@babel/helpers": "^7.29.13", + "@babel/parser": "^7.29.13", "@babel/template": "^7.29.7", - "@babel/traverse": "^7.29.7", - "@babel/types": "^7.29.7", + "@babel/traverse": "^7.29.13", + "@babel/types": "^7.29.11", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", @@ -132,14 +132,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", - "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "version": "7.29.13", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.13.tgz", + "integrity": "sha512-T5FRo+RzVHvGjWOuF1Ljc44b+NXAOazodHkGUHp4I3zCkQ4/sNVJm56h1S278LMR0bY5xBhztGziSbli8zObIw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.8", - "@babel/types": "^7.29.8", + "@babel/parser": "^7.29.13", + "@babel/types": "^7.29.11", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -149,9 +149,9 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", - "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "version": "7.29.13", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.13.tgz", + "integrity": "sha512-8WxJ4/Vmes3ghacj8VOJy3NW8eyHiFY/4thU/LSBuBE470+igjR/j1ZTNn8fV5VdNrLx6iXUwig526UdOvfP0w==", "dev": true, "license": "MIT", "dependencies": { @@ -190,15 +190,15 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", - "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "version": "7.29.13", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.13.tgz", + "integrity": "sha512-/U96wOz+SCoZ7Da/8kjDGltcNY280JPQcRNPK0Hk3PTbdpaiBDQImtC6JsbVwb1HGMr3usZQU2WsWVjhYNmRzw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7", - "@babel/traverse": "^7.29.7" + "@babel/traverse": "^7.29.13" }, "engines": { "node": ">=6.9.0" @@ -218,9 +218,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", - "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "version": "7.29.13", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.13.tgz", + "integrity": "sha512-fWegr+WsEsiMVW4KUNdIIzzMTZSzNiqhy0//6+2MRi2d5NFNsL/AYwBQW8eBnRbTBVRnDVzjaJEUqKaCWjMMdQ==", "dev": true, "license": "MIT", "engines": { @@ -248,27 +248,27 @@ } }, "node_modules/@babel/helpers": { - "version": "7.29.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.10.tgz", - "integrity": "sha512-EMCx3AGZ3WfAl6ht7AyQoPm2Lh+BGYEMdc4Q6Hf7uSCDOZFuLq44qNwL+iaim8VlyYhRAo4X43+weadK8ZB4Yg==", + "version": "7.29.13", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.13.tgz", + "integrity": "sha512-laoRpD/kO/iA4CDlgJbixHekg7oPvWALK0PQyK3Ob2I2njZRvVAD77RfWCIImtqWCq6KijoBoZK7bp/HlTWASQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.29.7", - "@babel/types": "^7.29.8" + "@babel/types": "^7.29.11" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.29.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.9.tgz", - "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", + "version": "7.29.13", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.13.tgz", + "integrity": "sha512-fJM50YYjlTiBhgdkGmC1tBpv+FMAyo4annf2X6Aks+0yRlaiVkYW/3f07xAfVVkYIoZ9fFZp+mEThUFnuybhkQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.29.8" + "@babel/types": "^7.29.11" }, "bin": { "parser": "bin/babel-parser.js" @@ -532,18 +532,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.29.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.10.tgz", - "integrity": "sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==", + "version": "7.29.13", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.13.tgz", + "integrity": "sha512-0ve0xMlFA73dgY1oyJRY6RoW+/bncdcOQqg6jjYcVfXBK90OdLXjm9R6lmRetdZVrPjXkKIoMVBqYFPjcAlZ4Q==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.8", + "@babel/generator": "^7.29.13", "@babel/helper-globals": "^7.29.7", - "@babel/parser": "^7.29.9", + "@babel/parser": "^7.29.13", "@babel/template": "^7.29.7", - "@babel/types": "^7.29.8", + "@babel/types": "^7.29.11", "debug": "^4.3.1" }, "engines": { @@ -551,13 +551,13 @@ } }, "node_modules/@babel/types": { - "version": "7.29.8", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", - "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "version": "7.29.11", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.11.tgz", + "integrity": "sha512-WCsemW40Cpc6gouC1SrY6PBaZ+oLRlEVY9XBvZBI7il/HyUrb2nJ505wE1MHEFyDZNnrWDEuy4jL50WVHfTTSQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-string-parser": "^7.29.11", "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { @@ -581,40 +581,6 @@ "dev": true, "license": "Apache-2.0" }, - "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@epic-web/invariant": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", @@ -1974,28 +1940,6 @@ "node": ">=20" } }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.5.tgz", - "integrity": "sha512-HshSvXzmBxNzqejd3k/KemgQ3hdREUYFRRrgxOZ+gPljDIsO2SDZrVZMd4Z/HsxudQbE62OVyVFE8z9BCurfjA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.3" - }, - "engines": { - "node": "^20.19.0 || ^22.13.0 || >=23.5.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", - "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2461,17 +2405,6 @@ "node": ">=14.17" } }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.4.tgz", - "integrity": "sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -2529,9 +2462,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", - "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.10.tgz", + "integrity": "sha512-lTyOMnOcmRBzdCv6/4zUZCrEhV0xrqQiUZBZtVcbmLHBXKLnN8q89v/wKRF/Q0HbwVsqbIG3o5HDoFl9sduM+g==", "dev": true, "license": "MIT" }, @@ -2618,17 +2551,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.71.2.tgz", - "integrity": "sha512-K72/pvT7qpm8q3k8G5u93NCSN1RcLxX5h7Gw0bQpbMXviBHeY6Nx1WEwmk9wP+eKTSQ8ecxvcgt/ZX/rB938xQ==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.72.1.tgz", + "integrity": "sha512-5CokTWXpmbylfFabsbvHC0CAw3XLaGnoa+nFJX5FR592h/LoZsENUE6p/rg5xvkKrFEXz6pYmgI29AgXc2N3BQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/type-utils": "8.71.2", - "@typescript-eslint/utils": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", + "@typescript-eslint/scope-manager": "8.72.1", + "@typescript-eslint/type-utils": "8.72.1", + "@typescript-eslint/utils": "8.72.1", + "@typescript-eslint/visitor-keys": "8.72.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" @@ -2641,15 +2574,15 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.71.2", + "@typescript-eslint/parser": "^8.72.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.12.tgz", - "integrity": "sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.14.tgz", + "integrity": "sha512-wCBiZ77u1tuWde6G/nfOtLaCTYcFDU5yCzARzK10y+rLhzYoL7a7yEemcopcc2Mzow7gZOIjnV2ym1NYmdiJOQ==", "dev": true, "license": "MIT", "engines": { @@ -2657,16 +2590,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.71.2.tgz", - "integrity": "sha512-aTtmZjp/x3gsGHkDs04/1I8kNogBJkpQaeGaN0PfiG43NzDEmW2n+OP5im9wfsvyX0yP1UZWBrAGtDBfH9jEVw==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.72.1.tgz", + "integrity": "sha512-ZGwZP4OCfyA0AQTpEAMWz+rtX01DRhQWW5hB0ucKDEIX5U7jdmPSaMx94rQfaPAQzIYz2BimOgKOJtjfpRFQ9g==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", + "@typescript-eslint/scope-manager": "8.72.1", + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/typescript-estree": "8.72.1", + "@typescript-eslint/visitor-keys": "8.72.1", "debug": "^4.4.3" }, "engines": { @@ -2682,14 +2615,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.71.2.tgz", - "integrity": "sha512-Pd68GsLVh5ZXlcEccFPdhSOvtHZ/2WU0XsA8zmXOS3F158lVlcTLhfQ6qvtL1RzbMie0Kp8xtbVwAg4nejKPHw==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.72.1.tgz", + "integrity": "sha512-fAuVMkwdO/huI8nyo/WKnNKf6Gag93S56Rh3Ts5mGcavwSdaN8tRg1gCeIGX8PF+nzp1BjGfO4gHhGzW1J6jTg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.71.2", - "@typescript-eslint/types": "^8.71.2", + "@typescript-eslint/tsconfig-utils": "^8.72.1", + "@typescript-eslint/types": "^8.72.1", "debug": "^4.4.3" }, "engines": { @@ -2704,14 +2637,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.71.2.tgz", - "integrity": "sha512-YF4wgg5iUX5Obywoac27B56FhozMNFhdJSbh11H5GBAwmBtfyRhmgTQqW9tRNNmHDvsZ2CX6UGzoz+YfYn2Leg==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.72.1.tgz", + "integrity": "sha512-lC/t6eMCZZQAAKZEYGL6RDVSuFehpdmMT6h+nJIjIa6oylN/PwDgDVtEIbB7O9xFfZYtZAYLoLlDNWKJhtF+uQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2" + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/visitor-keys": "8.72.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2722,9 +2655,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.71.2.tgz", - "integrity": "sha512-jz49TAWokm/7yWD9/o837nYax9DyALxIPOImdImvVzo6canBCZYzin8zJyqNR5k1j9K1DE0bVvr0XYB+99uAdg==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.72.1.tgz", + "integrity": "sha512-e4D5R5vpeAEPBxT2BAzsFQL3sbwyeeeo5+aczgNSRK1V734jE7pTqaGFU+fXapWEQwnZbpFaTn32+Z8DwS6OTg==", "dev": true, "license": "MIT", "engines": { @@ -2739,15 +2672,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.71.2.tgz", - "integrity": "sha512-cC8UaalCViJkb3rH/xLIvidEwoFRtMZMUqDjjJMGEKaTFwYRHYBcoczlEGHuvkHEO8svRDrgZ0yQgOArFmwang==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.72.1.tgz", + "integrity": "sha512-iY2wlmyrXJmx4yxUGP3aYCFF3cA/6ShddOKmLU2dx7LnEykbAM8WThlxZEfd1NddqceF6eJmZUayxx9oKIYNlg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/utils": "8.71.2", + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/typescript-estree": "8.72.1", + "@typescript-eslint/utils": "8.72.1", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, @@ -2764,9 +2697,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.71.2.tgz", - "integrity": "sha512-y5Ukl3oVp7e/VGxqIoEXoeb/Roj71PAJ4WG/N/RGj+eeDvKRLM15kGr9MijLbN0i03S52zxu31Z98E5gWChJKw==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.72.1.tgz", + "integrity": "sha512-LmE5IhQet1BWOWEXqBrVtBPsMAOQ6Nzk35d+WLh3mk4EUF33sqlfxjio1MdYeSvKSG5skactKKuixBIKXhL4Rw==", "dev": true, "license": "MIT", "engines": { @@ -2778,16 +2711,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.71.2.tgz", - "integrity": "sha512-DgNOEsl4pdYzwSL+N/Cl33tX1Hlw3FvId73LnKXfq7jnrF2viOEn7X+P7RBkkSWCVm92gnWd28GIC5vJuLREeA==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.72.1.tgz", + "integrity": "sha512-DAlUoUV93hIvrtIQLwCbmZQYVZwOMhiHJrOVUUIWicFZaIYjTRqlY3I/NZevfkLmSqkNHRu2qYDcq9lrn16oOQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.71.2", - "@typescript-eslint/tsconfig-utils": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/visitor-keys": "8.71.2", + "@typescript-eslint/project-service": "8.72.1", + "@typescript-eslint/tsconfig-utils": "8.72.1", + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/visitor-keys": "8.72.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", @@ -2845,9 +2778,9 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.6.tgz", + "integrity": "sha512-9lpSSU4Mly3mrtruwLs1eLK6+gzbzqeBFwRNjIjE+9LuDpWdYctrQlQ3ej1Ilgi7gknpsTRnPoLP8DpCHqHIJw==", "dev": true, "license": "ISC", "bin": { @@ -2858,16 +2791,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.71.2.tgz", - "integrity": "sha512-RyKa1G1M9rKHDhrk+HJtiF1MvLD5Ux2JW3TSkzw+02pRALdpJb+QzG1Y5em+LvCgzGwgg8H7mBRFKljNz7ImPw==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.72.1.tgz", + "integrity": "sha512-5v5liypurJBFHCBNqh/RjsymAD+VWcE0djuGY/BUqp5fC3Qn+luWDEksjuTtWjPn6i5zQlUtkZCRG/CYG0yCkA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.71.2", - "@typescript-eslint/types": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2" + "@typescript-eslint/scope-manager": "8.72.1", + "@typescript-eslint/types": "8.72.1", + "@typescript-eslint/typescript-estree": "8.72.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2882,13 +2815,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.71.2.tgz", - "integrity": "sha512-zozlN0UA32bSG2zkKAgQyRYSbEISVoyU6vvkKYo2aSny74D8Jh4e+POkJ6Lk0dlezZi5x7TtD+88Xb06IB8nhg==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.72.1.tgz", + "integrity": "sha512-SB8xqipSzZHUePCCLNeYxqnxq83X61/qzNhjQGbTfjxGZIeOEP7tBgWYX05Tcd6CgE02WdTJnh5b8kMZJ/+bnQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.71.2", + "@typescript-eslint/types": "8.72.1", "eslint-visitor-keys": "^5.0.0" }, "engines": { @@ -2920,9 +2853,9 @@ "license": "ISC" }, "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.12.2.tgz", - "integrity": "sha512-g5T90pqg1bo/7mytQx6F4iBNC0Wsh9cu+z9veDbFjc7HjpesJFWD7QMS0NGStXM075+7dJPPVvBbpZlnrdpi/w==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.13.0.tgz", + "integrity": "sha512-60E5mvmIiW+i1E/HYeSX4iE4A8s9NJSGYPu7UM0DJght1c2tTkWwuyDyAwzsEXhKM/XbbndfnTiXdfrf27d2hw==", "cpu": [ "arm" ], @@ -2934,9 +2867,9 @@ ] }, "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.12.2.tgz", - "integrity": "sha512-YGCRZv/9GLhwmz6mYDeTsm/92BAyR28l6c2ReweVW5pWgfsitWLY8upvfRlGdoyD8HjeTHSYJWyZGD4KJA/nFQ==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.13.0.tgz", + "integrity": "sha512-qlh/JR3Tuy1cJ7xtf5pR4ykvLiK6os7X7EL2+zXZbrVc/s+yB8DoFdQrCAW9/a2TOxPVbR7QVNpkPWh7UWIsEQ==", "cpu": [ "arm64" ], @@ -2948,9 +2881,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.12.2.tgz", - "integrity": "sha512-u9DiNT1auQMO20A9SyTuG3wUgQWB9Z7KjAg0uFuCDR1FsAY8A0CG2S6JpHS1xwm/w1G08bjXZDcyOCjv1WAm2w==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.13.0.tgz", + "integrity": "sha512-yynnnnJXUC99WeD1GfvuXPKsKNfvgzGYC2eRayFnUfsHVROjqrbFOkFQLZiSx1H8+PLy5BzU8vqyPyLqbRfeBQ==", "cpu": [ "arm64" ], @@ -2962,9 +2895,9 @@ ] }, "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.12.2.tgz", - "integrity": "sha512-f7rPLi/T1HVKZu/u6t87lroib16n8vrSzcyxI7lg4BGO9UF26KhQL44sd9eOUgrTYhvRXtWOIZT5PejdPyJfUA==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.13.0.tgz", + "integrity": "sha512-t8PXE0Ip9tmGyhRlfVsnEbzGM5iSvJIeNIXciUACjzpg0mmPs13fGv2x7W8sBa0S8zbIiohxKXS9fL/LXW/ERQ==", "cpu": [ "x64" ], @@ -2976,9 +2909,9 @@ ] }, "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.12.2.tgz", - "integrity": "sha512-BpcOjWCJub6nRZUS2zA20pmLvjtqAtGejETaIyRLiZiQf++cbrjltLA5NN/xaXfqeOBOSlMFbemIl5/S5tljmg==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.13.0.tgz", + "integrity": "sha512-qdtl9GDWDoDx6rhzF4RU5SJutV3lcLOiTiyqD6nBxYfEO6lAgLNukfrA+HJ2u2OiyWvV8JW5iEWD3LoONw7lYA==", "cpu": [ "x64" ], @@ -2990,9 +2923,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.12.2.tgz", - "integrity": "sha512-vZTDvdSISZjJx66OzJqtsOhzifbqRjbmI1Mnu49fQDwog5GtDI4QidRiEAYbZCRj9C8YZEW+3ZjqsyS9GR4k2A==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.13.0.tgz", + "integrity": "sha512-VrMUVwdrScTarsh4B6aUhTtziUavSlglo4Hi8XZ6CpAe4+j3nquY+XoP+tYkiSBDsXZ8386ne4pv4YYYBNi02w==", "cpu": [ "arm" ], @@ -3004,9 +2937,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.12.2.tgz", - "integrity": "sha512-BiPI+IrIlwcW4nLLMM21+B1dFPzd55yAVgVGrdgDjNef+ch03GdxrcyaIz8X9SsQirh/kCQ7mviyWlMxdh2D7g==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.13.0.tgz", + "integrity": "sha512-zSbTVwaxiTC+zYJ9xVNTC6c+BYO/kOV/odcTI3bHuFFXa+XmjLoUkb/8UxsZeU5YF4K000m17wrXoTblNWuzOg==", "cpu": [ "arm" ], @@ -3018,9 +2951,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.12.2.tgz", - "integrity": "sha512-zJc0H99FEPoFfSrNpa91HYfxzfAJCr502oxNK1cfdC9hlaFI43RT+JFCann9JUgZmLzzntChHyn13Sgn9ljHNg==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.13.0.tgz", + "integrity": "sha512-Z/Rax87moZHsuvJ8awdfP+zrMlsCt3d7mggUPIiPe32KpeagimyzJWnZSMQoV67an9uVQghyh92Pc0VprITnYA==", "cpu": [ "arm64" ], @@ -3035,9 +2968,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.12.2.tgz", - "integrity": "sha512-KQ3Lki6l+Pz1k/eBipN41ES+YUK30beLGb9YqcB1O542cyLCNE6GaxrfcY3T6EezmGGk84wb5XyO9loTM9tkcA==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.13.0.tgz", + "integrity": "sha512-oUzXz8hNvFLNEAag8lBKJe1euiV2dmGHAR+eQ5fNpsZO0F1K7IMRb4J6pqYsd7uLMRQNPiu5A1WKUJHbFLWbbw==", "cpu": [ "arm64" ], @@ -3052,9 +2985,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-loong64-gnu": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.12.2.tgz", - "integrity": "sha512-3SJGEh1DborhG6pyxvhPzCT4bbSIVihsvgJc13P1bHG7KLdNDaF9T3gsTwFc7Jw/5Y5/iWOjkEx7Zy0NvCGX3Q==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-gnu/-/resolver-binding-linux-loong64-gnu-1.13.0.tgz", + "integrity": "sha512-BxhGYvZBg0YrvNOeSEGR3eNklwXYy0mUJk7oeGJvZoQMKM68zYvbbf52+fQI3Le4X0fW276FTKIoTwjpMob80A==", "cpu": [ "loong64" ], @@ -3069,9 +3002,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-loong64-musl": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.12.2.tgz", - "integrity": "sha512-jiuG/Obbel7uw1PwHNFfrkiKhLAF6mnyZ6aWlOAVN9WqKm8v0OFGnciJIHu8+CMvXLQ8AD51LPzAoUfT21D5Ew==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-loong64-musl/-/resolver-binding-linux-loong64-musl-1.13.0.tgz", + "integrity": "sha512-nZcIuup9Ar3gAlqoZfX/KW6x83TMI11tLpCjldZG5M1KeY8qNUPNJJ71+sPvG8HMBpoh+ix1pAm5gkMFvcSAcQ==", "cpu": [ "loong64" ], @@ -3086,9 +3019,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.12.2.tgz", - "integrity": "sha512-q7xRvVpmcfeL+LlZg8Pbbo6QaTZwDU5BaGZbwfhkEsXJn3Was8xYfE0RBH266xZt0rM6B7i8xAYIvjthuUIWHg==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.13.0.tgz", + "integrity": "sha512-AG6AgdDrkRNjAPwD/cftFJGgZUWCiJX+E8vpYCDEnwFHLTHZ7ppBiU6/vyPPwrfjcPUPQCDbbxE/eZUXsx49jQ==", "cpu": [ "ppc64" ], @@ -3103,9 +3036,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.12.2.tgz", - "integrity": "sha512-0CVdx6lcnT3Q9inOH8tsMIOJ6ImndllMjqJHg8RLVdB7Vq4SfkEXl9mCSsVNuNA4MCYycRicCUxPCabVHJRr6A==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.13.0.tgz", + "integrity": "sha512-6vOqYGcAmzpRWpUURWutzvpf1qJ6eOu5cfYObdtPJnzZ0+Kw4cw+ZkZJqIYEh8fPuTBwSYDL/FwlUhma1G/JVQ==", "cpu": [ "riscv64" ], @@ -3120,9 +3053,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.12.2.tgz", - "integrity": "sha512-iOwlRo9vnp6R6ohHQS11n0NnfdXx/omhkocmIfaPRpQhKZ+3BDMkkdRVh53qjkFkpPddf+FETA28NwGN7l5l+w==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.13.0.tgz", + "integrity": "sha512-4HeIn0S2KVUowK0A+EweXrDvZ8CKHEfTtif0kx9vt3ORNsqcXNFFIFnHE0tizma3/Gt5OGrU2ovYNuj+D/bN4g==", "cpu": [ "riscv64" ], @@ -3137,9 +3070,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.12.2.tgz", - "integrity": "sha512-HYJtLfXq94q8iZNFT1lknx258wlkkWhZeUXJRqzKBBUJ00CvZ+N33zgbCqimLjsyw5Va6uUxhVa12mI+kaveEw==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.13.0.tgz", + "integrity": "sha512-JfkvqY7NZbxyhexLE+g6Z8Hsx4utHOGaVazAVghPiBn8Upw2iERZPpKYnW1FBVU4WStv/BiIsoK/Muke0E7asA==", "cpu": [ "s390x" ], @@ -3154,9 +3087,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.12.2.tgz", - "integrity": "sha512-mPsUhunKKDih5O96Y6enDQyHc1SqBPlY1E/SfMWDM3EdJ95Z9CArPeCVwCCqbP45ljvivdEk8Fxn+SIb1rDAJQ==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.13.0.tgz", + "integrity": "sha512-iwjLeVdZo/8v5OKAeRIC+4VQV045t1EPZr5B/AVLgUQ04IdtNthWzg6not2cNjZgH2gHpSf4fOXMmN83aLO1FA==", "cpu": [ "x64" ], @@ -3171,9 +3104,9 @@ ] }, "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.12.2.tgz", - "integrity": "sha512-azrt6+5ydLd8Vt210AAFis/lZevSfPw93EJRIJG+xPu4WCJ8K0kppCTpMyLPcKT7H15M4Jnt2tMp5bOvCkRC6A==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.13.0.tgz", + "integrity": "sha512-TOh1fqOjyq1OPoht3BDLd7Y+HeMJRwd5g2VNmCQclknEbjp4py5GFRmT4L/rOybF5Af8q0LT9zHs2WGkwlqtrw==", "cpu": [ "x64" ], @@ -3188,9 +3121,9 @@ ] }, "node_modules/@unrs/resolver-binding-openharmony-arm64": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.12.2.tgz", - "integrity": "sha512-YZ9hP4O0X9PQb8eO980qmLNGH4zT3I9+SZTdt0Pr0YyuGQhYKoOZkV02VzrzyOZJ5xIJ3UFIenKkUkGg8GjgWQ==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-openharmony-arm64/-/resolver-binding-openharmony-arm64-1.13.0.tgz", + "integrity": "sha512-3T2MNtF2dd1yjaXCVqrsi+/3VZeksEzU1hygPzqqkBLVVjn+2iJzXEkxxCKIVFrWnpmEbazeHJp/ruYD0RUVWA==", "cpu": [ "arm64" ], @@ -3201,29 +3134,10 @@ "openharmony" ] }, - "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.12.2.tgz", - "integrity": "sha512-tYFDIkMxSflfEc/h92ZWNsZlHSwgimbNHSO3PL2JWQHfCuC2q316jMyYU9TIWZsFK2bQwyK5VAdYgn8ygPj69A==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.10.0", - "@emnapi/runtime": "1.10.0", - "@napi-rs/wasm-runtime": "^1.1.4" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.12.2.tgz", - "integrity": "sha512-qzNyg3xL0VPQmCaUh+N5jSitce6k+uCBfMDesWRnlULOZaqUkaJ0ybdT+UqlAWJoQjuqfIU/0Ptx9bteN4D82g==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.13.0.tgz", + "integrity": "sha512-hKWfSLiN3L4cIxg0jrpyP/66AXLTcyD37jmSn//rGdOUYGlizYxTEFdJ+GZbp2NnaML3YS/A73nCysze8FaJdg==", "cpu": [ "arm64" ], @@ -3235,9 +3149,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.12.2.tgz", - "integrity": "sha512-WD9sY00OfpHVGfsnHZoA8jVT+esS/Bg8z8jzxp5BnDCjjwsuKsPQrzswwpFy4J1AUJbXPRfkpcX0mXrzeXW79g==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.13.0.tgz", + "integrity": "sha512-N4gDKkDoiyIQEcn3vTqe2ksRxUAtBvQ8c5TiT+WonSa6FHgCAY5+RggnZ134hXJoRj57JEjv4/m+i/pAKHWrTQ==", "cpu": [ "ia32" ], @@ -3249,9 +3163,9 @@ ] }, "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.12.2.tgz", - "integrity": "sha512-nAB74NfSNKknqQ1RrYj6uz8FcXEomu/MATJZxh/x+BArzN2U3JbOYC0APYzUIGhVY3m5hRxA8VPNdPBoG8txlA==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.13.0.tgz", + "integrity": "sha512-DpLMlAqlrk4zBVK3DiDjwKD0oq7pZNy+8BiIBRuByqb6dm5jsdoLMhIiyh/xR7+WejaW/1Ui+XgbgMNa4+zWJg==", "cpu": [ "x64" ], @@ -3332,9 +3246,9 @@ } }, "node_modules/ansi-regex": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.4.0.tgz", - "integrity": "sha512-KzTVk2tCWAHtYrvvvaP8bJKJq2pVinhLcGEQdtLIYPbmNGNyYe8QwNaTUYQp2J7/vIsUKt5QCqAfUkYyG9DkOw==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.5.0.tgz", + "integrity": "sha512-zhvbbbdt1kbw7EJ9OQoxmQcuaNR9P5kTj7e/YdmOSU10aHWbycofJxA6jKfoEy3vlLdctOF9ZHaxLtmSm998wQ==", "dev": true, "license": "MIT", "engines": { @@ -3799,9 +3713,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.11.28", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.28.tgz", - "integrity": "sha512-br0LOmjJqr6Rt4AEkadbcNf67Zpo7EPwKsWbjnRrJIa1QYFHQBqM4C7F2WTbV8ahTEcg1Eo+Y0aWjjORInYFyA==", + "version": "2.11.35", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.35.tgz", + "integrity": "sha512-GNk8KX52CHqeNKGk8+7tZnQab/2k1t/BgrUHPKNdijzpEhF1saPQZHVKb6m5loSAxB39gyrTYw34Qf9CQ3u1qQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3860,9 +3774,9 @@ } }, "node_modules/browserslist": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.3.tgz", - "integrity": "sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==", + "version": "4.29.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.5.tgz", + "integrity": "sha512-khTmKu5NGYTotqcYo8Bew2k4RAE9PuXRSFRXG2lQBrCEQHyeQ/vX6gKMxfokwywBsLiXZMnHsmWMG1pnO8J7uQ==", "dev": true, "funding": [ { @@ -3880,11 +3794,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.11.26", - "caniuse-lite": "^1.0.30001813", - "electron-to-chromium": "^1.5.439", - "node-releases": "^2.0.57", - "update-browserslist-db": "^1.3.3" + "baseline-browser-mapping": "^2.11.33", + "caniuse-lite": "^1.0.30001819", + "electron-to-chromium": "^1.5.464", + "node-releases": "^2.0.60", + "update-browserslist-db": "^1.3.4" }, "bin": { "browserslist": "cli.js" @@ -4085,9 +3999,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001816", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001816.tgz", - "integrity": "sha512-+8Yx7BXCoqk6IF8yTicjfUR6D/ldJzdlsodlEOiOSPmhK844WIgk67/zIQaGAOxNkZyyvBlrRFnLvqKIoqbAFw==", + "version": "1.0.30001820", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001820.tgz", + "integrity": "sha512-gfWD6MxqVCqAOwmODfZf7DchWvlrA+SRdNX7ceLfg3xRqe5ssjjpF7EgslC/0tiLiNTajdaNN/q8c/5u/7Gz8w==", "dev": true, "funding": [ { @@ -4597,9 +4511,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.456", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.456.tgz", - "integrity": "sha512-8hboqI6xesozteFb8aa7OGknvxUtTeRJLz0FoePysUEh/oWbddykIGdgpEJRbPRg/nIMfBf2DFos+H2MtvJl2A==", + "version": "1.5.477", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.477.tgz", + "integrity": "sha512-PN++F4zWZoVDGWinxMnSCpVqKhqFOJfLXxdU8bYJKudAEsHL/XKVITOKWVbfMt1r276Mi9RDLU9VHx9uKJ4RMQ==", "dev": true, "license": "ISC" }, @@ -4624,9 +4538,9 @@ "license": "MIT" }, "node_modules/enhanced-resolve": { - "version": "5.26.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.26.0.tgz", - "integrity": "sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==", + "version": "5.26.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.26.1.tgz", + "integrity": "sha512-PPnnSJq3azKOIewXR/uppBV/6h98dprBJ/WaQ9Qgj10xX1lJLNfg+XShpbsrSqcDSy2yYYyhfXM1wWhftqgyzw==", "dev": true, "license": "MIT", "dependencies": { @@ -4996,9 +4910,9 @@ } }, "node_modules/eslint-compat-utils/node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.6.tgz", + "integrity": "sha512-9lpSSU4Mly3mrtruwLs1eLK6+gzbzqeBFwRNjIjE+9LuDpWdYctrQlQ3ej1Ilgi7gknpsTRnPoLP8DpCHqHIJw==", "dev": true, "license": "ISC", "bin": { @@ -5235,9 +5149,9 @@ } }, "node_modules/eslint-plugin-import-x/node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.6.tgz", + "integrity": "sha512-9lpSSU4Mly3mrtruwLs1eLK6+gzbzqeBFwRNjIjE+9LuDpWdYctrQlQ3ej1Ilgi7gknpsTRnPoLP8DpCHqHIJw==", "dev": true, "license": "ISC", "bin": { @@ -5288,9 +5202,9 @@ } }, "node_modules/eslint-plugin-n/node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.6.tgz", + "integrity": "sha512-9lpSSU4Mly3mrtruwLs1eLK6+gzbzqeBFwRNjIjE+9LuDpWdYctrQlQ3ej1Ilgi7gknpsTRnPoLP8DpCHqHIJw==", "dev": true, "license": "ISC", "bin": { @@ -6478,9 +6392,9 @@ } }, "node_modules/is-bun-module/node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.6.tgz", + "integrity": "sha512-9lpSSU4Mly3mrtruwLs1eLK6+gzbzqeBFwRNjIjE+9LuDpWdYctrQlQ3ej1Ilgi7gknpsTRnPoLP8DpCHqHIJw==", "dev": true, "license": "ISC", "bin": { @@ -6504,9 +6418,9 @@ } }, "node_modules/is-core-module": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.17.0.tgz", - "integrity": "sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==", + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.18.0.tgz", + "integrity": "sha512-qyax9fgaKOEC4qK8WZn7Q4IcoZC9RC1O1fFxRcRTq/oMMkWT/uXpqpXa12kzWR409zAt1drYN9N9BO26UmBCmw==", "dev": true, "license": "MIT", "dependencies": { @@ -6928,9 +6842,9 @@ } }, "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.6.tgz", + "integrity": "sha512-9lpSSU4Mly3mrtruwLs1eLK6+gzbzqeBFwRNjIjE+9LuDpWdYctrQlQ3ej1Ilgi7gknpsTRnPoLP8DpCHqHIJw==", "dev": true, "license": "ISC", "bin": { @@ -7764,9 +7678,9 @@ } }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.6.tgz", + "integrity": "sha512-9lpSSU4Mly3mrtruwLs1eLK6+gzbzqeBFwRNjIjE+9LuDpWdYctrQlQ3ej1Ilgi7gknpsTRnPoLP8DpCHqHIJw==", "dev": true, "license": "ISC", "bin": { @@ -7963,9 +7877,9 @@ } }, "node_modules/jsondiffpatch": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.7.6.tgz", - "integrity": "sha512-zE9+AXFq+MkTolDor2Cw1nJzLC0aleqPkYf52Kb4Kn4mJcka/gFHpGI2JBVEJCfWOvBl0OoxZS+wuLdislQcqg==", + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/jsondiffpatch/-/jsondiffpatch-0.7.7.tgz", + "integrity": "sha512-C3375q+xluwQYS6Je613YqXpZhW9uSi2YFRR+8QTJVYhdk0GZiDr7HD9bXNrdV9PJCpmwsCgJM9ZXXESSZPCzA==", "dev": true, "license": "MIT", "dependencies": { @@ -8138,9 +8052,9 @@ } }, "node_modules/make-dir/node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.6.tgz", + "integrity": "sha512-9lpSSU4Mly3mrtruwLs1eLK6+gzbzqeBFwRNjIjE+9LuDpWdYctrQlQ3ej1Ilgi7gknpsTRnPoLP8DpCHqHIJw==", "dev": true, "license": "ISC", "bin": { @@ -8353,12 +8267,13 @@ "license": "MIT" }, "node_modules/napi-postinstall": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", - "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.8.tgz", + "integrity": "sha512-dHbDC5V1g/EI8OLEtL4Iuwbu0fgzmyykxenn2KnlsX9XdhTXL3gWnfbbP+ab+oUcgV6CFpb8QGyQt/ZXA0UXig==", "dev": true, "license": "MIT", "bin": { + "napi-patch": "lib/patch.js", "napi-postinstall": "lib/cli.js" }, "engines": { @@ -8503,9 +8418,9 @@ } }, "node_modules/node-forge": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", - "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.3.tgz", + "integrity": "sha512-P6wzfh6t70avmV8FrVEAd/36sOPJQ+hkaJVX1Laap9J/77m7M0eyozDvc8SwnDf4P7MP94gwbAAo0rg3YVXT+g==", "dev": true, "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { @@ -8520,9 +8435,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.59", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.59.tgz", - "integrity": "sha512-5qr2okC4ItAI0hG5SaV0HoYMpnM/Y6+Oqr7AmPYy/2uEoGvS+GbSKLeRxSS1uAdu59yz0ouzcuXievSgg///WA==", + "version": "2.0.63", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.63.tgz", + "integrity": "sha512-6li2QanLsAXpIH2R6j77MzRyvOyrvdTqlKtO4CgBdHGNvN99ZZfyxszHc5o5+IZBWD5u6Hzwg83JoGXmqZNG9Q==", "dev": true, "license": "MIT", "engines": { @@ -8546,9 +8461,9 @@ } }, "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.8.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", - "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.6.tgz", + "integrity": "sha512-9lpSSU4Mly3mrtruwLs1eLK6+gzbzqeBFwRNjIjE+9LuDpWdYctrQlQ3ej1Ilgi7gknpsTRnPoLP8DpCHqHIJw==", "dev": true, "license": "ISC", "bin": { @@ -9383,14 +9298,14 @@ } }, "node_modules/read-pkg/node_modules/resolve": { - "version": "1.22.13", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.13.tgz", - "integrity": "sha512-Dj/cW9zBV2aRj6XzCxuGIs3ESZKv02jixne3q6jFZYZ3/Tg09gHHviSMDL4kObh9pqSahdRHEnDoaP2gn8YLhA==", + "version": "1.22.14", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.14.tgz", + "integrity": "sha512-1ZjYvR9sbkiwC5+9QHetqW5HmA2pHRMaoupD01t2HlYnV/vydC2zPwLixhsMieSWVZt0JJRg5LVIk0Ow1D/TrA==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "is-core-module": "^2.17.0", + "is-core-module": "^2.18.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -9405,9 +9320,9 @@ } }, "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.3.tgz", + "integrity": "sha512-kM18BPOqTi0+TB68703/GJRpAML5Me+IDQsR1J26YB3EFKKNEyHIVZuWDX7+WKQB3tHwDwgk24BfhdpWUbytvQ==", "dev": true, "license": "ISC", "bin": { @@ -9663,9 +9578,9 @@ } }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.2.tgz", + "integrity": "sha512-GYrCADwpu6yV5OAvchkQ27Z5wwMxWAEMg5NNWjyHh/5DboFFqbdbvYNIvZouQpxXyeMPoTOh0vdPYKlf0ZswdQ==", "dev": true, "license": "ISC", "bin": { @@ -10532,14 +10447,6 @@ "dev": true, "license": "MIT" }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true - }, "node_modules/tunnel": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", @@ -10678,16 +10585,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.71.2", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.71.2.tgz", - "integrity": "sha512-Rz4effbMy2g9wnvOJZG6SbVavX313Lap1vNEbk1RUochzickvzP8P4HB+bkNg5e50eVz1hQGjh9K1omI1xB4Bw==", + "version": "8.72.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.72.1.tgz", + "integrity": "sha512-3Li9FfPmQp45nxEtFD1ZCrYFI3cYK5kpyNtmm1H7lMagm8u9sy6PTjy3ytwQZs7KNukOyKFHAZ6z6GjYFeaeXw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.71.2", - "@typescript-eslint/parser": "8.71.2", - "@typescript-eslint/typescript-estree": "8.71.2", - "@typescript-eslint/utils": "8.71.2" + "@typescript-eslint/eslint-plugin": "8.72.1", + "@typescript-eslint/parser": "8.72.1", + "@typescript-eslint/typescript-estree": "8.72.1", + "@typescript-eslint/utils": "8.72.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10751,41 +10658,39 @@ } }, "node_modules/unrs-resolver": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.12.2.tgz", - "integrity": "sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.13.0.tgz", + "integrity": "sha512-mcPQo9Vm6kXd84d/WqMiYBi2CcA57QHBX/ev5PoUEb8b2oQzUvJ6xYsfseQblnCncgnVmCZGWiFwK7KkS5JZJA==", "dev": true, - "hasInstallScript": true, "license": "MIT", "dependencies": { - "napi-postinstall": "^0.3.4" + "napi-postinstall": "^0.3.7" }, "funding": { "url": "https://opencollective.com/unrs-resolver" }, "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.12.2", - "@unrs/resolver-binding-android-arm64": "1.12.2", - "@unrs/resolver-binding-darwin-arm64": "1.12.2", - "@unrs/resolver-binding-darwin-x64": "1.12.2", - "@unrs/resolver-binding-freebsd-x64": "1.12.2", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.12.2", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.12.2", - "@unrs/resolver-binding-linux-arm64-gnu": "1.12.2", - "@unrs/resolver-binding-linux-arm64-musl": "1.12.2", - "@unrs/resolver-binding-linux-loong64-gnu": "1.12.2", - "@unrs/resolver-binding-linux-loong64-musl": "1.12.2", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.12.2", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.12.2", - "@unrs/resolver-binding-linux-riscv64-musl": "1.12.2", - "@unrs/resolver-binding-linux-s390x-gnu": "1.12.2", - "@unrs/resolver-binding-linux-x64-gnu": "1.12.2", - "@unrs/resolver-binding-linux-x64-musl": "1.12.2", - "@unrs/resolver-binding-openharmony-arm64": "1.12.2", - "@unrs/resolver-binding-wasm32-wasi": "1.12.2", - "@unrs/resolver-binding-win32-arm64-msvc": "1.12.2", - "@unrs/resolver-binding-win32-ia32-msvc": "1.12.2", - "@unrs/resolver-binding-win32-x64-msvc": "1.12.2" + "@unrs/resolver-binding-android-arm-eabi": "1.13.0", + "@unrs/resolver-binding-android-arm64": "1.13.0", + "@unrs/resolver-binding-darwin-arm64": "1.13.0", + "@unrs/resolver-binding-darwin-x64": "1.13.0", + "@unrs/resolver-binding-freebsd-x64": "1.13.0", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.13.0", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.13.0", + "@unrs/resolver-binding-linux-arm64-gnu": "1.13.0", + "@unrs/resolver-binding-linux-arm64-musl": "1.13.0", + "@unrs/resolver-binding-linux-loong64-gnu": "1.13.0", + "@unrs/resolver-binding-linux-loong64-musl": "1.13.0", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.13.0", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.13.0", + "@unrs/resolver-binding-linux-riscv64-musl": "1.13.0", + "@unrs/resolver-binding-linux-s390x-gnu": "1.13.0", + "@unrs/resolver-binding-linux-x64-gnu": "1.13.0", + "@unrs/resolver-binding-linux-x64-musl": "1.13.0", + "@unrs/resolver-binding-openharmony-arm64": "1.13.0", + "@unrs/resolver-binding-win32-arm64-msvc": "1.13.0", + "@unrs/resolver-binding-win32-ia32-msvc": "1.13.0", + "@unrs/resolver-binding-win32-x64-msvc": "1.13.0" } }, "node_modules/update-browserslist-db": { @@ -11080,9 +10985,9 @@ } }, "node_modules/ws": { - "version": "8.22.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz", - "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==", + "version": "8.22.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.1.tgz", + "integrity": "sha512-oyL6OPYme/CmiFvNuGzeoxCJ4nOrZE2O1FwM9MWM1AsGri6nLXB2pg+lNA8aLeXMSav0J6eIVS1j6vUPzUtK9g==", "dev": true, "license": "MIT", "engines": { diff --git a/deps/undici/src/package.json b/deps/undici/src/package.json index c00a1cfc1d8f..d1a37891d309 100644 --- a/deps/undici/src/package.json +++ b/deps/undici/src/package.json @@ -1,6 +1,6 @@ { "name": "undici", - "version": "7.30.1", + "version": "7.30.2", "description": "An HTTP/1.1 client, written from scratch for Node.js", "homepage": "https://undici.nodejs.org", "bugs": { diff --git a/deps/undici/src/types/dispatcher.d.ts b/deps/undici/src/types/dispatcher.d.ts index 3f2ec3d498bd..041da32ea1f1 100644 --- a/deps/undici/src/types/dispatcher.d.ts +++ b/deps/undici/src/types/dispatcher.d.ts @@ -113,7 +113,7 @@ declare namespace Dispatcher { idempotent?: boolean; /** Whether the response is expected to take a long time and would end up blocking the pipeline. When this is set to `true` further pipelining will be avoided on the same connection until headers have been received. Defaults to `method !== 'HEAD'`. */ blocking?: boolean; - /** The IP Type of Service (ToS) value for the request socket. Must be an integer between 0 and 255. Default: `0` */ + /** The IP Type of Service (ToS) value for the request socket. Must be an integer between 0 and 255. */ typeOfService?: number | null; /** Upgrade the request. Should be used to specify the kind of upgrade i.e. `'Websocket'`. Default: `method === 'CONNECT' || null`. */ upgrade?: boolean | string | null; diff --git a/deps/undici/undici.js b/deps/undici/undici.js index 73539e80c6ed..98cfafc4a66f 100644 --- a/deps/undici/undici.js +++ b/deps/undici/undici.js @@ -1509,6 +1509,20 @@ var require_util = __commonJS({ return ret; } __name(parseRawHeaders, "parseRawHeaders"); + function toRawHeaders(headers) { + const rawHeaders = []; + for (const [name, value] of Object.entries(headers)) { + if (Array.isArray(value)) { + for (const entry of value) { + rawHeaders.push(Buffer.from(name, "latin1"), Buffer.from(`${entry}`, "latin1")); + } + } else { + rawHeaders.push(Buffer.from(name, "latin1"), Buffer.from(`${value}`, "latin1")); + } + } + return rawHeaders; + } + __name(toRawHeaders, "toRawHeaders"); function encodeRawHeaders(headers) { if (!Array.isArray(headers)) { throw new TypeError("expected headers to be an array"); @@ -2047,6 +2061,7 @@ var require_util = __commonJS({ removeAllListeners, errorRequest, parseRawHeaders, + toRawHeaders, encodeRawHeaders, parseHeaders, parseKeepAliveTimeout, @@ -2961,7 +2976,7 @@ var require_request = __commonJS({ this.headersTimeout = headersTimeout; this.bodyTimeout = bodyTimeout; this.method = method; - this.typeOfService = typeOfService ?? 0; + this.typeOfService = typeOfService; this.abort = null; if (body == null) { this.body = null; @@ -6865,19 +6880,38 @@ var require_body = __commonJS({ }); function extractBody(object, keepalive = false) { let stream = null; - let controller = null; if (webidl.is.ReadableStream(object)) { stream = object; } else if (webidl.is.Blob(object)) { stream = object.stream(); } else { stream = new ReadableStream({ - pull() { + start() { }, - start(c) { - controller = c; + async pull(controller) { + const result = action(); + const iterator = result?.[Symbol.asyncIterator]?.(); + if (iterator == null) { + if (result?.length && !isErrored(stream)) { + controller.enqueue(typeof result === "string" ? textEncoder.encode(result) : new Uint8Array(result)); + } + queueMicrotask(() => readableStreamClose(controller)); + return; + } + while (true) { + const { value, done } = await iterator.next(); + if (done) { + queueMicrotask(() => readableStreamClose(controller)); + return; + } + if (value.length && !isErrored(stream)) { + controller.enqueue(new Uint8Array(value)); + return; + } + } }, - cancel() { + cancel(reason) { + return action()[Symbol.asyncIterator]?.().return(reason); }, type: "bytes" }); @@ -6934,7 +6968,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r length = null; } source = object; - action = /* @__PURE__ */ __name(async function* () { + const parts = (async function* () { for (const part of blobParts) { if (part.stream) { yield* part.stream(); @@ -6942,7 +6976,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r yield part; } } - }, "action"); + })(); + action = /* @__PURE__ */ __name(() => parts, "action"); type = `multipart/form-data; boundary=${boundary}`; } else if (webidl.is.Blob(object)) { source = object; @@ -6962,28 +6997,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r stream = webidl.is.ReadableStream(object) ? object : ReadableStreamFrom(object); } if (typeof source === "string" || isUint8Array(source)) { - action = /* @__PURE__ */ __name(() => { - length = typeof source === "string" ? Buffer.byteLength(source) : source.length; - return source; - }, "action"); - } - if (action != null) { - ; - (async () => { - const result = action(); - const iterator = result?.[Symbol.asyncIterator]?.(); - if (iterator) { - for await (const bytes of iterator) { - if (isErrored(stream)) break; - if (bytes.length) { - controller.enqueue(new Uint8Array(bytes)); - } - } - } else if (result?.length && !isErrored(stream)) { - controller.enqueue(typeof result === "string" ? textEncoder.encode(result) : new Uint8Array(result)); - } - queueMicrotask(() => readableStreamClose(controller)); - })(); + action = /* @__PURE__ */ __name(() => source, "action"); + length = typeof source === "string" ? Buffer.byteLength(source) : source.length; } const body = { stream, source, length }; return [body, type]; @@ -7184,6 +7199,7 @@ var require_client_h1 = __commonJS({ var kIdleSocketValidation = /* @__PURE__ */ Symbol("kIdleSocketValidation"); var kIdleSocketValidationTimeout = /* @__PURE__ */ Symbol("kIdleSocketValidationTimeout"); var kSocketUsed = /* @__PURE__ */ Symbol("kSocketUsed"); + var kTypeOfService = /* @__PURE__ */ Symbol("kTypeOfService"); var extractBody; function lazyllhttp() { const llhttpWasmData = process.env.JEST_WORKER_ID ? require_llhttp_wasm() : void 0; @@ -7986,6 +8002,25 @@ var require_client_h1 = __commonJS({ return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; } __name(shouldSendContentLength, "shouldSendContentLength"); + function setTypeOfService(socket, request) { + if (typeof socket.setTypeOfService !== "function") { + return; + } + const typeOfService = request.typeOfService; + if (typeOfService === void 0) { + return; + } + const currentTypeOfService = socket[kTypeOfService]; + if (currentTypeOfService === typeOfService) { + return; + } + try { + socket.setTypeOfService(typeOfService); + socket[kTypeOfService] = typeOfService; + } catch { + } + } + __name(setTypeOfService, "setTypeOfService"); function writeH1(client, request) { const { method, path, host, upgrade, blocking, reset } = request; let { body, headers, contentLength } = request; @@ -8062,9 +8097,7 @@ var require_client_h1 = __commonJS({ if (blocking) { socket[kBlocking] = true; } - if (socket.setTypeOfService) { - socket.setTypeOfService(request.typeOfService); - } + setTypeOfService(socket, request); let header = `${method} ${path} HTTP/1.1\r `; if (typeof host === "string") { @@ -12907,7 +12940,7 @@ var require_subresource_integrity = __commonJS({ __name(getStrongestMetadata, "getStrongestMetadata"); function parseMetadata(metadata) { const result = []; - for (const item of metadata.split(" ")) { + for (const item of metadata.split(/[\t\n\f\r ]+/)) { const expressionAndOptions = item.split("?", 1); const algorithmExpression = expressionAndOptions[0]; let base64Value = ""; diff --git a/src/undici_version.h b/src/undici_version.h index f192be95a9ed..5b8e0a41e493 100644 --- a/src/undici_version.h +++ b/src/undici_version.h @@ -2,5 +2,5 @@ // Refer to tools/dep_updaters/update-undici.sh #ifndef SRC_UNDICI_VERSION_H_ #define SRC_UNDICI_VERSION_H_ -#define UNDICI_VERSION "7.30.1" +#define UNDICI_VERSION "7.30.2" #endif // SRC_UNDICI_VERSION_H_