diff --git a/dist/query.js b/dist/query.js index 4c7d945a..0742ce08 100644 --- a/dist/query.js +++ b/dist/query.js @@ -2098,6 +2098,7 @@ var require_dispatcher = __commonJS({ var require_dispatcher_base = __commonJS({ "node_modules/undici/lib/dispatcher/dispatcher-base.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var Dispatcher = require_dispatcher(); var { ClientDestroyedError, @@ -2109,6 +2110,7 @@ var require_dispatcher_base = __commonJS({ var kOnClosed = /* @__PURE__ */ Symbol("onClosed"); var kInterceptedDispatch = /* @__PURE__ */ Symbol("Intercepted Dispatch"); var kWebSocketOptions = /* @__PURE__ */ Symbol("webSocketOptions"); + var kEventSourceOptions = /* @__PURE__ */ Symbol("eventSourceOptions"); var DispatcherBase = class extends Dispatcher { constructor(opts) { super(); @@ -2117,6 +2119,7 @@ var require_dispatcher_base = __commonJS({ this[kClosed] = false; this[kOnClosed] = []; this[kWebSocketOptions] = opts?.webSocket ?? {}; + this[kEventSourceOptions] = opts?.eventSource ?? {}; } get webSocketOptions() { return { @@ -2124,6 +2127,11 @@ var require_dispatcher_base = __commonJS({ maxPayloadSize: this[kWebSocketOptions].maxPayloadSize ?? 128 * 1024 * 1024 }; } + get eventSourceOptions() { + return { + maxEventSize: this[kEventSourceOptions].maxEventSize ?? buffer.kStringMaxLength + }; + } get destroyed() { return this[kDestroyed]; } @@ -6271,7 +6279,6 @@ var require_client_h1 = __commonJS({ socket[kSocketUsed] = false; socket[kParser] = new Parser(client, socket, llhttpInstance); addListener(socket, "error", function(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); const parser = this[kParser]; if (err.code === "ECONNRESET" && parser.statusCode && !parser.shouldKeepAlive) { const parserErr = parser.finish(); @@ -6955,7 +6962,6 @@ var require_client_h2 = __commonJS({ client[kHTTP2Session] = session; socket[kHTTP2Session] = session; util3.addListener(socket, "error", function(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kError] = err; this[kClient][kOnError](err); }); @@ -7014,7 +7020,6 @@ var require_client_h2 = __commonJS({ } } function onHttp2SessionError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kSocket][kError] = err; this[kClient][kOnError](err); } @@ -7708,9 +7713,10 @@ var require_client = __commonJS({ // h2 maxConcurrentStreams, allowH2, - webSocket + webSocket, + eventSource } = {}) { - super({ webSocket }); + super({ webSocket, eventSource }); if (keepAlive !== void 0) { throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead"); } @@ -8607,7 +8613,7 @@ var require_agent = __commonJS({ return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts); } var Agent3 = class extends DispatcherBase { - constructor({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { + constructor({ factory = defaultFactory, maxRedirections = 0, connect, tls, ...options } = {}) { if (typeof factory !== "function") { throw new InvalidArgumentError("factory must be a function."); } @@ -8621,8 +8627,11 @@ var require_agent = __commonJS({ if (connect && typeof connect !== "function") { connect = { ...connect }; } + if (tls && typeof tls !== "function") { + tls = { ...tls }; + } this[kInterceptors] = options.interceptors?.Agent && Array.isArray(options.interceptors.Agent) ? options.interceptors.Agent : [createRedirectInterceptor({ maxRedirections })]; - this[kOptions] = { ...util3.deepClone(options), connect }; + this[kOptions] = { ...util3.deepClone(options), connect, tls }; this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0; this[kMaxRedirections] = maxRedirections; this[kFactory] = factory; @@ -14350,8 +14359,9 @@ var require_fetch = __commonJS({ } ); response.body = { stream: stream3, source: null, length: null }; - fetchParams.controller.onAborted = onAborted; - fetchParams.controller.on("terminated", onAborted); + if (!fetchParams.controller.resume) { + fetchParams.controller.on("terminated", onAborted); + } fetchParams.controller.resume = async () => { while (true) { let bytes; @@ -14451,7 +14461,6 @@ var require_fetch = __commonJS({ headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString("latin1"), true); } location = headersList.get("location", true); - this.body = new Readable({ read: resume }); const decoders = []; const willFollow = location && request2.redirect === "follow" && redirectStatusSet.has(status); if (request2.method !== "HEAD" && request2.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) { @@ -14459,7 +14468,7 @@ var require_fetch = __commonJS({ const codings = contentEncoding ? contentEncoding.toLowerCase().split(",") : []; const maxContentEncodings = 5; if (codings.length > maxContentEncodings) { - reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); + this.abort(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); return true; } for (let i = codings.length - 1; i >= 0; --i) { @@ -14489,6 +14498,7 @@ var require_fetch = __commonJS({ } } } + this.body = new Readable({ read: resume }); const onError = this.onError.bind(this); resolve2({ status, @@ -14514,9 +14524,6 @@ var require_fetch = __commonJS({ if (this.abort) { fetchParams.controller.off("terminated", this.abort); } - if (fetchParams.controller.onAborted) { - fetchParams.controller.off("terminated", fetchParams.controller.onAborted); - } fetchParams.controller.ended = true; this.body.push(null); }, @@ -17590,6 +17597,16 @@ var require_receiver = __commonJS({ if (isControlFrame(this.#info.opcode)) { this.#loop = this.parseControlFrame(body); this.#state = parserStates.INFO; + const socket = this.ws[kResponse].socket; + if (this.#loop && socket.writableNeedDrain) { + this.#loop = false; + socket.once("drain", () => { + if (this.destroyed) return; + this.#loop = true; + this.run(callback); + }); + return; + } } else { if (!this.#info.compressed) { if (!this.writeFragments(body)) { @@ -18283,6 +18300,7 @@ var require_util8 = __commonJS({ var require_eventsource_stream = __commonJS({ "node_modules/undici/lib/web/eventsource/eventsource-stream.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var { Transform } = require("node:stream"); var { isASCIINumber, isValidLastEventId } = require_util8(); var BOM = [239, 187, 191]; @@ -18290,24 +18308,28 @@ var require_eventsource_stream = __commonJS({ var CR = 13; var COLON = 58; var SPACE = 32; + var defaultMaxEventSize = buffer.kStringMaxLength; var DATA = Buffer.from("data"); var EVENT = Buffer.from("event"); var ID = Buffer.from("id"); var RETRY = Buffer.from("retry"); - function isASCIINumberBytes(buffer, start) { - if (start >= buffer.length) { + var minParserItems = 1024; + var maxParserItems = 131072; + var bytesPerParserItem = 128; + function isASCIINumberBytes(buffer2, start) { + if (start >= buffer2.length) { return false; } - for (let i = start; i < buffer.length; i++) { - if (buffer[i] < 48 || buffer[i] > 57) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] < 48 || buffer2[i] > 57) { return false; } } return true; } - function isValidLastEventIdBytes(buffer, start) { - for (let i = start; i < buffer.length; i++) { - if (buffer[i] === 0) { + function isValidLastEventIdBytes(buffer2, start) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] === 0) { return false; } } @@ -18324,6 +18346,11 @@ var require_eventsource_stream = __commonJS({ } return true; } + function createMaxEventSizeExceededError() { + const error2 = new Error("EventSource message size exceeded"); + error2.aborted = false; + return error2; + } var EventSourceStream = class extends Transform { /** * @type {eventSourceSettings} @@ -18350,6 +18377,13 @@ var require_eventsource_stream = __commonJS({ pos = 0; lineChunkIndex = 0; linePos = 0; + lineLength = 0; + eventSize = 0; + eventFieldSizes = { data: 0, event: 0, id: 0, retry: 0 }; + dataLineCount = 0; + maxEventSize; + maxDataLines; + maxBufferedChunks; event = { data: void 0, event: void 0, @@ -18358,6 +18392,7 @@ var require_eventsource_stream = __commonJS({ }; /** * @param {object} options + * @param {number} [options.maxEventSize] * @param {eventSourceSettings} options.eventSourceSettings * @param {Function} [options.push] */ @@ -18365,6 +18400,10 @@ var require_eventsource_stream = __commonJS({ options.readableObjectMode = true; super(options); this.state = options.eventSourceSettings || {}; + this.maxEventSize = options.maxEventSize ?? defaultMaxEventSize; + const parserItemLimit = this.maxEventSize > 0 ? Math.min(maxParserItems, Math.max(minParserItems, Math.floor(this.maxEventSize / bytesPerParserItem))) : 0; + this.maxDataLines = parserItemLimit; + this.maxBufferedChunks = parserItemLimit; if (options.push) { this.push = options.push; } @@ -18380,6 +18419,10 @@ var require_eventsource_stream = __commonJS({ callback(); return; } + if (this.maxEventSize > 0 && this.chunks.length >= this.maxBufferedChunks && chunk[0] !== LF && chunk[0] !== CR) { + callback(createMaxEventSizeExceededError()); + return; + } this.chunks.push(chunk); if (this.checkBOM) { if (this.handleBOM()) { @@ -18416,18 +18459,32 @@ var require_eventsource_stream = __commonJS({ if (byte === CR) { this.crlfCheck = true; } - this.parseLine(this.readLine(), this.event); + try { + this.parseLine(this.readLine(), this.event); + } catch (error2) { + callback(error2); + return; + } this.consumeCurrentByte(); this.eventEndCheck = true; continue; } + if (this.maxEventSize > 0 && ++this.lineLength > this.maxEventSize + 7) { + callback(createMaxEventSizeExceededError()); + return; + } this.advanceCursor(); } callback(); } + _destroy(error2, callback) { + this.chunks.length = 0; + this.clearEvent(); + super._destroy(error2, callback); + } /** * @param {Buffer} line - * @param {EventStreamEvent} event + * @param {EventSourceStreamEvent} event */ parseLine(line, event) { if (line.length === 0) { @@ -18447,6 +18504,12 @@ var require_eventsource_stream = __commonJS({ } } if (isFieldName(line, fieldLength, DATA)) { + if (this.maxEventSize > 0 && this.dataLineCount >= this.maxDataLines) { + throw createMaxEventSizeExceededError(); + } + const valueBytes = line.length - valueStart; + const dataSize = this.eventFieldSizes.data + (event.data === void 0 ? 0 : 1) + valueBytes; + this.setEventFieldSize("data", dataSize); const value = line.toString("utf8", valueStart); if (event.data === void 0) { event.data = value; @@ -18454,27 +18517,38 @@ var require_eventsource_stream = __commonJS({ event.data += ` ${value}`; } + this.dataLineCount++; return; } if (isFieldName(line, fieldLength, RETRY)) { if (isASCIINumberBytes(line, valueStart)) { + this.setEventFieldSize("retry", line.length - valueStart); event.retry = line.toString("utf8", valueStart); } return; } if (isFieldName(line, fieldLength, ID)) { if (isValidLastEventIdBytes(line, valueStart)) { + this.setEventFieldSize("id", line.length - valueStart); event.id = line.toString("utf8", valueStart); } return; } if (isFieldName(line, fieldLength, EVENT)) { - const value = line.toString("utf8", valueStart); - if (value.length > 0) { - event.event = value; + if (valueStart < line.length) { + this.setEventFieldSize("event", line.length - valueStart); + event.event = line.toString("utf8", valueStart); } } } + setEventFieldSize(field, size) { + const eventSize = this.eventSize - this.eventFieldSizes[field] + size; + if (this.maxEventSize > 0 && eventSize > this.maxEventSize) { + throw createMaxEventSizeExceededError(); + } + this.eventSize = eventSize; + this.eventFieldSizes[field] = size; + } /** * @param {EventSourceStreamEvent} event */ @@ -18501,6 +18575,12 @@ ${value}`; this.event.event = void 0; this.event.id = void 0; this.event.retry = void 0; + this.eventSize = 0; + this.dataLineCount = 0; + this.eventFieldSizes.data = 0; + this.eventFieldSizes.event = 0; + this.eventFieldSizes.id = 0; + this.eventFieldSizes.retry = 0; } hasPendingEvent() { return this.event.data !== void 0 || this.event.event !== void 0 || this.event.id !== void 0 || this.event.retry !== void 0; @@ -18525,13 +18605,15 @@ ${value}`; syncLineStartToCursor() { this.lineChunkIndex = this.chunkIndex; this.linePos = this.pos; + this.lineLength = 0; this.dropConsumedChunks(); } dropConsumedChunks() { - while (this.lineChunkIndex > 0) { - this.chunks.shift(); - this.lineChunkIndex--; - this.chunkIndex--; + if (this.lineChunkIndex > 0) { + const consumed = this.lineChunkIndex; + this.chunks.splice(0, consumed); + this.lineChunkIndex = 0; + this.chunkIndex -= consumed; } if (this.chunkIndex === this.chunks.length) { this.chunks.length = 0; @@ -18634,6 +18716,7 @@ var require_eventsource = __commonJS({ var { delay } = require_util8(); var { kEnumerableProperty } = require_util(); var { environmentSettingsObject } = require_util2(); + var { getGlobalDispatcher } = require_global2(); var experimentalWarned = false; var defaultReconnectionTime = 3e3; var CONNECTING = 0; @@ -18774,6 +18857,7 @@ var require_eventsource = __commonJS({ this.#state.origin = response.urlList[response.urlList.length - 1].origin; const eventSourceStream = new EventSourceStream({ eventSourceSettings: this.#state, + maxEventSize: this.#dispatcher.eventSourceOptions?.maxEventSize, push: (event) => { this.dispatchEvent(createFastMessageEvent( event.type, @@ -18906,7 +18990,8 @@ var require_eventsource = __commonJS({ { key: "dispatcher", // undici only - converter: webidl.converters.any + converter: webidl.converters.any, + defaultValue: () => getGlobalDispatcher() } ]); module2.exports = { @@ -41165,6 +41250,7 @@ var require_symbols6 = __commonJS({ kDestroy: /* @__PURE__ */ Symbol("destroy"), kDispatch: /* @__PURE__ */ Symbol("dispatch"), kUrl: /* @__PURE__ */ Symbol("url"), + kRedirectCacheControl: /* @__PURE__ */ Symbol("redirect cache control"), kWriting: /* @__PURE__ */ Symbol("writing"), kResuming: /* @__PURE__ */ Symbol("resuming"), kQueue: /* @__PURE__ */ Symbol("queue"), @@ -42412,6 +42498,19 @@ var require_util10 = __commonJS({ } return ret; } + 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; + } function encodeRawHeaders(headers) { if (!Array.isArray(headers)) { throw new TypeError("expected headers to be an array"); @@ -42933,6 +43032,7 @@ var require_util10 = __commonJS({ removeAllListeners, errorRequest: errorRequest2, parseRawHeaders, + toRawHeaders, encodeRawHeaders, parseHeaders, parseKeepAliveTimeout, @@ -43318,7 +43418,7 @@ var require_request3 = __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; @@ -43829,6 +43929,7 @@ var require_unwrap_handler = __commonJS({ var require_dispatcher_base2 = __commonJS({ "node_modules/@octokit/action/node_modules/undici/lib/dispatcher/dispatcher-base.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var Dispatcher = require_dispatcher2(); var UnwrapHandler = require_unwrap_handler(); var { @@ -43840,6 +43941,7 @@ var require_dispatcher_base2 = __commonJS({ var kOnDestroyed = /* @__PURE__ */ Symbol("onDestroyed"); var kOnClosed = /* @__PURE__ */ Symbol("onClosed"); var kWebSocketOptions = /* @__PURE__ */ Symbol("webSocketOptions"); + var kEventSourceOptions = /* @__PURE__ */ Symbol("eventSourceOptions"); var DispatcherBase = class extends Dispatcher { /** @type {boolean} */ [kDestroyed] = false; @@ -43855,6 +43957,7 @@ var require_dispatcher_base2 = __commonJS({ constructor(opts) { super(); this[kWebSocketOptions] = opts?.webSocket ?? {}; + this[kEventSourceOptions] = opts?.eventSource ?? {}; } /** * @returns {import('../../types/dispatcher').WebSocketOptions} @@ -43866,6 +43969,14 @@ var require_dispatcher_base2 = __commonJS({ // 128 MB default }; } + /** + * @returns {import('../../types/client').Client.EventSourceOptions} + */ + get eventSourceOptions() { + return { + maxEventSize: this[kEventSourceOptions].maxEventSize ?? buffer.kStringMaxLength + }; + } /** @returns {boolean} */ get destroyed() { return this[kDestroyed]; @@ -44011,15 +44122,19 @@ var require_connect2 = __commonJS({ if (this._sessionCache.has(sessionKey)) { this._sessionCache.delete(sessionKey); } else if (this._sessionCache.size >= this._maxCachedSessions) { + let evicted = false; for (const [key, ref] of this._sessionCache) { if (ref.deref() === void 0) { this._sessionCache.delete(key); - return; + evicted = true; + break; } } - const oldest = this._sessionCache.keys().next(); - if (!oldest.done) { - this._sessionCache.delete(oldest.value); + if (!evicted) { + const oldest = this._sessionCache.keys().next(); + if (!oldest.done) { + this._sessionCache.delete(oldest.value); + } } } this._sessionCache.set(sessionKey, new WeakRef(session)); @@ -45078,6 +45193,10 @@ var require_infra = __commonJS({ return input.slice(start, position.position); } var ASCII_WHITESPACE_REPLACE_REGEX = /[\u0009\u000A\u000C\u000D\u0020]/g; + var nonASCIIRegex = /[^\x00-\x7F]/; + function asciiLowercase(str) { + return nonASCIIRegex.test(str) ? str.replace(/[A-Z]+/g, (upper) => upper.toLowerCase()) : str.toLowerCase(); + } function forgivingBase64(data) { data = data.replace(ASCII_WHITESPACE_REPLACE_REGEX, ""); let dataLength = data.length; @@ -45152,6 +45271,7 @@ var require_infra = __commonJS({ return result; } module2.exports = { + asciiLowercase, collectASequenceOfCodePoints, collectASequenceOfCodePointsFast, forgivingBase64, @@ -47461,19 +47581,38 @@ var require_body2 = __commonJS({ }); function extractBody(object, keepalive = false) { let stream3 = null; - let controller = null; if (webidl.is.ReadableStream(object)) { stream3 = object; } else if (webidl.is.Blob(object)) { stream3 = object.stream(); } else { stream3 = new ReadableStream({ - pull() { + start() { }, - start(c) { - controller = c; + async pull(controller) { + const result = action(); + const iterator2 = result?.[Symbol.asyncIterator]?.(); + if (iterator2 == null) { + if (result?.length && !isErrored(stream3)) { + controller.enqueue(typeof result === "string" ? textEncoder.encode(result) : new Uint8Array(result)); + } + queueMicrotask(() => readableStreamClose(controller)); + return; + } + while (true) { + const { value, done } = await iterator2.next(); + if (done) { + queueMicrotask(() => readableStreamClose(controller)); + return; + } + if (value.length && !isErrored(stream3)) { + controller.enqueue(new Uint8Array(value)); + return; + } + } }, - cancel() { + cancel(reason) { + return action()[Symbol.asyncIterator]?.().return(reason); }, type: "bytes" }); @@ -47530,7 +47669,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r length = null; } source = object; - action = async function* () { + const parts = (async function* () { for (const part of blobParts) { if (part.stream) { yield* part.stream(); @@ -47538,7 +47677,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r yield part; } } - }; + })(); + action = () => parts; type = `multipart/form-data; boundary=${boundary}`; } else if (webidl.is.Blob(object)) { source = object; @@ -47558,28 +47698,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r stream3 = webidl.is.ReadableStream(object) ? object : ReadableStreamFrom(object); } if (typeof source === "string" || isUint8Array(source)) { - action = () => { - length = typeof source === "string" ? Buffer.byteLength(source) : source.length; - return source; - }; - } - if (action != null) { - ; - (async () => { - const result = action(); - const iterator2 = result?.[Symbol.asyncIterator]?.(); - if (iterator2) { - for await (const bytes of iterator2) { - if (isErrored(stream3)) break; - if (bytes.length) { - controller.enqueue(new Uint8Array(bytes)); - } - } - } else if (result?.length && !isErrored(stream3)) { - controller.enqueue(typeof result === "string" ? textEncoder.encode(result) : new Uint8Array(result)); - } - queueMicrotask(() => readableStreamClose(controller)); - })(); + action = () => source; + length = typeof source === "string" ? Buffer.byteLength(source) : source.length; } const body = { stream: stream3, source, length }; return [body, type]; @@ -47772,6 +47892,7 @@ var require_client_h12 = __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_wasm2() : void 0; @@ -48431,7 +48552,6 @@ var require_client_h12 = __commonJS({ }; } function onHttpSocketError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); const parser = this[kParser]; if (err.code === "ECONNRESET" && parser.statusCode && !parser.shouldKeepAlive) { const parserErr = parser.finish(); @@ -48560,6 +48680,24 @@ var require_client_h12 = __commonJS({ function shouldSendContentLength(method) { return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; } + function setTypeOfService(socket, request2) { + if (typeof socket.setTypeOfService !== "function") { + return; + } + const typeOfService = request2.typeOfService; + if (typeOfService === void 0) { + return; + } + const currentTypeOfService = socket[kTypeOfService]; + if (currentTypeOfService === typeOfService) { + return; + } + try { + socket.setTypeOfService(typeOfService); + socket[kTypeOfService] = typeOfService; + } catch { + } + } function writeH1(client, request2) { const { method, path: path8, host, upgrade, blocking, reset } = request2; let { body, headers, contentLength } = request2; @@ -48636,9 +48774,7 @@ var require_client_h12 = __commonJS({ if (blocking) { socket[kBlocking] = true; } - if (socket.setTypeOfService) { - socket.setTypeOfService(request2.typeOfService); - } + setTypeOfService(socket, request2); let header = `${method} ${path8} HTTP/1.1\r `; if (typeof host === "string") { @@ -49211,7 +49347,6 @@ var require_client_h22 = __commonJS({ } } function onHttp2SessionError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kSocket][kError] = err; this[kClient][kOnError](err); } @@ -49301,7 +49436,6 @@ var require_client_h22 = __commonJS({ client[kResume](); } function onHttp2SocketError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kError] = err; this[kClient][kOnError](err); } @@ -49862,7 +49996,8 @@ var require_client2 = __commonJS({ initialWindowSize, connectionWindowSize, pingInterval, - webSocket + webSocket, + eventSource } = {}) { if (keepAlive !== void 0) { throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead"); @@ -49940,7 +50075,7 @@ var require_client2 = __commonJS({ if (pingInterval != null && (typeof pingInterval !== "number" || !Number.isInteger(pingInterval) || pingInterval < 0)) { throw new InvalidArgumentError("pingInterval must be a positive integer, greater or equal to 0"); } - super({ webSocket }); + super({ webSocket, eventSource }); if (typeof connect2 !== "function") { connect2 = buildConnector({ ...tls, @@ -50921,7 +51056,7 @@ var require_agent2 = __commonJS({ return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts); } var Agent3 = class extends DispatcherBase { - constructor({ factory = defaultFactory, maxOrigins = Infinity, connect, ...options } = {}) { + constructor({ factory = defaultFactory, maxOrigins = Infinity, connect, tls, ...options } = {}) { if (typeof factory !== "function") { throw new InvalidArgumentError("factory must be a function."); } @@ -50935,7 +51070,10 @@ var require_agent2 = __commonJS({ if (connect && typeof connect !== "function") { connect = { ...connect }; } - this[kOptions] = { ...util3.deepClone(options), maxOrigins, connect }; + if (tls && typeof tls !== "function") { + tls = { ...tls }; + } + this[kOptions] = { ...util3.deepClone(options), maxOrigins, connect, tls }; this[kFactory] = factory; this[kClients] = /* @__PURE__ */ new Map(); this[kOrigins] = /* @__PURE__ */ new Set(); @@ -55799,7 +55937,7 @@ var require_redirect_handler2 = __commonJS({ "node_modules/@octokit/action/node_modules/undici/lib/handler/redirect-handler.js"(exports2, module2) { "use strict"; var util3 = require_util10(); - var { kBodyUsed } = require_symbols6(); + var { kBodyUsed, kRedirectCacheControl } = require_symbols6(); var assert = require("node:assert"); var { InvalidArgumentError } = require_errors2(); var EE = require("node:events"); @@ -55837,6 +55975,10 @@ var require_redirect_handler2 = __commonJS({ this.maxRedirections = maxRedirections; this.handler = handler2; this.history = []; + Object.defineProperty(this.history, kRedirectCacheControl, { + value: [], + enumerable: false + }); if (util3.isStream(this.opts.body)) { if (util3.bodyLength(this.opts.body) === 0) { this.opts.body.on("data", function() { @@ -55887,6 +56029,11 @@ var require_redirect_handler2 = __commonJS({ this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage); return; } + this.history[kRedirectCacheControl].push({ + statusCode, + headers: { ...headers }, + receivedAt: Date.now() + }); const { origin, pathname, search } = util3.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin))); const path8 = search ? `${pathname}${search}` : pathname; const redirectUrlString = `${origin}${path8}`; @@ -55933,9 +56080,17 @@ var require_redirect_handler2 = __commonJS({ 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]); + if (headers.length > 0 && Array.isArray(headers[0])) { + for (const [key, value] of headers) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + ret.push(key, value); + } + } + } else { + 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") { @@ -56754,15 +56909,46 @@ var require_cache2 = __commonJS({ } else if (typeof opts.headers === "object") { 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)) { + 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)) { @@ -57588,6 +57774,7 @@ var require_cache_handler = __commonJS({ "node_modules/@octokit/action/node_modules/undici/lib/handler/cache-handler.js"(exports2, module2) { "use strict"; var util3 = require_util10(); + var { kRedirectCacheControl } = require_symbols6(); var { parseCacheControlHeader, hasInvalidCacheControlDirective, @@ -57599,6 +57786,13 @@ var require_cache_handler = __commonJS({ var { parseHttpDate } = require_date(); function noop4() { } + function sameOrigin(a, b) { + try { + return new URL(String(a)).origin === new URL(String(b)).origin; + } catch { + return String(a) === String(b); + } + } var HEURISTICALLY_CACHEABLE_STATUS_CODES = [ 200, 203, @@ -57617,6 +57811,7 @@ var require_cache_handler = __commonJS({ 206 ]; var MAX_RESPONSE_AGE = 2147483647e3; + var REVALIDATION_ONLY_RETENTION = 864e5; function trimOWS(value) { return value.replace(/^[\t ]+|[\t ]+$/g, ""); } @@ -57628,6 +57823,15 @@ var require_cache_handler = __commonJS({ } 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]; for (let i = 0; i < values.length; i++) { @@ -57689,6 +57893,9 @@ var require_cache_handler = __commonJS({ deleteLocationTargets(store, cacheKey, resHeaders.location); deleteLocationTargets(store, cacheKey, resHeaders["content-location"]); } + function requestCarriesCredentials(headers) { + return headers != null && (Object.hasOwn(headers, "authorization") || Object.hasOwn(headers, "cookie") || Object.hasOwn(headers, "proxy-authorization")); + } var CacheHandler = class { /** * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey} @@ -57714,6 +57921,19 @@ var require_cache_handler = __commonJS({ * @type {import('node:stream').Writable | undefined} */ #writeStream; + /** + * The URLs visited while following redirects, shared by reference from the + * redirect handler through the request context. Carries the suppressed hops' + * 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 @@ -57729,6 +57949,10 @@ var require_cache_handler = __commonJS({ onRequestStart(controller, context) { this.#writeStream?.destroy(); this.#writeStream = void 0; + this.#replaying304 = false; + this.#suppress304End = false; + this.#pending304End = void 0; + this.#history = context?.history; this.#handler.onRequestStart?.(controller, context); } onRequestUpgrade(controller, statusCode, headers, socket) { @@ -57752,6 +57976,29 @@ var require_cache_handler = __commonJS({ invalidateUnsafeRequest(this.#store, this.#cacheKey, resHeaders); return downstreamOnHeaders(); } + if (this.#history && this.#history.length > 1 && requestCarriesCredentials(this.#cacheKey.headers)) { + return downstreamOnHeaders(); + } + if (this.#history && this.#history.length > 0) { + for (const hopUrl of this.#history) { + if (!sameOrigin(hopUrl.origin, this.#cacheKey.origin)) { + return downstreamOnHeaders(); + } + } + } + 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 + ) : void 0; + if (redirectHopInfo?.length > 0 && redirectPolicy === void 0) { + return downstreamOnHeaders(); + } const cacheControlHeader = resHeaders["cache-control"]; const cacheControlDirectives = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {}; if (revalidationResponseDisallowsCachedReuse(this.#cacheType, resHeaders, cacheControlDirectives)) { @@ -57771,7 +58018,6 @@ var require_cache_handler = __commonJS({ } return downstreamOnHeaders(); } - const now = Date.now(); const resAge = Object.hasOwn(resHeaders, "age") ? getAge(resHeaders.age) : void 0; if (resAge !== void 0 && resAge >= MAX_RESPONSE_AGE) { deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); @@ -57784,43 +58030,102 @@ var require_cache_handler = __commonJS({ } const apparentAge = resDate ? Math.max(0, now - resDate.getTime()) : 0; const currentAge = Math.max(apparentAge, resAge ?? 0); - const staleAt = determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives) ?? this.#cacheByDefault; - if (staleAt === void 0 || currentAge >= staleAt) { + const hasValidator = typeof resHeaders.etag === "string" && isEtagUsable(resHeaders.etag) || typeof resHeaders["last-modified"] === "string"; + const staleAt = determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives, hasValidator) ?? this.#cacheByDefault; + const revalidationOnly = staleAt === 0 && hasValidator; + if (staleAt === void 0 || currentAge >= staleAt && !revalidationOnly) { if (cacheControlHeader || staleAt !== void 0) { deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); } return downstreamOnHeaders(); } const baseTime = now - currentAge; - const absoluteStaleAt = staleAt + baseTime; - if (now >= absoluteStaleAt) { + let absoluteStaleAt = staleAt + baseTime; + if (redirectPolicy !== void 0) { + absoluteStaleAt = Math.min(absoluteStaleAt, redirectPolicy.staleAt); + } + if (now >= absoluteStaleAt && !revalidationOnly) { deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); return downstreamOnHeaders(); } let varyDirectives; - if (this.#cacheKey.headers && resHeaders.vary) { - varyDirectives = parseVaryHeader(resHeaders.vary, this.#cacheKey.headers); - if (!varyDirectives) { - 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)) { + return downstreamOnHeaders(); + } + } + if (this.#cacheKey.headers) { + varyDirectives = parseVaryHeader(combinedVary, this.#cacheKey.headers); + if (!varyDirectives) { + return downstreamOnHeaders(); + } + } + } + let effectiveCacheControlDirectives = cacheControlDirectives; + if (redirectPolicy !== void 0) { + 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); const value = { statusCode, statusMessage, headers: strippedHeaders, vary: varyDirectives, - cacheControlDirectives, + cacheControlDirectives: effectiveCacheControlDirectives, cachedAt, staleAt: absoluteStaleAt, deleteAt }; if (statusCode === 304) { + this.#replaying304 = true; + let done = false; + const finish304 = () => { + if (done) { + return; + } + done = true; + this.#replaying304 = false; + if (this.#pending304End) { + const { controller: controller2, trailers } = this.#pending304End; + this.#pending304End = void 0; + this.#writeStream?.end(); + this.#handler.onResponseEnd?.(controller2, trailers); + } + }; + const failReplay = (err) => { + if (done) { + return; + } + done = true; + this.#replaying304 = false; + this.#suppress304End = true; + this.#pending304End = void 0; + this.#writeStream?.destroy(); + try { + this.#handler.onResponseError?.(controller, err); + } catch { + } + }; const handle304 = (cachedValue) => { if (!cachedValue) { - return downstreamOnHeaders(); + downstreamOnHeaders(); + finish304(); + return; } value.statusCode = cachedValue.statusCode; value.statusMessage = cachedValue.statusMessage; @@ -57830,39 +58135,57 @@ var require_cache_handler = __commonJS({ downstreamOnHeaders(); this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value); if (!this.#writeStream || !cachedValue?.body) { + finish304(); return; } if (typeof cachedValue.body.values === "function") { const bodyIterator = cachedValue.body.values(); const streamCachedBody = () => { - for (const chunk of bodyIterator) { - const full = this.#writeStream.write(chunk) === false; - this.#handler.onResponseData?.(controller, chunk); - if (full) { - break; + if (done) { + return; + } + try { + for (const chunk of bodyIterator) { + const full = this.#writeStream?.write(chunk) === false; + this.#handler.onResponseData?.(controller, chunk); + if (full) { + return; + } } + finish304(); + } catch (err) { + failReplay(err); } }; this.#writeStream.on("error", function() { handler2.#writeStream = void 0; handler2.#store.delete(handler2.#cacheKey); + streamCachedBody(); }).on("drain", () => { streamCachedBody(); }).on("close", function() { if (handler2.#writeStream === this) { handler2.#writeStream = void 0; + streamCachedBody(); } }); streamCachedBody(); } else if (typeof cachedValue.body.on === "function") { 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 = void 0; this.#store.delete(this.#cacheKey); + finish304(); }); this.#writeStream.on("error", function() { handler2.#writeStream = void 0; @@ -57872,11 +58195,15 @@ var require_cache_handler = __commonJS({ handler2.#writeStream = void 0; } }); + } else { + finish304(); } }; const result = this.#store.get(this.#cacheKey); if (result && typeof result.then === "function") { - result.then(handle304); + result.then(handle304, () => handle304(void 0)).catch((err) => { + failReplay(err); + }); } else { handle304(result); } @@ -57907,10 +58234,20 @@ var require_cache_handler = __commonJS({ this.#handler.onResponseData?.(controller, chunk); } 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 = void 0; this.#writeStream?.destroy(err); this.#writeStream = void 0; this.#handler.onResponseError?.(controller, err); @@ -57966,6 +58303,74 @@ var require_cache_handler = __commonJS({ } return true; } + 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 === void 0 || hopPolicy.staleAt <= now) { + return void 0; + } + staleAt = Math.min(staleAt, hopPolicy.staleAt); + requiresRevalidation ||= hopPolicy.requiresRevalidation; + } + return { staleAt, requiresRevalidation }; + } + function getRedirectHopPolicy(cacheType, method, hop, reqHeaders, cacheByDefault) { + if (!Number.isInteger(hop?.statusCode) || !Number.isFinite(hop?.receivedAt)) { + return void 0; + } + const hopHeaders = hop.headers ?? {}; + const cacheControlHeader = hopHeaders["cache-control"]; + const hopCacheControl = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {}; + if (hopHeaders.vary && hasVaryStar(hopHeaders.vary)) { + return void 0; + } + if (hopCacheControl["no-store"] === true) { + return void 0; + } + if (cacheType === "shared" && Object.hasOwn(hopCacheControl, "private")) { + return void 0; + } + if (Object.hasOwn(hopCacheControl, "no-cache") || hopCacheControl["must-revalidate"] === true || cacheType === "shared" && hopCacheControl["proxy-revalidate"] === true) { + return void 0; + } + const heuristicallyCacheable = hopHeaders["last-modified"] && arrayIncludes(HEURISTICALLY_CACHEABLE_STATUS_CODES, hop.statusCode); + if (!cacheControlHeader && !hopHeaders.expires && !heuristicallyCacheable && !cacheByDefault) { + return void 0; + } + if (!canCacheResponse(cacheType, method, hop.statusCode, hopHeaders, hopCacheControl, reqHeaders)) { + return void 0; + } + const age = Object.hasOwn(hopHeaders, "age") ? getAge(hopHeaders.age) : void 0; + if (age !== void 0 && age >= MAX_RESPONSE_AGE) { + return void 0; + } + const responseDate = Object.hasOwn(hopHeaders, "date") ? getDate(hopHeaders.date) : void 0; + if (responseDate === null) { + return void 0; + } + 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 === void 0) { + return void 0; + } + 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") + }; + } function getDate(dateHeader) { let dateValue = dateHeader; if (Array.isArray(dateValue)) { @@ -57996,7 +58401,7 @@ var require_cache_handler = __commonJS({ } return Number(age) * 1e3; } - function determineStaleAt(cacheType, now, age, resHeaders, responseDate, cacheControlDirectives) { + function determineStaleAt(cacheType, now, age, resHeaders, responseDate, cacheControlDirectives, hasValidator) { if (cacheType === "shared") { if (hasInvalidCacheControlDirective(cacheControlDirectives, "s-maxage")) { return 0; @@ -58049,6 +58454,9 @@ var require_cache_handler = __commonJS({ if (cacheControlDirectives.immutable) { return 31536e6; } + if (cacheControlDirectives["no-cache"] === true && hasValidator) { + return 0; + } return void 0; } function determineDeleteAt(baseTime, cachedAt, cacheControlDirectives, staleAt) { @@ -58066,6 +58474,9 @@ var require_cache_handler = __commonJS({ } if (staleWhileRevalidate === -Infinity && staleIfError === -Infinity && immutable === -Infinity) { const freshnessLifetime = staleAt - baseTime; + if (freshnessLifetime <= 0) { + return cachedAt + REVALIDATION_ONLY_RETENTION; + } const datePrecisionPadding = Math.min(Math.max(cachedAt - baseTime, 0), 1e3); return staleAt + freshnessLifetime + datePrecisionPadding; } @@ -58411,7 +58822,16 @@ var require_cache3 = __commonJS({ var CacheHandler = require_cache_handler(); var MemoryCacheStore = require_memory_cache_store(); var CacheRevalidationHandler = require_cache_revalidation_handler(); - var { assertCacheStore, assertCacheMethods, makeCacheKey, normalizeHeaders, parseCacheControlHeader, isInvalidOrWildcardVaryHeader } = require_cache2(); + var { + assertCacheStore, + assertCacheMethods, + makeCacheKey, + normalizeHeaders, + parseCacheControlHeader, + isInvalidOrWildcardVaryHeader, + parseVaryHeader, + isEtagUsable + } = require_cache2(); var { AbortError } = require_errors2(); var { parseHttpDate } = require_date(); function assertCacheOrigins(origins, name) { @@ -58490,6 +58910,17 @@ var require_cache3 = __commonJS({ function revalidationResponseUpdatesCacheControl(headers) { return headers["cache-control"] !== void 0; } + 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); @@ -58519,6 +58950,34 @@ var require_cache3 = __commonJS({ } 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; + } function isStale(result, cacheControlDirectives, cacheType) { const now = Date.now(); if (now > result.staleAt) { @@ -58600,18 +59059,23 @@ var require_cache3 = __commonJS({ }; stream3.on("error", function(err) { if (!this.readableEnded) { - if (typeof handler2.onResponseError === "function") { - handler2.onResponseError(controller, err); - } else { - throw err; - } + handler2.onResponseError?.(controller, err); } }).on("close", function() { if (!this.errored) { - handler2.onResponseEnd?.(controller, {}); + try { + handler2.onResponseEnd?.(controller, {}); + } catch (err) { + handler2.onResponseError?.(controller, err); + } } }); - handler2.onRequestStart?.(controller, context); + try { + handler2.onRequestStart?.(controller, context); + } catch (err) { + stream3.destroy(err); + return; + } if (stream3.destroyed) { return; } @@ -58619,12 +59083,22 @@ var require_cache3 = __commonJS({ if (isStale2) { headers.warning = '110 - "response is stale"'; } - handler2.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage); + controller.rawHeaders = util3.toRawHeaders(headers); + try { + handler2.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage); + } catch (err) { + stream3.destroy(err); + return; + } if (opts.method === "HEAD") { stream3.destroy(); } else { stream3.on("data", function(chunk) { - handler2.onResponseData?.(controller, chunk); + try { + handler2.onResponseData?.(controller, chunk); + } catch (err) { + stream3.destroy(err); + } }); } } @@ -58687,6 +59161,13 @@ var require_cache3 = __commonJS({ } } const headers = makeRevalidationHeaders(opts, result); + const refetch = () => { + if (util3.isStream(result.body)) { + result.body.on("error", nop).destroy(); + } + deleteCachedValue(globalOpts.store, cacheKey); + return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler2)); + }; return dispatch( { ...opts, @@ -58696,15 +59177,13 @@ var require_cache3 = __commonJS({ (success, context, statusCode, headers2) => { if (success) { if (statusCode === 304) { - if (revalidationResponseDisallowsCachedReuse(globalOpts.type, headers2)) { - if (util3.isStream(result.body)) { - result.body.on("error", nop).destroy(); - } - deleteCachedValue(globalOpts.store, cacheKey); - return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler2)); + if (!revalidationTargetMatchesCacheKey(cacheKey, context) || !revalidationEtagMatchesCachedValue(result, headers2) || revalidationResponseDisallowsCachedReuse(globalOpts.type, headers2)) { + return refetch(); } if (revalidationResponseUpdatesCacheControl(headers2)) { deleteCachedValue(globalOpts.store, cacheKey); + } else if (revalidationResponseAddsVary(result, headers2.vary ? parseVaryHeader(headers2.vary, opts.headers) : void 0)) { + return refetch(); } } sendCachedValue(handler2, opts, result, age, context, stale); @@ -58801,7 +59280,31 @@ var require_cache3 = __commonJS({ opts2, reqCacheControl, result2 - )); + )).catch((err) => { + if (typeof handler2.onResponseError === "function") { + handler2.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, @@ -59015,9 +59518,14 @@ var require_decompress = __commonJS({ } this.#decompressedSize = decompressedSize; } - const result = super.onResponseData(this.#controller, chunk); - if (result === false && !this.#controller.paused) { - this.#controller.pause(); + try { + const result = super.onResponseData(this.#controller, chunk); + if (result === false && !this.#controller.paused) { + this.#controller.pause(); + } + } catch (err) { + this.#fail(err); + return; } } } while (this.#drainRequested && !this.#terminated && !this.#controller.paused); @@ -59031,9 +59539,14 @@ var require_decompress = __commonJS({ if (this.#terminated || !this.#completionPending || this.#controller.paused || this.#draining) { return; } - this.#terminated = true; this.#cleanupDecompressors(); - super.onResponseEnd(this.#controller, this.#trailers); + try { + super.onResponseEnd(this.#controller, this.#trailers); + } catch (err) { + this.#fail(err); + return; + } + this.#terminated = true; } #onDecompressionEnd() { if (this.#terminated) { @@ -59178,7 +59691,8 @@ var require_decompress = __commonJS({ * @returns {void} */ onResponseStart(controller, statusCode, headers, statusMessage) { - const contentEncoding = headers["content-encoding"]; + const rawContentEncoding = headers["content-encoding"]; + const contentEncoding = Array.isArray(rawContentEncoding) ? rawContentEncoding.join(",") : rawContentEncoding; if (this.#shouldSkipDecompression(contentEncoding, statusCode)) { return super.onResponseStart(this.#controller, statusCode, headers, statusMessage); } @@ -59296,6 +59810,18 @@ var require_deduplication_handler = __commonJS({ * @type {DispatchHandler} */ #primaryHandler; + /** + * Whether the primary request has started (onRequestStart received). Until + * then the request context is unknown and cannot be given to waiting handlers. + * @type {boolean} + */ + #requestStarted = false; + /** + * The primary request context, replayed to waiting handlers so they observe + * the same redirect history as the primary. + * @type {any} + */ + #context = null; /** * @type {WaitingHandler[]} */ @@ -59364,18 +59890,22 @@ var require_deduplication_handler = __commonJS({ const waitingHandler = this.#createWaitingHandler(handler2); const waitingController = waitingHandler.controller; try { - handler2.onRequestStart?.(waitingController, null); - if (waitingController.aborted) { - waitingHandler.done = true; - return true; - } - if (this.#responseStarted) { - handler2.onResponseStart?.( - waitingController, - this.#statusCode, - this.#headers, - this.#statusMessage - ); + if (this.#requestStarted) { + handler2.onRequestStart?.(waitingController, this.#context); + if (waitingController.aborted) { + waitingHandler.done = true; + return true; + } + if (this.#responseStarted) { + handler2.onResponseStart?.( + waitingController, + this.#statusCode, + this.#headers, + this.#statusMessage + ); + } + } else { + waitingHandler.pendingStart = true; } } catch { waitingHandler.done = true; @@ -59392,6 +59922,21 @@ var require_deduplication_handler = __commonJS({ */ onRequestStart(controller, context) { this.#controller = controller; + if (!this.#requestStarted) { + this.#requestStarted = true; + this.#context = context; + for (const waitingHandler of this.#waitingHandlers) { + if (waitingHandler.pendingStart && !waitingHandler.done && !waitingHandler.controller.aborted) { + waitingHandler.pendingStart = false; + try { + waitingHandler.handler.onRequestStart?.(waitingHandler.controller, context); + } catch { + waitingHandler.done = true; + } + } + } + this.#pruneDoneWaitingHandlers(); + } this.#primaryHandler.onRequestStart?.(controller, context); } /** @@ -59529,7 +60074,8 @@ var require_deduplication_handler = __commonJS({ bufferedChunks: [], bufferedBytes: 0, pendingTrailers: null, - done: false + done: false, + pendingStart: false }; const state = { aborted: false, @@ -59736,7 +60282,7 @@ var require_sqlite_cache_store = __commonJS({ var { Writable: Writable2 } = require("node:stream"); var { assertCacheKey, assertCacheValue } = require_cache2(); var DatabaseSync; - var VERSION10 = 3; + var VERSION10 = 4; var MAX_ENTRY_SIZE = 2 * 1e3 * 1e3 * 1e3; module2.exports = class SqliteCacheStore { #maxEntrySize = MAX_ENTRY_SIZE; @@ -61738,6 +62284,7 @@ var require_subresource_integrity = __commonJS({ "use strict"; var assert = require("node:assert"); var { runtimeFeatures } = require_runtime_features(); + var { asciiLowercase } = require_infra(); var validSRIHashAlgorithmTokenSet = /* @__PURE__ */ new Map([["sha256", 0], ["sha384", 1], ["sha512", 2]]); var crypto3; if (runtimeFeatures.has("crypto")) { @@ -61760,10 +62307,7 @@ var require_subresource_integrity = __commonJS({ validSRIHashAlgorithmTokenSet ) ); - var isValidSRIHashAlgorithm = ( - /** @type {IsValidSRIHashAlgorithm} */ - Map.prototype.has.bind(validSRIHashAlgorithmTokenSet) - ); + var isValidSRIHashAlgorithm = (algorithm) => validSRIHashAlgorithmTokenSet.has(asciiLowercase(algorithm)); var bytesMatch = runtimeFeatures.has("crypto") === false || validSRIHashAlgorithmTokenSet.size === 0 ? () => true : (bytes, metadataList) => { const parsedMetadata = parseMetadata(metadataList); if (parsedMetadata.length === 0) { @@ -61811,7 +62355,7 @@ var require_subresource_integrity = __commonJS({ } 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 = ""; @@ -61824,7 +62368,8 @@ var require_subresource_integrity = __commonJS({ base64Value = algorithmAndValue[1]; } const metadata2 = { - alg: algorithm, + // Possible spec bug? + alg: asciiLowercase(algorithm), val: base64Value }; result.push(metadata2); @@ -62873,7 +63418,6 @@ var require_fetch2 = __commonJS({ } } const location = headersList.get("location", true); - this.body = new Readable({ read: resume }); const willFollow = location && request2.redirect === "follow" && redirectStatusSet.has(status); const decoders = []; if (request2.method !== "HEAD" && request2.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) { @@ -62881,7 +63425,7 @@ var require_fetch2 = __commonJS({ const codings = contentEncoding ? contentEncoding.toLowerCase().split(",") : []; const maxContentEncodings = 5; if (codings.length > maxContentEncodings) { - reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); + this.abort(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); return true; } for (let i = codings.length - 1; i >= 0; --i) { @@ -62916,6 +63460,7 @@ var require_fetch2 = __commonJS({ } } } + this.body = new Readable({ read: resume }); const onError = this.onError.bind(this); resolve2({ status, @@ -63895,8 +64440,12 @@ var require_util13 = __commonJS({ validateCookiePath(cookie.path); out.push(`Path=${cookie.path}`); } - if (cookie.expires && cookie.expires.toString() !== "Invalid Date") { - out.push(`Expires=${toIMFDate(cookie.expires)}`); + if (cookie.expires != null) { + const expiresMs = cookie.expires instanceof Date ? cookie.expires.getTime() : cookie.expires; + const maxTimeValue = 864e13; + if (typeof expiresMs === "number" && Number.isFinite(expiresMs) && Math.abs(expiresMs) <= maxTimeValue) { + out.push(`Expires=${toIMFDate(cookie.expires)}`); + } } if (cookie.sameSite) { out.push(`SameSite=${cookie.sameSite}`); @@ -63971,88 +64520,89 @@ var require_parse3 = __commonJS({ }; } function parseUnparsedAttributes(unparsedAttributes, cookieAttributeList = {}) { - if (unparsedAttributes.length === 0) { - return cookieAttributeList; - } - assert(unparsedAttributes[0] === ";"); - unparsedAttributes = unparsedAttributes.slice(1); - let cookieAv = ""; - if (unparsedAttributes.includes(";")) { - cookieAv = collectASequenceOfCodePointsFast( - ";", - unparsedAttributes, - { position: 0 } - ); - unparsedAttributes = unparsedAttributes.slice(cookieAv.length); - } else { - cookieAv = unparsedAttributes; - unparsedAttributes = ""; - } - let attributeName = ""; - let attributeValue = ""; - if (cookieAv.includes("=")) { - const position = { position: 0 }; - attributeName = collectASequenceOfCodePointsFast( - "=", - cookieAv, - position - ); - attributeValue = cookieAv.slice(position.position + 1); - } else { - attributeName = cookieAv; - } - attributeName = attributeName.trim(); - attributeValue = attributeValue.trim(); - if (attributeValue.length > maxAttributeValueSize) { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); - } - const attributeNameLowercase = attributeName.toLowerCase(); - if (attributeNameLowercase === "expires") { - const expiryTime = new Date(attributeValue); - cookieAttributeList.expires = expiryTime; - } else if (attributeNameLowercase === "max-age") { - const charCode = attributeValue.charCodeAt(0); - if ((charCode < 48 || charCode > 57) && attributeValue[0] !== "-") { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); - } - if (!/^\d+$/.test(attributeValue)) { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); + while (true) { + if (unparsedAttributes.length === 0) { + return cookieAttributeList; + } + assert(unparsedAttributes[0] === ";"); + unparsedAttributes = unparsedAttributes.slice(1); + let cookieAv = ""; + if (unparsedAttributes.includes(";")) { + cookieAv = collectASequenceOfCodePointsFast( + ";", + unparsedAttributes, + { position: 0 } + ); + unparsedAttributes = unparsedAttributes.slice(cookieAv.length); + } else { + cookieAv = unparsedAttributes; + unparsedAttributes = ""; + } + let attributeName = ""; + let attributeValue = ""; + if (cookieAv.includes("=")) { + const position = { position: 0 }; + attributeName = collectASequenceOfCodePointsFast( + "=", + cookieAv, + position + ); + attributeValue = cookieAv.slice(position.position + 1); + } else { + attributeName = cookieAv; } - const deltaSeconds = Number(attributeValue); - cookieAttributeList.maxAge = deltaSeconds; - } else if (attributeNameLowercase === "domain") { - let cookieDomain = attributeValue; - if (cookieDomain[0] === ".") { - cookieDomain = cookieDomain.slice(1); + attributeName = attributeName.trim(); + attributeValue = attributeValue.trim(); + if (attributeValue.length > maxAttributeValueSize) { + continue; } - cookieDomain = cookieDomain.toLowerCase(); - cookieAttributeList.domain = cookieDomain; - } else if (attributeNameLowercase === "path") { - let cookiePath = ""; - if (attributeValue.length === 0 || attributeValue[0] !== "/") { - cookiePath = "/"; + const attributeNameLowercase = attributeName.toLowerCase(); + if (attributeNameLowercase === "expires") { + const expiryTime = new Date(attributeValue); + cookieAttributeList.expires = expiryTime; + } else if (attributeNameLowercase === "max-age") { + const charCode = attributeValue.charCodeAt(0); + if ((charCode < 48 || charCode > 57) && attributeValue[0] !== "-") { + continue; + } + if (!/^\d+$/.test(attributeValue)) { + continue; + } + const deltaSeconds = Number(attributeValue); + cookieAttributeList.maxAge = deltaSeconds; + } else if (attributeNameLowercase === "domain") { + let cookieDomain = attributeValue; + if (cookieDomain[0] === ".") { + cookieDomain = cookieDomain.slice(1); + } + cookieDomain = cookieDomain.toLowerCase(); + cookieAttributeList.domain = cookieDomain; + } else if (attributeNameLowercase === "path") { + let cookiePath = ""; + if (attributeValue.length === 0 || attributeValue[0] !== "/") { + cookiePath = "/"; + } else { + cookiePath = attributeValue; + } + cookieAttributeList.path = cookiePath; + } else if (attributeNameLowercase === "secure") { + cookieAttributeList.secure = true; + } else if (attributeNameLowercase === "httponly") { + cookieAttributeList.httpOnly = true; + } else if (attributeNameLowercase === "samesite") { + const attributeValueLowercase = attributeValue.toLowerCase(); + if (attributeValueLowercase === "none") { + cookieAttributeList.sameSite = "None"; + } else if (attributeValueLowercase === "strict") { + cookieAttributeList.sameSite = "Strict"; + } else if (attributeValueLowercase === "lax") { + cookieAttributeList.sameSite = "Lax"; + } } else { - cookiePath = attributeValue; + cookieAttributeList.unparsed ??= []; + cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`); } - cookieAttributeList.path = cookiePath; - } else if (attributeNameLowercase === "secure") { - cookieAttributeList.secure = true; - } else if (attributeNameLowercase === "httponly") { - cookieAttributeList.httpOnly = true; - } else if (attributeNameLowercase === "samesite") { - const attributeValueLowercase = attributeValue.toLowerCase(); - if (attributeValueLowercase === "none") { - cookieAttributeList.sameSite = "None"; - } else if (attributeValueLowercase === "strict") { - cookieAttributeList.sameSite = "Strict"; - } else if (attributeValueLowercase === "lax") { - cookieAttributeList.sameSite = "Lax"; - } - } else { - cookieAttributeList.unparsed ??= []; - cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`); } - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); } module2.exports = { parseSetCookie, @@ -64074,7 +64624,7 @@ var require_cookies2 = __commonJS({ webidl.argumentLengthCheck(arguments, 1, "getCookies"); brandChecks(headers); const cookie = headers.get("cookie"); - const out = {}; + const out = { __proto__: null }; if (!cookie) { return out; } @@ -65223,6 +65773,15 @@ var require_receiver2 = __commonJS({ if (isControlFrame(this.#info.opcode)) { this.#loop = this.parseControlFrame(body); this.#state = parserStates.INFO; + if (this.#loop && this.#handler.socket.writableNeedDrain) { + this.#loop = false; + this.#handler.socket.once("drain", () => { + if (this.destroyed) return; + this.#loop = true; + this.run(callback); + }); + return; + } } else { if (!this.#info.compressed) { if (!this.writeFragments(body)) { @@ -66398,6 +66957,7 @@ var require_util15 = __commonJS({ var require_eventsource_stream2 = __commonJS({ "node_modules/@octokit/action/node_modules/undici/lib/web/eventsource/eventsource-stream.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var { Transform } = require("node:stream"); var { isASCIINumber, isValidLastEventId } = require_util15(); var BOM = [239, 187, 191]; @@ -66405,24 +66965,28 @@ var require_eventsource_stream2 = __commonJS({ var CR = 13; var COLON = 58; var SPACE = 32; + var defaultMaxEventSize = buffer.kStringMaxLength; var DATA = Buffer.from("data"); var EVENT = Buffer.from("event"); var ID = Buffer.from("id"); var RETRY = Buffer.from("retry"); - function isASCIINumberBytes(buffer, start) { - if (start >= buffer.length) { + var minParserItems = 1024; + var maxParserItems = 131072; + var bytesPerParserItem = 128; + function isASCIINumberBytes(buffer2, start) { + if (start >= buffer2.length) { return false; } - for (let i = start; i < buffer.length; i++) { - if (buffer[i] < 48 || buffer[i] > 57) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] < 48 || buffer2[i] > 57) { return false; } } return true; } - function isValidLastEventIdBytes(buffer, start) { - for (let i = start; i < buffer.length; i++) { - if (buffer[i] === 0) { + function isValidLastEventIdBytes(buffer2, start) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] === 0) { return false; } } @@ -66439,6 +67003,11 @@ var require_eventsource_stream2 = __commonJS({ } return true; } + function createMaxEventSizeExceededError() { + const error2 = new Error("EventSource message size exceeded"); + error2.aborted = false; + return error2; + } var EventSourceStream = class extends Transform { /** * @type {eventSourceSettings} @@ -66465,6 +67034,13 @@ var require_eventsource_stream2 = __commonJS({ pos = 0; lineChunkIndex = 0; linePos = 0; + lineLength = 0; + eventSize = 0; + eventFieldSizes = { data: 0, event: 0, id: 0, retry: 0 }; + dataLineCount = 0; + maxEventSize; + maxDataLines; + maxBufferedChunks; event = { data: void 0, event: void 0, @@ -66474,6 +67050,7 @@ var require_eventsource_stream2 = __commonJS({ /** * @param {object} options * @param {boolean} [options.readableObjectMode] + * @param {number} [options.maxEventSize] * @param {eventSourceSettings} [options.eventSourceSettings] * @param {(chunk: any, encoding?: BufferEncoding | undefined) => boolean} [options.push] */ @@ -66481,6 +67058,10 @@ var require_eventsource_stream2 = __commonJS({ options.readableObjectMode = true; super(options); this.state = options.eventSourceSettings || {}; + this.maxEventSize = options.maxEventSize ?? defaultMaxEventSize; + const parserItemLimit = this.maxEventSize > 0 ? Math.min(maxParserItems, Math.max(minParserItems, Math.floor(this.maxEventSize / bytesPerParserItem))) : 0; + this.maxDataLines = parserItemLimit; + this.maxBufferedChunks = parserItemLimit; if (options.push) { this.push = options.push; } @@ -66496,6 +67077,10 @@ var require_eventsource_stream2 = __commonJS({ callback(); return; } + if (this.maxEventSize > 0 && this.chunks.length >= this.maxBufferedChunks && chunk[0] !== LF && chunk[0] !== CR) { + callback(createMaxEventSizeExceededError()); + return; + } this.chunks.push(chunk); if (this.checkBOM) { if (this.handleBOM()) { @@ -66532,15 +67117,29 @@ var require_eventsource_stream2 = __commonJS({ if (byte === CR) { this.crlfCheck = true; } - this.parseLine(this.readLine(), this.event); + try { + this.parseLine(this.readLine(), this.event); + } catch (error2) { + callback(error2); + return; + } this.consumeCurrentByte(); this.eventEndCheck = true; continue; } + if (this.maxEventSize > 0 && ++this.lineLength > this.maxEventSize + 7) { + callback(createMaxEventSizeExceededError()); + return; + } this.advanceCursor(); } callback(); } + _destroy(error2, callback) { + this.chunks.length = 0; + this.clearEvent(); + super._destroy(error2, callback); + } /** * @param {Buffer} line * @param {EventSourceStreamEvent} event @@ -66563,6 +67162,12 @@ var require_eventsource_stream2 = __commonJS({ } } if (isFieldName(line, fieldLength, DATA)) { + if (this.maxEventSize > 0 && this.dataLineCount >= this.maxDataLines) { + throw createMaxEventSizeExceededError(); + } + const valueBytes = line.length - valueStart; + const dataSize = this.eventFieldSizes.data + (event.data === void 0 ? 0 : 1) + valueBytes; + this.setEventFieldSize("data", dataSize); const value = line.toString("utf8", valueStart); if (event.data === void 0) { event.data = value; @@ -66570,27 +67175,38 @@ var require_eventsource_stream2 = __commonJS({ event.data += ` ${value}`; } + this.dataLineCount++; return; } if (isFieldName(line, fieldLength, RETRY)) { if (isASCIINumberBytes(line, valueStart)) { + this.setEventFieldSize("retry", line.length - valueStart); event.retry = line.toString("utf8", valueStart); } return; } if (isFieldName(line, fieldLength, ID)) { if (isValidLastEventIdBytes(line, valueStart)) { + this.setEventFieldSize("id", line.length - valueStart); event.id = line.toString("utf8", valueStart); } return; } if (isFieldName(line, fieldLength, EVENT)) { - const value = line.toString("utf8", valueStart); - if (value.length > 0) { - event.event = value; + if (valueStart < line.length) { + this.setEventFieldSize("event", line.length - valueStart); + event.event = line.toString("utf8", valueStart); } } } + setEventFieldSize(field, size) { + const eventSize = this.eventSize - this.eventFieldSizes[field] + size; + if (this.maxEventSize > 0 && eventSize > this.maxEventSize) { + throw createMaxEventSizeExceededError(); + } + this.eventSize = eventSize; + this.eventFieldSizes[field] = size; + } /** * @param {EventSourceStreamEvent} event */ @@ -66617,6 +67233,12 @@ ${value}`; this.event.event = void 0; this.event.id = void 0; this.event.retry = void 0; + this.eventSize = 0; + this.dataLineCount = 0; + this.eventFieldSizes.data = 0; + this.eventFieldSizes.event = 0; + this.eventFieldSizes.id = 0; + this.eventFieldSizes.retry = 0; } hasPendingEvent() { return this.event.data !== void 0 || this.event.event !== void 0 || this.event.id !== void 0 || this.event.retry !== void 0; @@ -66641,13 +67263,15 @@ ${value}`; syncLineStartToCursor() { this.lineChunkIndex = this.chunkIndex; this.linePos = this.pos; + this.lineLength = 0; this.dropConsumedChunks(); } dropConsumedChunks() { - while (this.lineChunkIndex > 0) { - this.chunks.shift(); - this.lineChunkIndex--; - this.chunkIndex--; + if (this.lineChunkIndex > 0) { + const consumed = this.lineChunkIndex; + this.chunks.splice(0, consumed); + this.lineChunkIndex = 0; + this.chunkIndex -= consumed; } if (this.chunkIndex === this.chunks.length) { this.chunks.length = 0; @@ -66749,6 +67373,7 @@ var require_eventsource2 = __commonJS({ var { isNetworkError } = require_response2(); var { kEnumerableProperty } = require_util10(); var { environmentSettingsObject } = require_util11(); + var { getGlobalDispatcher } = require_global4(); var experimentalWarned = false; var defaultReconnectionTime = 3e3; var CONNECTING = 0; @@ -66890,6 +67515,7 @@ var require_eventsource2 = __commonJS({ this.#state.origin = response.urlList[response.urlList.length - 1].origin; const eventSourceStream = new EventSourceStream({ eventSourceSettings: this.#state, + maxEventSize: this.#dispatcher.eventSourceOptions?.maxEventSize, push: (event) => { this.dispatchEvent(createFastMessageEvent( event.type, @@ -67026,7 +67652,8 @@ var require_eventsource2 = __commonJS({ { key: "dispatcher", // undici only - converter: webidl.converters.any + converter: webidl.converters.any, + defaultValue: () => getGlobalDispatcher() }, { key: "node", diff --git a/dist/update-repo-task-status.js b/dist/update-repo-task-status.js index ed3fb2b7..135de455 100644 --- a/dist/update-repo-task-status.js +++ b/dist/update-repo-task-status.js @@ -2098,6 +2098,7 @@ var require_dispatcher = __commonJS({ var require_dispatcher_base = __commonJS({ "node_modules/undici/lib/dispatcher/dispatcher-base.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var Dispatcher = require_dispatcher(); var { ClientDestroyedError, @@ -2109,6 +2110,7 @@ var require_dispatcher_base = __commonJS({ var kOnClosed = /* @__PURE__ */ Symbol("onClosed"); var kInterceptedDispatch = /* @__PURE__ */ Symbol("Intercepted Dispatch"); var kWebSocketOptions = /* @__PURE__ */ Symbol("webSocketOptions"); + var kEventSourceOptions = /* @__PURE__ */ Symbol("eventSourceOptions"); var DispatcherBase = class extends Dispatcher { constructor(opts) { super(); @@ -2117,6 +2119,7 @@ var require_dispatcher_base = __commonJS({ this[kClosed] = false; this[kOnClosed] = []; this[kWebSocketOptions] = opts?.webSocket ?? {}; + this[kEventSourceOptions] = opts?.eventSource ?? {}; } get webSocketOptions() { return { @@ -2124,6 +2127,11 @@ var require_dispatcher_base = __commonJS({ maxPayloadSize: this[kWebSocketOptions].maxPayloadSize ?? 128 * 1024 * 1024 }; } + get eventSourceOptions() { + return { + maxEventSize: this[kEventSourceOptions].maxEventSize ?? buffer.kStringMaxLength + }; + } get destroyed() { return this[kDestroyed]; } @@ -6271,7 +6279,6 @@ var require_client_h1 = __commonJS({ socket[kSocketUsed] = false; socket[kParser] = new Parser(client, socket, llhttpInstance); addListener(socket, "error", function(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); const parser = this[kParser]; if (err.code === "ECONNRESET" && parser.statusCode && !parser.shouldKeepAlive) { const parserErr = parser.finish(); @@ -6955,7 +6962,6 @@ var require_client_h2 = __commonJS({ client[kHTTP2Session] = session; socket[kHTTP2Session] = session; util.addListener(socket, "error", function(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kError] = err; this[kClient][kOnError](err); }); @@ -7014,7 +7020,6 @@ var require_client_h2 = __commonJS({ } } function onHttp2SessionError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kSocket][kError] = err; this[kClient][kOnError](err); } @@ -7708,9 +7713,10 @@ var require_client = __commonJS({ // h2 maxConcurrentStreams, allowH2, - webSocket + webSocket, + eventSource } = {}) { - super({ webSocket }); + super({ webSocket, eventSource }); if (keepAlive !== void 0) { throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead"); } @@ -8607,7 +8613,7 @@ var require_agent = __commonJS({ return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts); } var Agent = class extends DispatcherBase { - constructor({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { + constructor({ factory = defaultFactory, maxRedirections = 0, connect, tls, ...options } = {}) { if (typeof factory !== "function") { throw new InvalidArgumentError("factory must be a function."); } @@ -8621,8 +8627,11 @@ var require_agent = __commonJS({ if (connect && typeof connect !== "function") { connect = { ...connect }; } + if (tls && typeof tls !== "function") { + tls = { ...tls }; + } this[kInterceptors] = options.interceptors?.Agent && Array.isArray(options.interceptors.Agent) ? options.interceptors.Agent : [createRedirectInterceptor({ maxRedirections })]; - this[kOptions] = { ...util.deepClone(options), connect }; + this[kOptions] = { ...util.deepClone(options), connect, tls }; this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0; this[kMaxRedirections] = maxRedirections; this[kFactory] = factory; @@ -14350,8 +14359,9 @@ var require_fetch = __commonJS({ } ); response.body = { stream, source: null, length: null }; - fetchParams.controller.onAborted = onAborted; - fetchParams.controller.on("terminated", onAborted); + if (!fetchParams.controller.resume) { + fetchParams.controller.on("terminated", onAborted); + } fetchParams.controller.resume = async () => { while (true) { let bytes; @@ -14451,7 +14461,6 @@ var require_fetch = __commonJS({ headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString("latin1"), true); } location = headersList.get("location", true); - this.body = new Readable({ read: resume }); const decoders = []; const willFollow = location && request2.redirect === "follow" && redirectStatusSet.has(status); if (request2.method !== "HEAD" && request2.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) { @@ -14459,7 +14468,7 @@ var require_fetch = __commonJS({ const codings = contentEncoding ? contentEncoding.toLowerCase().split(",") : []; const maxContentEncodings = 5; if (codings.length > maxContentEncodings) { - reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); + this.abort(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); return true; } for (let i = codings.length - 1; i >= 0; --i) { @@ -14489,6 +14498,7 @@ var require_fetch = __commonJS({ } } } + this.body = new Readable({ read: resume }); const onError = this.onError.bind(this); resolve({ status, @@ -14514,9 +14524,6 @@ var require_fetch = __commonJS({ if (this.abort) { fetchParams.controller.off("terminated", this.abort); } - if (fetchParams.controller.onAborted) { - fetchParams.controller.off("terminated", fetchParams.controller.onAborted); - } fetchParams.controller.ended = true; this.body.push(null); }, @@ -17590,6 +17597,16 @@ var require_receiver = __commonJS({ if (isControlFrame(this.#info.opcode)) { this.#loop = this.parseControlFrame(body); this.#state = parserStates.INFO; + const socket = this.ws[kResponse].socket; + if (this.#loop && socket.writableNeedDrain) { + this.#loop = false; + socket.once("drain", () => { + if (this.destroyed) return; + this.#loop = true; + this.run(callback); + }); + return; + } } else { if (!this.#info.compressed) { if (!this.writeFragments(body)) { @@ -18283,6 +18300,7 @@ var require_util8 = __commonJS({ var require_eventsource_stream = __commonJS({ "node_modules/undici/lib/web/eventsource/eventsource-stream.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var { Transform } = require("node:stream"); var { isASCIINumber, isValidLastEventId } = require_util8(); var BOM = [239, 187, 191]; @@ -18290,24 +18308,28 @@ var require_eventsource_stream = __commonJS({ var CR = 13; var COLON = 58; var SPACE = 32; + var defaultMaxEventSize = buffer.kStringMaxLength; var DATA = Buffer.from("data"); var EVENT = Buffer.from("event"); var ID = Buffer.from("id"); var RETRY = Buffer.from("retry"); - function isASCIINumberBytes(buffer, start) { - if (start >= buffer.length) { + var minParserItems = 1024; + var maxParserItems = 131072; + var bytesPerParserItem = 128; + function isASCIINumberBytes(buffer2, start) { + if (start >= buffer2.length) { return false; } - for (let i = start; i < buffer.length; i++) { - if (buffer[i] < 48 || buffer[i] > 57) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] < 48 || buffer2[i] > 57) { return false; } } return true; } - function isValidLastEventIdBytes(buffer, start) { - for (let i = start; i < buffer.length; i++) { - if (buffer[i] === 0) { + function isValidLastEventIdBytes(buffer2, start) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] === 0) { return false; } } @@ -18324,6 +18346,11 @@ var require_eventsource_stream = __commonJS({ } return true; } + function createMaxEventSizeExceededError() { + const error = new Error("EventSource message size exceeded"); + error.aborted = false; + return error; + } var EventSourceStream = class extends Transform { /** * @type {eventSourceSettings} @@ -18350,6 +18377,13 @@ var require_eventsource_stream = __commonJS({ pos = 0; lineChunkIndex = 0; linePos = 0; + lineLength = 0; + eventSize = 0; + eventFieldSizes = { data: 0, event: 0, id: 0, retry: 0 }; + dataLineCount = 0; + maxEventSize; + maxDataLines; + maxBufferedChunks; event = { data: void 0, event: void 0, @@ -18358,6 +18392,7 @@ var require_eventsource_stream = __commonJS({ }; /** * @param {object} options + * @param {number} [options.maxEventSize] * @param {eventSourceSettings} options.eventSourceSettings * @param {Function} [options.push] */ @@ -18365,6 +18400,10 @@ var require_eventsource_stream = __commonJS({ options.readableObjectMode = true; super(options); this.state = options.eventSourceSettings || {}; + this.maxEventSize = options.maxEventSize ?? defaultMaxEventSize; + const parserItemLimit = this.maxEventSize > 0 ? Math.min(maxParserItems, Math.max(minParserItems, Math.floor(this.maxEventSize / bytesPerParserItem))) : 0; + this.maxDataLines = parserItemLimit; + this.maxBufferedChunks = parserItemLimit; if (options.push) { this.push = options.push; } @@ -18380,6 +18419,10 @@ var require_eventsource_stream = __commonJS({ callback(); return; } + if (this.maxEventSize > 0 && this.chunks.length >= this.maxBufferedChunks && chunk[0] !== LF && chunk[0] !== CR) { + callback(createMaxEventSizeExceededError()); + return; + } this.chunks.push(chunk); if (this.checkBOM) { if (this.handleBOM()) { @@ -18416,18 +18459,32 @@ var require_eventsource_stream = __commonJS({ if (byte === CR) { this.crlfCheck = true; } - this.parseLine(this.readLine(), this.event); + try { + this.parseLine(this.readLine(), this.event); + } catch (error) { + callback(error); + return; + } this.consumeCurrentByte(); this.eventEndCheck = true; continue; } + if (this.maxEventSize > 0 && ++this.lineLength > this.maxEventSize + 7) { + callback(createMaxEventSizeExceededError()); + return; + } this.advanceCursor(); } callback(); } + _destroy(error, callback) { + this.chunks.length = 0; + this.clearEvent(); + super._destroy(error, callback); + } /** * @param {Buffer} line - * @param {EventStreamEvent} event + * @param {EventSourceStreamEvent} event */ parseLine(line, event) { if (line.length === 0) { @@ -18447,6 +18504,12 @@ var require_eventsource_stream = __commonJS({ } } if (isFieldName(line, fieldLength, DATA)) { + if (this.maxEventSize > 0 && this.dataLineCount >= this.maxDataLines) { + throw createMaxEventSizeExceededError(); + } + const valueBytes = line.length - valueStart; + const dataSize = this.eventFieldSizes.data + (event.data === void 0 ? 0 : 1) + valueBytes; + this.setEventFieldSize("data", dataSize); const value = line.toString("utf8", valueStart); if (event.data === void 0) { event.data = value; @@ -18454,27 +18517,38 @@ var require_eventsource_stream = __commonJS({ event.data += ` ${value}`; } + this.dataLineCount++; return; } if (isFieldName(line, fieldLength, RETRY)) { if (isASCIINumberBytes(line, valueStart)) { + this.setEventFieldSize("retry", line.length - valueStart); event.retry = line.toString("utf8", valueStart); } return; } if (isFieldName(line, fieldLength, ID)) { if (isValidLastEventIdBytes(line, valueStart)) { + this.setEventFieldSize("id", line.length - valueStart); event.id = line.toString("utf8", valueStart); } return; } if (isFieldName(line, fieldLength, EVENT)) { - const value = line.toString("utf8", valueStart); - if (value.length > 0) { - event.event = value; + if (valueStart < line.length) { + this.setEventFieldSize("event", line.length - valueStart); + event.event = line.toString("utf8", valueStart); } } } + setEventFieldSize(field, size) { + const eventSize = this.eventSize - this.eventFieldSizes[field] + size; + if (this.maxEventSize > 0 && eventSize > this.maxEventSize) { + throw createMaxEventSizeExceededError(); + } + this.eventSize = eventSize; + this.eventFieldSizes[field] = size; + } /** * @param {EventSourceStreamEvent} event */ @@ -18501,6 +18575,12 @@ ${value}`; this.event.event = void 0; this.event.id = void 0; this.event.retry = void 0; + this.eventSize = 0; + this.dataLineCount = 0; + this.eventFieldSizes.data = 0; + this.eventFieldSizes.event = 0; + this.eventFieldSizes.id = 0; + this.eventFieldSizes.retry = 0; } hasPendingEvent() { return this.event.data !== void 0 || this.event.event !== void 0 || this.event.id !== void 0 || this.event.retry !== void 0; @@ -18525,13 +18605,15 @@ ${value}`; syncLineStartToCursor() { this.lineChunkIndex = this.chunkIndex; this.linePos = this.pos; + this.lineLength = 0; this.dropConsumedChunks(); } dropConsumedChunks() { - while (this.lineChunkIndex > 0) { - this.chunks.shift(); - this.lineChunkIndex--; - this.chunkIndex--; + if (this.lineChunkIndex > 0) { + const consumed = this.lineChunkIndex; + this.chunks.splice(0, consumed); + this.lineChunkIndex = 0; + this.chunkIndex -= consumed; } if (this.chunkIndex === this.chunks.length) { this.chunks.length = 0; @@ -18634,6 +18716,7 @@ var require_eventsource = __commonJS({ var { delay } = require_util8(); var { kEnumerableProperty } = require_util(); var { environmentSettingsObject } = require_util2(); + var { getGlobalDispatcher } = require_global2(); var experimentalWarned = false; var defaultReconnectionTime = 3e3; var CONNECTING = 0; @@ -18774,6 +18857,7 @@ var require_eventsource = __commonJS({ this.#state.origin = response.urlList[response.urlList.length - 1].origin; const eventSourceStream = new EventSourceStream({ eventSourceSettings: this.#state, + maxEventSize: this.#dispatcher.eventSourceOptions?.maxEventSize, push: (event) => { this.dispatchEvent(createFastMessageEvent( event.type, @@ -18906,7 +18990,8 @@ var require_eventsource = __commonJS({ { key: "dispatcher", // undici only - converter: webidl.converters.any + converter: webidl.converters.any, + defaultValue: () => getGlobalDispatcher() } ]); module2.exports = { @@ -26011,6 +26096,7 @@ var require_symbols6 = __commonJS({ kDestroy: /* @__PURE__ */ Symbol("destroy"), kDispatch: /* @__PURE__ */ Symbol("dispatch"), kUrl: /* @__PURE__ */ Symbol("url"), + kRedirectCacheControl: /* @__PURE__ */ Symbol("redirect cache control"), kWriting: /* @__PURE__ */ Symbol("writing"), kResuming: /* @__PURE__ */ Symbol("resuming"), kQueue: /* @__PURE__ */ Symbol("queue"), @@ -27258,6 +27344,19 @@ var require_util10 = __commonJS({ } return ret; } + 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; + } function encodeRawHeaders(headers) { if (!Array.isArray(headers)) { throw new TypeError("expected headers to be an array"); @@ -27779,6 +27878,7 @@ var require_util10 = __commonJS({ removeAllListeners, errorRequest: errorRequest2, parseRawHeaders, + toRawHeaders, encodeRawHeaders, parseHeaders, parseKeepAliveTimeout, @@ -28164,7 +28264,7 @@ var require_request3 = __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; @@ -28675,6 +28775,7 @@ var require_unwrap_handler = __commonJS({ var require_dispatcher_base2 = __commonJS({ "node_modules/@octokit/action/node_modules/undici/lib/dispatcher/dispatcher-base.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var Dispatcher = require_dispatcher2(); var UnwrapHandler = require_unwrap_handler(); var { @@ -28686,6 +28787,7 @@ var require_dispatcher_base2 = __commonJS({ var kOnDestroyed = /* @__PURE__ */ Symbol("onDestroyed"); var kOnClosed = /* @__PURE__ */ Symbol("onClosed"); var kWebSocketOptions = /* @__PURE__ */ Symbol("webSocketOptions"); + var kEventSourceOptions = /* @__PURE__ */ Symbol("eventSourceOptions"); var DispatcherBase = class extends Dispatcher { /** @type {boolean} */ [kDestroyed] = false; @@ -28701,6 +28803,7 @@ var require_dispatcher_base2 = __commonJS({ constructor(opts) { super(); this[kWebSocketOptions] = opts?.webSocket ?? {}; + this[kEventSourceOptions] = opts?.eventSource ?? {}; } /** * @returns {import('../../types/dispatcher').WebSocketOptions} @@ -28712,6 +28815,14 @@ var require_dispatcher_base2 = __commonJS({ // 128 MB default }; } + /** + * @returns {import('../../types/client').Client.EventSourceOptions} + */ + get eventSourceOptions() { + return { + maxEventSize: this[kEventSourceOptions].maxEventSize ?? buffer.kStringMaxLength + }; + } /** @returns {boolean} */ get destroyed() { return this[kDestroyed]; @@ -28857,15 +28968,19 @@ var require_connect2 = __commonJS({ if (this._sessionCache.has(sessionKey)) { this._sessionCache.delete(sessionKey); } else if (this._sessionCache.size >= this._maxCachedSessions) { + let evicted = false; for (const [key, ref] of this._sessionCache) { if (ref.deref() === void 0) { this._sessionCache.delete(key); - return; + evicted = true; + break; } } - const oldest = this._sessionCache.keys().next(); - if (!oldest.done) { - this._sessionCache.delete(oldest.value); + if (!evicted) { + const oldest = this._sessionCache.keys().next(); + if (!oldest.done) { + this._sessionCache.delete(oldest.value); + } } } this._sessionCache.set(sessionKey, new WeakRef(session)); @@ -29924,6 +30039,10 @@ var require_infra = __commonJS({ return input.slice(start, position.position); } var ASCII_WHITESPACE_REPLACE_REGEX = /[\u0009\u000A\u000C\u000D\u0020]/g; + var nonASCIIRegex = /[^\x00-\x7F]/; + function asciiLowercase(str) { + return nonASCIIRegex.test(str) ? str.replace(/[A-Z]+/g, (upper) => upper.toLowerCase()) : str.toLowerCase(); + } function forgivingBase64(data) { data = data.replace(ASCII_WHITESPACE_REPLACE_REGEX, ""); let dataLength = data.length; @@ -29998,6 +30117,7 @@ var require_infra = __commonJS({ return result; } module2.exports = { + asciiLowercase, collectASequenceOfCodePoints, collectASequenceOfCodePointsFast, forgivingBase64, @@ -32307,19 +32427,38 @@ var require_body2 = __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 iterator2 = result?.[Symbol.asyncIterator]?.(); + if (iterator2 == 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 iterator2.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" }); @@ -32376,7 +32515,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r length = null; } source = object; - action = async function* () { + const parts = (async function* () { for (const part of blobParts) { if (part.stream) { yield* part.stream(); @@ -32384,7 +32523,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r yield part; } } - }; + })(); + action = () => parts; type = `multipart/form-data; boundary=${boundary}`; } else if (webidl.is.Blob(object)) { source = object; @@ -32404,28 +32544,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r stream = webidl.is.ReadableStream(object) ? object : ReadableStreamFrom(object); } if (typeof source === "string" || isUint8Array(source)) { - action = () => { - length = typeof source === "string" ? Buffer.byteLength(source) : source.length; - return source; - }; - } - if (action != null) { - ; - (async () => { - const result = action(); - const iterator2 = result?.[Symbol.asyncIterator]?.(); - if (iterator2) { - for await (const bytes of iterator2) { - 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 = () => source; + length = typeof source === "string" ? Buffer.byteLength(source) : source.length; } const body = { stream, source, length }; return [body, type]; @@ -32618,6 +32738,7 @@ var require_client_h12 = __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_wasm2() : void 0; @@ -33277,7 +33398,6 @@ var require_client_h12 = __commonJS({ }; } function onHttpSocketError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); const parser = this[kParser]; if (err.code === "ECONNRESET" && parser.statusCode && !parser.shouldKeepAlive) { const parserErr = parser.finish(); @@ -33406,6 +33526,24 @@ var require_client_h12 = __commonJS({ function shouldSendContentLength(method) { return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; } + function setTypeOfService(socket, request2) { + if (typeof socket.setTypeOfService !== "function") { + return; + } + const typeOfService = request2.typeOfService; + if (typeOfService === void 0) { + return; + } + const currentTypeOfService = socket[kTypeOfService]; + if (currentTypeOfService === typeOfService) { + return; + } + try { + socket.setTypeOfService(typeOfService); + socket[kTypeOfService] = typeOfService; + } catch { + } + } function writeH1(client, request2) { const { method, path, host, upgrade, blocking, reset } = request2; let { body, headers, contentLength } = request2; @@ -33482,9 +33620,7 @@ var require_client_h12 = __commonJS({ if (blocking) { socket[kBlocking] = true; } - if (socket.setTypeOfService) { - socket.setTypeOfService(request2.typeOfService); - } + setTypeOfService(socket, request2); let header = `${method} ${path} HTTP/1.1\r `; if (typeof host === "string") { @@ -34057,7 +34193,6 @@ var require_client_h22 = __commonJS({ } } function onHttp2SessionError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kSocket][kError] = err; this[kClient][kOnError](err); } @@ -34147,7 +34282,6 @@ var require_client_h22 = __commonJS({ client[kResume](); } function onHttp2SocketError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kError] = err; this[kClient][kOnError](err); } @@ -34708,7 +34842,8 @@ var require_client2 = __commonJS({ initialWindowSize, connectionWindowSize, pingInterval, - webSocket + webSocket, + eventSource } = {}) { if (keepAlive !== void 0) { throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead"); @@ -34786,7 +34921,7 @@ var require_client2 = __commonJS({ if (pingInterval != null && (typeof pingInterval !== "number" || !Number.isInteger(pingInterval) || pingInterval < 0)) { throw new InvalidArgumentError("pingInterval must be a positive integer, greater or equal to 0"); } - super({ webSocket }); + super({ webSocket, eventSource }); if (typeof connect2 !== "function") { connect2 = buildConnector({ ...tls, @@ -35767,7 +35902,7 @@ var require_agent2 = __commonJS({ return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts); } var Agent = class extends DispatcherBase { - constructor({ factory = defaultFactory, maxOrigins = Infinity, connect, ...options } = {}) { + constructor({ factory = defaultFactory, maxOrigins = Infinity, connect, tls, ...options } = {}) { if (typeof factory !== "function") { throw new InvalidArgumentError("factory must be a function."); } @@ -35781,7 +35916,10 @@ var require_agent2 = __commonJS({ if (connect && typeof connect !== "function") { connect = { ...connect }; } - this[kOptions] = { ...util.deepClone(options), maxOrigins, connect }; + if (tls && typeof tls !== "function") { + tls = { ...tls }; + } + this[kOptions] = { ...util.deepClone(options), maxOrigins, connect, tls }; this[kFactory] = factory; this[kClients] = /* @__PURE__ */ new Map(); this[kOrigins] = /* @__PURE__ */ new Set(); @@ -40645,7 +40783,7 @@ var require_redirect_handler2 = __commonJS({ "node_modules/@octokit/action/node_modules/undici/lib/handler/redirect-handler.js"(exports2, module2) { "use strict"; var util = require_util10(); - var { kBodyUsed } = require_symbols6(); + var { kBodyUsed, kRedirectCacheControl } = require_symbols6(); var assert = require("node:assert"); var { InvalidArgumentError } = require_errors3(); var EE = require("node:events"); @@ -40683,6 +40821,10 @@ var require_redirect_handler2 = __commonJS({ this.maxRedirections = maxRedirections; this.handler = handler2; this.history = []; + Object.defineProperty(this.history, kRedirectCacheControl, { + value: [], + enumerable: false + }); if (util.isStream(this.opts.body)) { if (util.bodyLength(this.opts.body) === 0) { this.opts.body.on("data", function() { @@ -40733,6 +40875,11 @@ var require_redirect_handler2 = __commonJS({ this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage); return; } + 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; const redirectUrlString = `${origin}${path}`; @@ -40779,9 +40926,17 @@ var require_redirect_handler2 = __commonJS({ 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]); + if (headers.length > 0 && Array.isArray(headers[0])) { + for (const [key, value] of headers) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + ret.push(key, value); + } + } + } else { + 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") { @@ -41600,15 +41755,46 @@ var require_cache2 = __commonJS({ } else if (typeof opts.headers === "object") { 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)) { + 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)) { @@ -42434,6 +42620,7 @@ var require_cache_handler = __commonJS({ "node_modules/@octokit/action/node_modules/undici/lib/handler/cache-handler.js"(exports2, module2) { "use strict"; var util = require_util10(); + var { kRedirectCacheControl } = require_symbols6(); var { parseCacheControlHeader, hasInvalidCacheControlDirective, @@ -42445,6 +42632,13 @@ var require_cache_handler = __commonJS({ var { parseHttpDate } = require_date(); function noop4() { } + function sameOrigin(a, b) { + try { + return new URL(String(a)).origin === new URL(String(b)).origin; + } catch { + return String(a) === String(b); + } + } var HEURISTICALLY_CACHEABLE_STATUS_CODES = [ 200, 203, @@ -42463,6 +42657,7 @@ var require_cache_handler = __commonJS({ 206 ]; var MAX_RESPONSE_AGE = 2147483647e3; + var REVALIDATION_ONLY_RETENTION = 864e5; function trimOWS(value) { return value.replace(/^[\t ]+|[\t ]+$/g, ""); } @@ -42474,6 +42669,15 @@ var require_cache_handler = __commonJS({ } 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]; for (let i = 0; i < values.length; i++) { @@ -42535,6 +42739,9 @@ var require_cache_handler = __commonJS({ deleteLocationTargets(store, cacheKey, resHeaders.location); deleteLocationTargets(store, cacheKey, resHeaders["content-location"]); } + function requestCarriesCredentials(headers) { + return headers != null && (Object.hasOwn(headers, "authorization") || Object.hasOwn(headers, "cookie") || Object.hasOwn(headers, "proxy-authorization")); + } var CacheHandler = class { /** * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey} @@ -42560,6 +42767,19 @@ var require_cache_handler = __commonJS({ * @type {import('node:stream').Writable | undefined} */ #writeStream; + /** + * The URLs visited while following redirects, shared by reference from the + * redirect handler through the request context. Carries the suppressed hops' + * 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 @@ -42575,6 +42795,10 @@ var require_cache_handler = __commonJS({ onRequestStart(controller, context) { this.#writeStream?.destroy(); this.#writeStream = void 0; + this.#replaying304 = false; + this.#suppress304End = false; + this.#pending304End = void 0; + this.#history = context?.history; this.#handler.onRequestStart?.(controller, context); } onRequestUpgrade(controller, statusCode, headers, socket) { @@ -42598,6 +42822,29 @@ var require_cache_handler = __commonJS({ invalidateUnsafeRequest(this.#store, this.#cacheKey, resHeaders); return downstreamOnHeaders(); } + if (this.#history && this.#history.length > 1 && requestCarriesCredentials(this.#cacheKey.headers)) { + return downstreamOnHeaders(); + } + if (this.#history && this.#history.length > 0) { + for (const hopUrl of this.#history) { + if (!sameOrigin(hopUrl.origin, this.#cacheKey.origin)) { + return downstreamOnHeaders(); + } + } + } + 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 + ) : void 0; + if (redirectHopInfo?.length > 0 && redirectPolicy === void 0) { + return downstreamOnHeaders(); + } const cacheControlHeader = resHeaders["cache-control"]; const cacheControlDirectives = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {}; if (revalidationResponseDisallowsCachedReuse(this.#cacheType, resHeaders, cacheControlDirectives)) { @@ -42617,7 +42864,6 @@ var require_cache_handler = __commonJS({ } return downstreamOnHeaders(); } - const now = Date.now(); const resAge = Object.hasOwn(resHeaders, "age") ? getAge(resHeaders.age) : void 0; if (resAge !== void 0 && resAge >= MAX_RESPONSE_AGE) { deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); @@ -42630,43 +42876,102 @@ var require_cache_handler = __commonJS({ } const apparentAge = resDate ? Math.max(0, now - resDate.getTime()) : 0; const currentAge = Math.max(apparentAge, resAge ?? 0); - const staleAt = determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives) ?? this.#cacheByDefault; - if (staleAt === void 0 || currentAge >= staleAt) { + const hasValidator = typeof resHeaders.etag === "string" && isEtagUsable(resHeaders.etag) || typeof resHeaders["last-modified"] === "string"; + const staleAt = determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives, hasValidator) ?? this.#cacheByDefault; + const revalidationOnly = staleAt === 0 && hasValidator; + if (staleAt === void 0 || currentAge >= staleAt && !revalidationOnly) { if (cacheControlHeader || staleAt !== void 0) { deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); } return downstreamOnHeaders(); } const baseTime = now - currentAge; - const absoluteStaleAt = staleAt + baseTime; - if (now >= absoluteStaleAt) { + let absoluteStaleAt = staleAt + baseTime; + if (redirectPolicy !== void 0) { + absoluteStaleAt = Math.min(absoluteStaleAt, redirectPolicy.staleAt); + } + if (now >= absoluteStaleAt && !revalidationOnly) { deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); return downstreamOnHeaders(); } let varyDirectives; - if (this.#cacheKey.headers && resHeaders.vary) { - varyDirectives = parseVaryHeader(resHeaders.vary, this.#cacheKey.headers); - if (!varyDirectives) { - 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)) { + return downstreamOnHeaders(); + } + } + if (this.#cacheKey.headers) { + varyDirectives = parseVaryHeader(combinedVary, this.#cacheKey.headers); + if (!varyDirectives) { + return downstreamOnHeaders(); + } + } + } + let effectiveCacheControlDirectives = cacheControlDirectives; + if (redirectPolicy !== void 0) { + 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); const value = { statusCode, statusMessage, headers: strippedHeaders, vary: varyDirectives, - cacheControlDirectives, + cacheControlDirectives: effectiveCacheControlDirectives, cachedAt, staleAt: absoluteStaleAt, deleteAt }; if (statusCode === 304) { + this.#replaying304 = true; + let done = false; + const finish304 = () => { + if (done) { + return; + } + done = true; + this.#replaying304 = false; + if (this.#pending304End) { + const { controller: controller2, trailers } = this.#pending304End; + this.#pending304End = void 0; + this.#writeStream?.end(); + this.#handler.onResponseEnd?.(controller2, trailers); + } + }; + const failReplay = (err) => { + if (done) { + return; + } + done = true; + this.#replaying304 = false; + this.#suppress304End = true; + this.#pending304End = void 0; + this.#writeStream?.destroy(); + try { + this.#handler.onResponseError?.(controller, err); + } catch { + } + }; const handle304 = (cachedValue) => { if (!cachedValue) { - return downstreamOnHeaders(); + downstreamOnHeaders(); + finish304(); + return; } value.statusCode = cachedValue.statusCode; value.statusMessage = cachedValue.statusMessage; @@ -42676,39 +42981,57 @@ var require_cache_handler = __commonJS({ downstreamOnHeaders(); this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value); if (!this.#writeStream || !cachedValue?.body) { + finish304(); return; } if (typeof cachedValue.body.values === "function") { const bodyIterator = cachedValue.body.values(); const streamCachedBody = () => { - for (const chunk of bodyIterator) { - const full = this.#writeStream.write(chunk) === false; - this.#handler.onResponseData?.(controller, chunk); - if (full) { - break; + if (done) { + return; + } + try { + for (const chunk of bodyIterator) { + const full = this.#writeStream?.write(chunk) === false; + this.#handler.onResponseData?.(controller, chunk); + if (full) { + return; + } } + finish304(); + } catch (err) { + failReplay(err); } }; this.#writeStream.on("error", function() { handler2.#writeStream = void 0; handler2.#store.delete(handler2.#cacheKey); + streamCachedBody(); }).on("drain", () => { streamCachedBody(); }).on("close", function() { if (handler2.#writeStream === this) { handler2.#writeStream = void 0; + streamCachedBody(); } }); streamCachedBody(); } else if (typeof cachedValue.body.on === "function") { 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 = void 0; this.#store.delete(this.#cacheKey); + finish304(); }); this.#writeStream.on("error", function() { handler2.#writeStream = void 0; @@ -42718,11 +43041,15 @@ var require_cache_handler = __commonJS({ handler2.#writeStream = void 0; } }); + } else { + finish304(); } }; const result = this.#store.get(this.#cacheKey); if (result && typeof result.then === "function") { - result.then(handle304); + result.then(handle304, () => handle304(void 0)).catch((err) => { + failReplay(err); + }); } else { handle304(result); } @@ -42753,10 +43080,20 @@ var require_cache_handler = __commonJS({ this.#handler.onResponseData?.(controller, chunk); } 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 = void 0; this.#writeStream?.destroy(err); this.#writeStream = void 0; this.#handler.onResponseError?.(controller, err); @@ -42812,6 +43149,74 @@ var require_cache_handler = __commonJS({ } return true; } + 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 === void 0 || hopPolicy.staleAt <= now) { + return void 0; + } + staleAt = Math.min(staleAt, hopPolicy.staleAt); + requiresRevalidation ||= hopPolicy.requiresRevalidation; + } + return { staleAt, requiresRevalidation }; + } + function getRedirectHopPolicy(cacheType, method, hop, reqHeaders, cacheByDefault) { + if (!Number.isInteger(hop?.statusCode) || !Number.isFinite(hop?.receivedAt)) { + return void 0; + } + const hopHeaders = hop.headers ?? {}; + const cacheControlHeader = hopHeaders["cache-control"]; + const hopCacheControl = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {}; + if (hopHeaders.vary && hasVaryStar(hopHeaders.vary)) { + return void 0; + } + if (hopCacheControl["no-store"] === true) { + return void 0; + } + if (cacheType === "shared" && Object.hasOwn(hopCacheControl, "private")) { + return void 0; + } + if (Object.hasOwn(hopCacheControl, "no-cache") || hopCacheControl["must-revalidate"] === true || cacheType === "shared" && hopCacheControl["proxy-revalidate"] === true) { + return void 0; + } + const heuristicallyCacheable = hopHeaders["last-modified"] && arrayIncludes(HEURISTICALLY_CACHEABLE_STATUS_CODES, hop.statusCode); + if (!cacheControlHeader && !hopHeaders.expires && !heuristicallyCacheable && !cacheByDefault) { + return void 0; + } + if (!canCacheResponse(cacheType, method, hop.statusCode, hopHeaders, hopCacheControl, reqHeaders)) { + return void 0; + } + const age = Object.hasOwn(hopHeaders, "age") ? getAge(hopHeaders.age) : void 0; + if (age !== void 0 && age >= MAX_RESPONSE_AGE) { + return void 0; + } + const responseDate = Object.hasOwn(hopHeaders, "date") ? getDate(hopHeaders.date) : void 0; + if (responseDate === null) { + return void 0; + } + 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 === void 0) { + return void 0; + } + 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") + }; + } function getDate(dateHeader) { let dateValue = dateHeader; if (Array.isArray(dateValue)) { @@ -42842,7 +43247,7 @@ var require_cache_handler = __commonJS({ } return Number(age) * 1e3; } - function determineStaleAt(cacheType, now, age, resHeaders, responseDate, cacheControlDirectives) { + function determineStaleAt(cacheType, now, age, resHeaders, responseDate, cacheControlDirectives, hasValidator) { if (cacheType === "shared") { if (hasInvalidCacheControlDirective(cacheControlDirectives, "s-maxage")) { return 0; @@ -42895,6 +43300,9 @@ var require_cache_handler = __commonJS({ if (cacheControlDirectives.immutable) { return 31536e6; } + if (cacheControlDirectives["no-cache"] === true && hasValidator) { + return 0; + } return void 0; } function determineDeleteAt(baseTime, cachedAt, cacheControlDirectives, staleAt) { @@ -42912,6 +43320,9 @@ var require_cache_handler = __commonJS({ } if (staleWhileRevalidate === -Infinity && staleIfError === -Infinity && immutable === -Infinity) { const freshnessLifetime = staleAt - baseTime; + if (freshnessLifetime <= 0) { + return cachedAt + REVALIDATION_ONLY_RETENTION; + } const datePrecisionPadding = Math.min(Math.max(cachedAt - baseTime, 0), 1e3); return staleAt + freshnessLifetime + datePrecisionPadding; } @@ -43257,7 +43668,16 @@ var require_cache3 = __commonJS({ var CacheHandler = require_cache_handler(); var MemoryCacheStore = require_memory_cache_store(); var CacheRevalidationHandler = require_cache_revalidation_handler(); - var { assertCacheStore, assertCacheMethods, makeCacheKey, normalizeHeaders, parseCacheControlHeader, isInvalidOrWildcardVaryHeader } = require_cache2(); + var { + assertCacheStore, + assertCacheMethods, + makeCacheKey, + normalizeHeaders, + parseCacheControlHeader, + isInvalidOrWildcardVaryHeader, + parseVaryHeader, + isEtagUsable + } = require_cache2(); var { AbortError } = require_errors3(); var { parseHttpDate } = require_date(); function assertCacheOrigins(origins, name) { @@ -43336,6 +43756,17 @@ var require_cache3 = __commonJS({ function revalidationResponseUpdatesCacheControl(headers) { return headers["cache-control"] !== void 0; } + 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); @@ -43365,6 +43796,34 @@ var require_cache3 = __commonJS({ } 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; + } function isStale(result, cacheControlDirectives, cacheType) { const now = Date.now(); if (now > result.staleAt) { @@ -43446,18 +43905,23 @@ var require_cache3 = __commonJS({ }; stream.on("error", function(err) { if (!this.readableEnded) { - if (typeof handler2.onResponseError === "function") { - handler2.onResponseError(controller, err); - } else { - throw err; - } + handler2.onResponseError?.(controller, err); } }).on("close", function() { if (!this.errored) { - handler2.onResponseEnd?.(controller, {}); + try { + handler2.onResponseEnd?.(controller, {}); + } catch (err) { + handler2.onResponseError?.(controller, err); + } } }); - handler2.onRequestStart?.(controller, context); + try { + handler2.onRequestStart?.(controller, context); + } catch (err) { + stream.destroy(err); + return; + } if (stream.destroyed) { return; } @@ -43465,12 +43929,22 @@ var require_cache3 = __commonJS({ if (isStale2) { headers.warning = '110 - "response is stale"'; } - handler2.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage); + controller.rawHeaders = util.toRawHeaders(headers); + try { + handler2.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) { - handler2.onResponseData?.(controller, chunk); + try { + handler2.onResponseData?.(controller, chunk); + } catch (err) { + stream.destroy(err); + } }); } } @@ -43533,6 +44007,13 @@ var require_cache3 = __commonJS({ } } 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, handler2)); + }; return dispatch( { ...opts, @@ -43542,15 +44023,13 @@ var require_cache3 = __commonJS({ (success, context, statusCode, headers2) => { if (success) { if (statusCode === 304) { - if (revalidationResponseDisallowsCachedReuse(globalOpts.type, headers2)) { - if (util.isStream(result.body)) { - result.body.on("error", nop).destroy(); - } - deleteCachedValue(globalOpts.store, cacheKey); - return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler2)); + if (!revalidationTargetMatchesCacheKey(cacheKey, context) || !revalidationEtagMatchesCachedValue(result, headers2) || revalidationResponseDisallowsCachedReuse(globalOpts.type, headers2)) { + return refetch(); } if (revalidationResponseUpdatesCacheControl(headers2)) { deleteCachedValue(globalOpts.store, cacheKey); + } else if (revalidationResponseAddsVary(result, headers2.vary ? parseVaryHeader(headers2.vary, opts.headers) : void 0)) { + return refetch(); } } sendCachedValue(handler2, opts, result, age, context, stale); @@ -43647,7 +44126,31 @@ var require_cache3 = __commonJS({ opts2, reqCacheControl, result2 - )); + )).catch((err) => { + if (typeof handler2.onResponseError === "function") { + handler2.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, @@ -43861,9 +44364,14 @@ var require_decompress = __commonJS({ } this.#decompressedSize = decompressedSize; } - const result = super.onResponseData(this.#controller, chunk); - if (result === false && !this.#controller.paused) { - this.#controller.pause(); + try { + const result = super.onResponseData(this.#controller, chunk); + if (result === false && !this.#controller.paused) { + this.#controller.pause(); + } + } catch (err) { + this.#fail(err); + return; } } } while (this.#drainRequested && !this.#terminated && !this.#controller.paused); @@ -43877,9 +44385,14 @@ var require_decompress = __commonJS({ if (this.#terminated || !this.#completionPending || this.#controller.paused || this.#draining) { return; } - this.#terminated = true; this.#cleanupDecompressors(); - super.onResponseEnd(this.#controller, this.#trailers); + try { + super.onResponseEnd(this.#controller, this.#trailers); + } catch (err) { + this.#fail(err); + return; + } + this.#terminated = true; } #onDecompressionEnd() { if (this.#terminated) { @@ -44024,7 +44537,8 @@ var require_decompress = __commonJS({ * @returns {void} */ onResponseStart(controller, statusCode, headers, statusMessage) { - const contentEncoding = headers["content-encoding"]; + const rawContentEncoding = headers["content-encoding"]; + const contentEncoding = Array.isArray(rawContentEncoding) ? rawContentEncoding.join(",") : rawContentEncoding; if (this.#shouldSkipDecompression(contentEncoding, statusCode)) { return super.onResponseStart(this.#controller, statusCode, headers, statusMessage); } @@ -44142,6 +44656,18 @@ var require_deduplication_handler = __commonJS({ * @type {DispatchHandler} */ #primaryHandler; + /** + * Whether the primary request has started (onRequestStart received). Until + * then the request context is unknown and cannot be given to waiting handlers. + * @type {boolean} + */ + #requestStarted = false; + /** + * The primary request context, replayed to waiting handlers so they observe + * the same redirect history as the primary. + * @type {any} + */ + #context = null; /** * @type {WaitingHandler[]} */ @@ -44210,18 +44736,22 @@ var require_deduplication_handler = __commonJS({ const waitingHandler = this.#createWaitingHandler(handler2); const waitingController = waitingHandler.controller; try { - handler2.onRequestStart?.(waitingController, null); - if (waitingController.aborted) { - waitingHandler.done = true; - return true; - } - if (this.#responseStarted) { - handler2.onResponseStart?.( - waitingController, - this.#statusCode, - this.#headers, - this.#statusMessage - ); + if (this.#requestStarted) { + handler2.onRequestStart?.(waitingController, this.#context); + if (waitingController.aborted) { + waitingHandler.done = true; + return true; + } + if (this.#responseStarted) { + handler2.onResponseStart?.( + waitingController, + this.#statusCode, + this.#headers, + this.#statusMessage + ); + } + } else { + waitingHandler.pendingStart = true; } } catch { waitingHandler.done = true; @@ -44238,6 +44768,21 @@ var require_deduplication_handler = __commonJS({ */ onRequestStart(controller, context) { this.#controller = controller; + if (!this.#requestStarted) { + this.#requestStarted = true; + this.#context = context; + for (const waitingHandler of this.#waitingHandlers) { + if (waitingHandler.pendingStart && !waitingHandler.done && !waitingHandler.controller.aborted) { + waitingHandler.pendingStart = false; + try { + waitingHandler.handler.onRequestStart?.(waitingHandler.controller, context); + } catch { + waitingHandler.done = true; + } + } + } + this.#pruneDoneWaitingHandlers(); + } this.#primaryHandler.onRequestStart?.(controller, context); } /** @@ -44375,7 +44920,8 @@ var require_deduplication_handler = __commonJS({ bufferedChunks: [], bufferedBytes: 0, pendingTrailers: null, - done: false + done: false, + pendingStart: false }; const state = { aborted: false, @@ -44582,7 +45128,7 @@ var require_sqlite_cache_store = __commonJS({ var { Writable } = require("node:stream"); var { assertCacheKey, assertCacheValue } = require_cache2(); var DatabaseSync; - var VERSION10 = 3; + var VERSION10 = 4; var MAX_ENTRY_SIZE = 2 * 1e3 * 1e3 * 1e3; module2.exports = class SqliteCacheStore { #maxEntrySize = MAX_ENTRY_SIZE; @@ -46584,6 +47130,7 @@ var require_subresource_integrity = __commonJS({ "use strict"; var assert = require("node:assert"); var { runtimeFeatures } = require_runtime_features(); + var { asciiLowercase } = require_infra(); var validSRIHashAlgorithmTokenSet = /* @__PURE__ */ new Map([["sha256", 0], ["sha384", 1], ["sha512", 2]]); var crypto; if (runtimeFeatures.has("crypto")) { @@ -46606,10 +47153,7 @@ var require_subresource_integrity = __commonJS({ validSRIHashAlgorithmTokenSet ) ); - var isValidSRIHashAlgorithm = ( - /** @type {IsValidSRIHashAlgorithm} */ - Map.prototype.has.bind(validSRIHashAlgorithmTokenSet) - ); + var isValidSRIHashAlgorithm = (algorithm) => validSRIHashAlgorithmTokenSet.has(asciiLowercase(algorithm)); var bytesMatch = runtimeFeatures.has("crypto") === false || validSRIHashAlgorithmTokenSet.size === 0 ? () => true : (bytes, metadataList) => { const parsedMetadata = parseMetadata(metadataList); if (parsedMetadata.length === 0) { @@ -46657,7 +47201,7 @@ var require_subresource_integrity = __commonJS({ } 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 = ""; @@ -46670,7 +47214,8 @@ var require_subresource_integrity = __commonJS({ base64Value = algorithmAndValue[1]; } const metadata2 = { - alg: algorithm, + // Possible spec bug? + alg: asciiLowercase(algorithm), val: base64Value }; result.push(metadata2); @@ -47719,7 +48264,6 @@ var require_fetch2 = __commonJS({ } } const location = headersList.get("location", true); - this.body = new Readable({ read: resume }); const willFollow = location && request2.redirect === "follow" && redirectStatusSet.has(status); const decoders = []; if (request2.method !== "HEAD" && request2.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) { @@ -47727,7 +48271,7 @@ var require_fetch2 = __commonJS({ const codings = contentEncoding ? contentEncoding.toLowerCase().split(",") : []; const maxContentEncodings = 5; if (codings.length > maxContentEncodings) { - reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); + this.abort(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); return true; } for (let i = codings.length - 1; i >= 0; --i) { @@ -47762,6 +48306,7 @@ var require_fetch2 = __commonJS({ } } } + this.body = new Readable({ read: resume }); const onError = this.onError.bind(this); resolve({ status, @@ -48741,8 +49286,12 @@ var require_util13 = __commonJS({ validateCookiePath(cookie.path); out.push(`Path=${cookie.path}`); } - if (cookie.expires && cookie.expires.toString() !== "Invalid Date") { - out.push(`Expires=${toIMFDate(cookie.expires)}`); + if (cookie.expires != null) { + const expiresMs = cookie.expires instanceof Date ? cookie.expires.getTime() : cookie.expires; + const maxTimeValue = 864e13; + if (typeof expiresMs === "number" && Number.isFinite(expiresMs) && Math.abs(expiresMs) <= maxTimeValue) { + out.push(`Expires=${toIMFDate(cookie.expires)}`); + } } if (cookie.sameSite) { out.push(`SameSite=${cookie.sameSite}`); @@ -48817,88 +49366,89 @@ var require_parse2 = __commonJS({ }; } function parseUnparsedAttributes(unparsedAttributes, cookieAttributeList = {}) { - if (unparsedAttributes.length === 0) { - return cookieAttributeList; - } - assert(unparsedAttributes[0] === ";"); - unparsedAttributes = unparsedAttributes.slice(1); - let cookieAv = ""; - if (unparsedAttributes.includes(";")) { - cookieAv = collectASequenceOfCodePointsFast( - ";", - unparsedAttributes, - { position: 0 } - ); - unparsedAttributes = unparsedAttributes.slice(cookieAv.length); - } else { - cookieAv = unparsedAttributes; - unparsedAttributes = ""; - } - let attributeName = ""; - let attributeValue = ""; - if (cookieAv.includes("=")) { - const position = { position: 0 }; - attributeName = collectASequenceOfCodePointsFast( - "=", - cookieAv, - position - ); - attributeValue = cookieAv.slice(position.position + 1); - } else { - attributeName = cookieAv; - } - attributeName = attributeName.trim(); - attributeValue = attributeValue.trim(); - if (attributeValue.length > maxAttributeValueSize) { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); - } - const attributeNameLowercase = attributeName.toLowerCase(); - if (attributeNameLowercase === "expires") { - const expiryTime = new Date(attributeValue); - cookieAttributeList.expires = expiryTime; - } else if (attributeNameLowercase === "max-age") { - const charCode = attributeValue.charCodeAt(0); - if ((charCode < 48 || charCode > 57) && attributeValue[0] !== "-") { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); - } - if (!/^\d+$/.test(attributeValue)) { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); + while (true) { + if (unparsedAttributes.length === 0) { + return cookieAttributeList; + } + assert(unparsedAttributes[0] === ";"); + unparsedAttributes = unparsedAttributes.slice(1); + let cookieAv = ""; + if (unparsedAttributes.includes(";")) { + cookieAv = collectASequenceOfCodePointsFast( + ";", + unparsedAttributes, + { position: 0 } + ); + unparsedAttributes = unparsedAttributes.slice(cookieAv.length); + } else { + cookieAv = unparsedAttributes; + unparsedAttributes = ""; + } + let attributeName = ""; + let attributeValue = ""; + if (cookieAv.includes("=")) { + const position = { position: 0 }; + attributeName = collectASequenceOfCodePointsFast( + "=", + cookieAv, + position + ); + attributeValue = cookieAv.slice(position.position + 1); + } else { + attributeName = cookieAv; } - const deltaSeconds = Number(attributeValue); - cookieAttributeList.maxAge = deltaSeconds; - } else if (attributeNameLowercase === "domain") { - let cookieDomain = attributeValue; - if (cookieDomain[0] === ".") { - cookieDomain = cookieDomain.slice(1); + attributeName = attributeName.trim(); + attributeValue = attributeValue.trim(); + if (attributeValue.length > maxAttributeValueSize) { + continue; } - cookieDomain = cookieDomain.toLowerCase(); - cookieAttributeList.domain = cookieDomain; - } else if (attributeNameLowercase === "path") { - let cookiePath = ""; - if (attributeValue.length === 0 || attributeValue[0] !== "/") { - cookiePath = "/"; + const attributeNameLowercase = attributeName.toLowerCase(); + if (attributeNameLowercase === "expires") { + const expiryTime = new Date(attributeValue); + cookieAttributeList.expires = expiryTime; + } else if (attributeNameLowercase === "max-age") { + const charCode = attributeValue.charCodeAt(0); + if ((charCode < 48 || charCode > 57) && attributeValue[0] !== "-") { + continue; + } + if (!/^\d+$/.test(attributeValue)) { + continue; + } + const deltaSeconds = Number(attributeValue); + cookieAttributeList.maxAge = deltaSeconds; + } else if (attributeNameLowercase === "domain") { + let cookieDomain = attributeValue; + if (cookieDomain[0] === ".") { + cookieDomain = cookieDomain.slice(1); + } + cookieDomain = cookieDomain.toLowerCase(); + cookieAttributeList.domain = cookieDomain; + } else if (attributeNameLowercase === "path") { + let cookiePath = ""; + if (attributeValue.length === 0 || attributeValue[0] !== "/") { + cookiePath = "/"; + } else { + cookiePath = attributeValue; + } + cookieAttributeList.path = cookiePath; + } else if (attributeNameLowercase === "secure") { + cookieAttributeList.secure = true; + } else if (attributeNameLowercase === "httponly") { + cookieAttributeList.httpOnly = true; + } else if (attributeNameLowercase === "samesite") { + const attributeValueLowercase = attributeValue.toLowerCase(); + if (attributeValueLowercase === "none") { + cookieAttributeList.sameSite = "None"; + } else if (attributeValueLowercase === "strict") { + cookieAttributeList.sameSite = "Strict"; + } else if (attributeValueLowercase === "lax") { + cookieAttributeList.sameSite = "Lax"; + } } else { - cookiePath = attributeValue; + cookieAttributeList.unparsed ??= []; + cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`); } - cookieAttributeList.path = cookiePath; - } else if (attributeNameLowercase === "secure") { - cookieAttributeList.secure = true; - } else if (attributeNameLowercase === "httponly") { - cookieAttributeList.httpOnly = true; - } else if (attributeNameLowercase === "samesite") { - const attributeValueLowercase = attributeValue.toLowerCase(); - if (attributeValueLowercase === "none") { - cookieAttributeList.sameSite = "None"; - } else if (attributeValueLowercase === "strict") { - cookieAttributeList.sameSite = "Strict"; - } else if (attributeValueLowercase === "lax") { - cookieAttributeList.sameSite = "Lax"; - } - } else { - cookieAttributeList.unparsed ??= []; - cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`); } - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); } module2.exports = { parseSetCookie, @@ -48920,7 +49470,7 @@ var require_cookies2 = __commonJS({ webidl.argumentLengthCheck(arguments, 1, "getCookies"); brandChecks(headers); const cookie = headers.get("cookie"); - const out = {}; + const out = { __proto__: null }; if (!cookie) { return out; } @@ -50069,6 +50619,15 @@ var require_receiver2 = __commonJS({ if (isControlFrame(this.#info.opcode)) { this.#loop = this.parseControlFrame(body); this.#state = parserStates.INFO; + if (this.#loop && this.#handler.socket.writableNeedDrain) { + this.#loop = false; + this.#handler.socket.once("drain", () => { + if (this.destroyed) return; + this.#loop = true; + this.run(callback); + }); + return; + } } else { if (!this.#info.compressed) { if (!this.writeFragments(body)) { @@ -51244,6 +51803,7 @@ var require_util15 = __commonJS({ var require_eventsource_stream2 = __commonJS({ "node_modules/@octokit/action/node_modules/undici/lib/web/eventsource/eventsource-stream.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var { Transform } = require("node:stream"); var { isASCIINumber, isValidLastEventId } = require_util15(); var BOM = [239, 187, 191]; @@ -51251,24 +51811,28 @@ var require_eventsource_stream2 = __commonJS({ var CR = 13; var COLON = 58; var SPACE = 32; + var defaultMaxEventSize = buffer.kStringMaxLength; var DATA = Buffer.from("data"); var EVENT = Buffer.from("event"); var ID = Buffer.from("id"); var RETRY = Buffer.from("retry"); - function isASCIINumberBytes(buffer, start) { - if (start >= buffer.length) { + var minParserItems = 1024; + var maxParserItems = 131072; + var bytesPerParserItem = 128; + function isASCIINumberBytes(buffer2, start) { + if (start >= buffer2.length) { return false; } - for (let i = start; i < buffer.length; i++) { - if (buffer[i] < 48 || buffer[i] > 57) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] < 48 || buffer2[i] > 57) { return false; } } return true; } - function isValidLastEventIdBytes(buffer, start) { - for (let i = start; i < buffer.length; i++) { - if (buffer[i] === 0) { + function isValidLastEventIdBytes(buffer2, start) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] === 0) { return false; } } @@ -51285,6 +51849,11 @@ var require_eventsource_stream2 = __commonJS({ } return true; } + function createMaxEventSizeExceededError() { + const error = new Error("EventSource message size exceeded"); + error.aborted = false; + return error; + } var EventSourceStream = class extends Transform { /** * @type {eventSourceSettings} @@ -51311,6 +51880,13 @@ var require_eventsource_stream2 = __commonJS({ pos = 0; lineChunkIndex = 0; linePos = 0; + lineLength = 0; + eventSize = 0; + eventFieldSizes = { data: 0, event: 0, id: 0, retry: 0 }; + dataLineCount = 0; + maxEventSize; + maxDataLines; + maxBufferedChunks; event = { data: void 0, event: void 0, @@ -51320,6 +51896,7 @@ var require_eventsource_stream2 = __commonJS({ /** * @param {object} options * @param {boolean} [options.readableObjectMode] + * @param {number} [options.maxEventSize] * @param {eventSourceSettings} [options.eventSourceSettings] * @param {(chunk: any, encoding?: BufferEncoding | undefined) => boolean} [options.push] */ @@ -51327,6 +51904,10 @@ var require_eventsource_stream2 = __commonJS({ options.readableObjectMode = true; super(options); this.state = options.eventSourceSettings || {}; + this.maxEventSize = options.maxEventSize ?? defaultMaxEventSize; + const parserItemLimit = this.maxEventSize > 0 ? Math.min(maxParserItems, Math.max(minParserItems, Math.floor(this.maxEventSize / bytesPerParserItem))) : 0; + this.maxDataLines = parserItemLimit; + this.maxBufferedChunks = parserItemLimit; if (options.push) { this.push = options.push; } @@ -51342,6 +51923,10 @@ var require_eventsource_stream2 = __commonJS({ callback(); return; } + if (this.maxEventSize > 0 && this.chunks.length >= this.maxBufferedChunks && chunk[0] !== LF && chunk[0] !== CR) { + callback(createMaxEventSizeExceededError()); + return; + } this.chunks.push(chunk); if (this.checkBOM) { if (this.handleBOM()) { @@ -51378,15 +51963,29 @@ var require_eventsource_stream2 = __commonJS({ if (byte === CR) { this.crlfCheck = true; } - this.parseLine(this.readLine(), this.event); + try { + this.parseLine(this.readLine(), this.event); + } catch (error) { + callback(error); + return; + } this.consumeCurrentByte(); this.eventEndCheck = true; continue; } + if (this.maxEventSize > 0 && ++this.lineLength > this.maxEventSize + 7) { + callback(createMaxEventSizeExceededError()); + return; + } this.advanceCursor(); } callback(); } + _destroy(error, callback) { + this.chunks.length = 0; + this.clearEvent(); + super._destroy(error, callback); + } /** * @param {Buffer} line * @param {EventSourceStreamEvent} event @@ -51409,6 +52008,12 @@ var require_eventsource_stream2 = __commonJS({ } } if (isFieldName(line, fieldLength, DATA)) { + if (this.maxEventSize > 0 && this.dataLineCount >= this.maxDataLines) { + throw createMaxEventSizeExceededError(); + } + const valueBytes = line.length - valueStart; + const dataSize = this.eventFieldSizes.data + (event.data === void 0 ? 0 : 1) + valueBytes; + this.setEventFieldSize("data", dataSize); const value = line.toString("utf8", valueStart); if (event.data === void 0) { event.data = value; @@ -51416,27 +52021,38 @@ var require_eventsource_stream2 = __commonJS({ event.data += ` ${value}`; } + this.dataLineCount++; return; } if (isFieldName(line, fieldLength, RETRY)) { if (isASCIINumberBytes(line, valueStart)) { + this.setEventFieldSize("retry", line.length - valueStart); event.retry = line.toString("utf8", valueStart); } return; } if (isFieldName(line, fieldLength, ID)) { if (isValidLastEventIdBytes(line, valueStart)) { + this.setEventFieldSize("id", line.length - valueStart); event.id = line.toString("utf8", valueStart); } return; } if (isFieldName(line, fieldLength, EVENT)) { - const value = line.toString("utf8", valueStart); - if (value.length > 0) { - event.event = value; + if (valueStart < line.length) { + this.setEventFieldSize("event", line.length - valueStart); + event.event = line.toString("utf8", valueStart); } } } + setEventFieldSize(field, size) { + const eventSize = this.eventSize - this.eventFieldSizes[field] + size; + if (this.maxEventSize > 0 && eventSize > this.maxEventSize) { + throw createMaxEventSizeExceededError(); + } + this.eventSize = eventSize; + this.eventFieldSizes[field] = size; + } /** * @param {EventSourceStreamEvent} event */ @@ -51463,6 +52079,12 @@ ${value}`; this.event.event = void 0; this.event.id = void 0; this.event.retry = void 0; + this.eventSize = 0; + this.dataLineCount = 0; + this.eventFieldSizes.data = 0; + this.eventFieldSizes.event = 0; + this.eventFieldSizes.id = 0; + this.eventFieldSizes.retry = 0; } hasPendingEvent() { return this.event.data !== void 0 || this.event.event !== void 0 || this.event.id !== void 0 || this.event.retry !== void 0; @@ -51487,13 +52109,15 @@ ${value}`; syncLineStartToCursor() { this.lineChunkIndex = this.chunkIndex; this.linePos = this.pos; + this.lineLength = 0; this.dropConsumedChunks(); } dropConsumedChunks() { - while (this.lineChunkIndex > 0) { - this.chunks.shift(); - this.lineChunkIndex--; - this.chunkIndex--; + if (this.lineChunkIndex > 0) { + const consumed = this.lineChunkIndex; + this.chunks.splice(0, consumed); + this.lineChunkIndex = 0; + this.chunkIndex -= consumed; } if (this.chunkIndex === this.chunks.length) { this.chunks.length = 0; @@ -51595,6 +52219,7 @@ var require_eventsource2 = __commonJS({ var { isNetworkError } = require_response2(); var { kEnumerableProperty } = require_util10(); var { environmentSettingsObject } = require_util11(); + var { getGlobalDispatcher } = require_global4(); var experimentalWarned = false; var defaultReconnectionTime = 3e3; var CONNECTING = 0; @@ -51736,6 +52361,7 @@ var require_eventsource2 = __commonJS({ this.#state.origin = response.urlList[response.urlList.length - 1].origin; const eventSourceStream = new EventSourceStream({ eventSourceSettings: this.#state, + maxEventSize: this.#dispatcher.eventSourceOptions?.maxEventSize, push: (event) => { this.dispatchEvent(createFastMessageEvent( event.type, @@ -51872,7 +52498,8 @@ var require_eventsource2 = __commonJS({ { key: "dispatcher", // undici only - converter: webidl.converters.any + converter: webidl.converters.any, + defaultValue: () => getGlobalDispatcher() }, { key: "node", diff --git a/dist/update-repo-task-statuses.js b/dist/update-repo-task-statuses.js index 38369365..85f14ec0 100644 --- a/dist/update-repo-task-statuses.js +++ b/dist/update-repo-task-statuses.js @@ -2098,6 +2098,7 @@ var require_dispatcher = __commonJS({ var require_dispatcher_base = __commonJS({ "node_modules/undici/lib/dispatcher/dispatcher-base.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var Dispatcher = require_dispatcher(); var { ClientDestroyedError, @@ -2109,6 +2110,7 @@ var require_dispatcher_base = __commonJS({ var kOnClosed = /* @__PURE__ */ Symbol("onClosed"); var kInterceptedDispatch = /* @__PURE__ */ Symbol("Intercepted Dispatch"); var kWebSocketOptions = /* @__PURE__ */ Symbol("webSocketOptions"); + var kEventSourceOptions = /* @__PURE__ */ Symbol("eventSourceOptions"); var DispatcherBase = class extends Dispatcher { constructor(opts) { super(); @@ -2117,6 +2119,7 @@ var require_dispatcher_base = __commonJS({ this[kClosed] = false; this[kOnClosed] = []; this[kWebSocketOptions] = opts?.webSocket ?? {}; + this[kEventSourceOptions] = opts?.eventSource ?? {}; } get webSocketOptions() { return { @@ -2124,6 +2127,11 @@ var require_dispatcher_base = __commonJS({ maxPayloadSize: this[kWebSocketOptions].maxPayloadSize ?? 128 * 1024 * 1024 }; } + get eventSourceOptions() { + return { + maxEventSize: this[kEventSourceOptions].maxEventSize ?? buffer.kStringMaxLength + }; + } get destroyed() { return this[kDestroyed]; } @@ -6271,7 +6279,6 @@ var require_client_h1 = __commonJS({ socket[kSocketUsed] = false; socket[kParser] = new Parser(client, socket, llhttpInstance); addListener(socket, "error", function(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); const parser = this[kParser]; if (err.code === "ECONNRESET" && parser.statusCode && !parser.shouldKeepAlive) { const parserErr = parser.finish(); @@ -6955,7 +6962,6 @@ var require_client_h2 = __commonJS({ client[kHTTP2Session] = session; socket[kHTTP2Session] = session; util.addListener(socket, "error", function(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kError] = err; this[kClient][kOnError](err); }); @@ -7014,7 +7020,6 @@ var require_client_h2 = __commonJS({ } } function onHttp2SessionError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kSocket][kError] = err; this[kClient][kOnError](err); } @@ -7708,9 +7713,10 @@ var require_client = __commonJS({ // h2 maxConcurrentStreams, allowH2, - webSocket + webSocket, + eventSource } = {}) { - super({ webSocket }); + super({ webSocket, eventSource }); if (keepAlive !== void 0) { throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead"); } @@ -8607,7 +8613,7 @@ var require_agent = __commonJS({ return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts); } var Agent = class extends DispatcherBase { - constructor({ factory = defaultFactory, maxRedirections = 0, connect, ...options } = {}) { + constructor({ factory = defaultFactory, maxRedirections = 0, connect, tls, ...options } = {}) { if (typeof factory !== "function") { throw new InvalidArgumentError("factory must be a function."); } @@ -8621,8 +8627,11 @@ var require_agent = __commonJS({ if (connect && typeof connect !== "function") { connect = { ...connect }; } + if (tls && typeof tls !== "function") { + tls = { ...tls }; + } this[kInterceptors] = options.interceptors?.Agent && Array.isArray(options.interceptors.Agent) ? options.interceptors.Agent : [createRedirectInterceptor({ maxRedirections })]; - this[kOptions] = { ...util.deepClone(options), connect }; + this[kOptions] = { ...util.deepClone(options), connect, tls }; this[kOptions].interceptors = options.interceptors ? { ...options.interceptors } : void 0; this[kMaxRedirections] = maxRedirections; this[kFactory] = factory; @@ -14350,8 +14359,9 @@ var require_fetch = __commonJS({ } ); response.body = { stream, source: null, length: null }; - fetchParams.controller.onAborted = onAborted; - fetchParams.controller.on("terminated", onAborted); + if (!fetchParams.controller.resume) { + fetchParams.controller.on("terminated", onAborted); + } fetchParams.controller.resume = async () => { while (true) { let bytes; @@ -14451,7 +14461,6 @@ var require_fetch = __commonJS({ headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString("latin1"), true); } location = headersList.get("location", true); - this.body = new Readable({ read: resume }); const decoders = []; const willFollow = location && request2.redirect === "follow" && redirectStatusSet.has(status); if (request2.method !== "HEAD" && request2.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) { @@ -14459,7 +14468,7 @@ var require_fetch = __commonJS({ const codings = contentEncoding ? contentEncoding.toLowerCase().split(",") : []; const maxContentEncodings = 5; if (codings.length > maxContentEncodings) { - reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); + this.abort(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); return true; } for (let i = codings.length - 1; i >= 0; --i) { @@ -14489,6 +14498,7 @@ var require_fetch = __commonJS({ } } } + this.body = new Readable({ read: resume }); const onError = this.onError.bind(this); resolve({ status, @@ -14514,9 +14524,6 @@ var require_fetch = __commonJS({ if (this.abort) { fetchParams.controller.off("terminated", this.abort); } - if (fetchParams.controller.onAborted) { - fetchParams.controller.off("terminated", fetchParams.controller.onAborted); - } fetchParams.controller.ended = true; this.body.push(null); }, @@ -17590,6 +17597,16 @@ var require_receiver = __commonJS({ if (isControlFrame(this.#info.opcode)) { this.#loop = this.parseControlFrame(body); this.#state = parserStates.INFO; + const socket = this.ws[kResponse].socket; + if (this.#loop && socket.writableNeedDrain) { + this.#loop = false; + socket.once("drain", () => { + if (this.destroyed) return; + this.#loop = true; + this.run(callback); + }); + return; + } } else { if (!this.#info.compressed) { if (!this.writeFragments(body)) { @@ -18283,6 +18300,7 @@ var require_util8 = __commonJS({ var require_eventsource_stream = __commonJS({ "node_modules/undici/lib/web/eventsource/eventsource-stream.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var { Transform } = require("node:stream"); var { isASCIINumber, isValidLastEventId } = require_util8(); var BOM = [239, 187, 191]; @@ -18290,24 +18308,28 @@ var require_eventsource_stream = __commonJS({ var CR = 13; var COLON = 58; var SPACE = 32; + var defaultMaxEventSize = buffer.kStringMaxLength; var DATA = Buffer.from("data"); var EVENT = Buffer.from("event"); var ID = Buffer.from("id"); var RETRY = Buffer.from("retry"); - function isASCIINumberBytes(buffer, start) { - if (start >= buffer.length) { + var minParserItems = 1024; + var maxParserItems = 131072; + var bytesPerParserItem = 128; + function isASCIINumberBytes(buffer2, start) { + if (start >= buffer2.length) { return false; } - for (let i = start; i < buffer.length; i++) { - if (buffer[i] < 48 || buffer[i] > 57) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] < 48 || buffer2[i] > 57) { return false; } } return true; } - function isValidLastEventIdBytes(buffer, start) { - for (let i = start; i < buffer.length; i++) { - if (buffer[i] === 0) { + function isValidLastEventIdBytes(buffer2, start) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] === 0) { return false; } } @@ -18324,6 +18346,11 @@ var require_eventsource_stream = __commonJS({ } return true; } + function createMaxEventSizeExceededError() { + const error = new Error("EventSource message size exceeded"); + error.aborted = false; + return error; + } var EventSourceStream = class extends Transform { /** * @type {eventSourceSettings} @@ -18350,6 +18377,13 @@ var require_eventsource_stream = __commonJS({ pos = 0; lineChunkIndex = 0; linePos = 0; + lineLength = 0; + eventSize = 0; + eventFieldSizes = { data: 0, event: 0, id: 0, retry: 0 }; + dataLineCount = 0; + maxEventSize; + maxDataLines; + maxBufferedChunks; event = { data: void 0, event: void 0, @@ -18358,6 +18392,7 @@ var require_eventsource_stream = __commonJS({ }; /** * @param {object} options + * @param {number} [options.maxEventSize] * @param {eventSourceSettings} options.eventSourceSettings * @param {Function} [options.push] */ @@ -18365,6 +18400,10 @@ var require_eventsource_stream = __commonJS({ options.readableObjectMode = true; super(options); this.state = options.eventSourceSettings || {}; + this.maxEventSize = options.maxEventSize ?? defaultMaxEventSize; + const parserItemLimit = this.maxEventSize > 0 ? Math.min(maxParserItems, Math.max(minParserItems, Math.floor(this.maxEventSize / bytesPerParserItem))) : 0; + this.maxDataLines = parserItemLimit; + this.maxBufferedChunks = parserItemLimit; if (options.push) { this.push = options.push; } @@ -18380,6 +18419,10 @@ var require_eventsource_stream = __commonJS({ callback(); return; } + if (this.maxEventSize > 0 && this.chunks.length >= this.maxBufferedChunks && chunk[0] !== LF && chunk[0] !== CR) { + callback(createMaxEventSizeExceededError()); + return; + } this.chunks.push(chunk); if (this.checkBOM) { if (this.handleBOM()) { @@ -18416,18 +18459,32 @@ var require_eventsource_stream = __commonJS({ if (byte === CR) { this.crlfCheck = true; } - this.parseLine(this.readLine(), this.event); + try { + this.parseLine(this.readLine(), this.event); + } catch (error) { + callback(error); + return; + } this.consumeCurrentByte(); this.eventEndCheck = true; continue; } + if (this.maxEventSize > 0 && ++this.lineLength > this.maxEventSize + 7) { + callback(createMaxEventSizeExceededError()); + return; + } this.advanceCursor(); } callback(); } + _destroy(error, callback) { + this.chunks.length = 0; + this.clearEvent(); + super._destroy(error, callback); + } /** * @param {Buffer} line - * @param {EventStreamEvent} event + * @param {EventSourceStreamEvent} event */ parseLine(line, event) { if (line.length === 0) { @@ -18447,6 +18504,12 @@ var require_eventsource_stream = __commonJS({ } } if (isFieldName(line, fieldLength, DATA)) { + if (this.maxEventSize > 0 && this.dataLineCount >= this.maxDataLines) { + throw createMaxEventSizeExceededError(); + } + const valueBytes = line.length - valueStart; + const dataSize = this.eventFieldSizes.data + (event.data === void 0 ? 0 : 1) + valueBytes; + this.setEventFieldSize("data", dataSize); const value = line.toString("utf8", valueStart); if (event.data === void 0) { event.data = value; @@ -18454,27 +18517,38 @@ var require_eventsource_stream = __commonJS({ event.data += ` ${value}`; } + this.dataLineCount++; return; } if (isFieldName(line, fieldLength, RETRY)) { if (isASCIINumberBytes(line, valueStart)) { + this.setEventFieldSize("retry", line.length - valueStart); event.retry = line.toString("utf8", valueStart); } return; } if (isFieldName(line, fieldLength, ID)) { if (isValidLastEventIdBytes(line, valueStart)) { + this.setEventFieldSize("id", line.length - valueStart); event.id = line.toString("utf8", valueStart); } return; } if (isFieldName(line, fieldLength, EVENT)) { - const value = line.toString("utf8", valueStart); - if (value.length > 0) { - event.event = value; + if (valueStart < line.length) { + this.setEventFieldSize("event", line.length - valueStart); + event.event = line.toString("utf8", valueStart); } } } + setEventFieldSize(field, size) { + const eventSize = this.eventSize - this.eventFieldSizes[field] + size; + if (this.maxEventSize > 0 && eventSize > this.maxEventSize) { + throw createMaxEventSizeExceededError(); + } + this.eventSize = eventSize; + this.eventFieldSizes[field] = size; + } /** * @param {EventSourceStreamEvent} event */ @@ -18501,6 +18575,12 @@ ${value}`; this.event.event = void 0; this.event.id = void 0; this.event.retry = void 0; + this.eventSize = 0; + this.dataLineCount = 0; + this.eventFieldSizes.data = 0; + this.eventFieldSizes.event = 0; + this.eventFieldSizes.id = 0; + this.eventFieldSizes.retry = 0; } hasPendingEvent() { return this.event.data !== void 0 || this.event.event !== void 0 || this.event.id !== void 0 || this.event.retry !== void 0; @@ -18525,13 +18605,15 @@ ${value}`; syncLineStartToCursor() { this.lineChunkIndex = this.chunkIndex; this.linePos = this.pos; + this.lineLength = 0; this.dropConsumedChunks(); } dropConsumedChunks() { - while (this.lineChunkIndex > 0) { - this.chunks.shift(); - this.lineChunkIndex--; - this.chunkIndex--; + if (this.lineChunkIndex > 0) { + const consumed = this.lineChunkIndex; + this.chunks.splice(0, consumed); + this.lineChunkIndex = 0; + this.chunkIndex -= consumed; } if (this.chunkIndex === this.chunks.length) { this.chunks.length = 0; @@ -18634,6 +18716,7 @@ var require_eventsource = __commonJS({ var { delay } = require_util8(); var { kEnumerableProperty } = require_util(); var { environmentSettingsObject } = require_util2(); + var { getGlobalDispatcher } = require_global2(); var experimentalWarned = false; var defaultReconnectionTime = 3e3; var CONNECTING = 0; @@ -18774,6 +18857,7 @@ var require_eventsource = __commonJS({ this.#state.origin = response.urlList[response.urlList.length - 1].origin; const eventSourceStream = new EventSourceStream({ eventSourceSettings: this.#state, + maxEventSize: this.#dispatcher.eventSourceOptions?.maxEventSize, push: (event) => { this.dispatchEvent(createFastMessageEvent( event.type, @@ -18906,7 +18990,8 @@ var require_eventsource = __commonJS({ { key: "dispatcher", // undici only - converter: webidl.converters.any + converter: webidl.converters.any, + defaultValue: () => getGlobalDispatcher() } ]); module2.exports = { @@ -26011,6 +26096,7 @@ var require_symbols6 = __commonJS({ kDestroy: /* @__PURE__ */ Symbol("destroy"), kDispatch: /* @__PURE__ */ Symbol("dispatch"), kUrl: /* @__PURE__ */ Symbol("url"), + kRedirectCacheControl: /* @__PURE__ */ Symbol("redirect cache control"), kWriting: /* @__PURE__ */ Symbol("writing"), kResuming: /* @__PURE__ */ Symbol("resuming"), kQueue: /* @__PURE__ */ Symbol("queue"), @@ -27258,6 +27344,19 @@ var require_util10 = __commonJS({ } return ret; } + 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; + } function encodeRawHeaders(headers) { if (!Array.isArray(headers)) { throw new TypeError("expected headers to be an array"); @@ -27779,6 +27878,7 @@ var require_util10 = __commonJS({ removeAllListeners, errorRequest: errorRequest2, parseRawHeaders, + toRawHeaders, encodeRawHeaders, parseHeaders, parseKeepAliveTimeout, @@ -28164,7 +28264,7 @@ var require_request3 = __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; @@ -28675,6 +28775,7 @@ var require_unwrap_handler = __commonJS({ var require_dispatcher_base2 = __commonJS({ "node_modules/@octokit/action/node_modules/undici/lib/dispatcher/dispatcher-base.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var Dispatcher = require_dispatcher2(); var UnwrapHandler = require_unwrap_handler(); var { @@ -28686,6 +28787,7 @@ var require_dispatcher_base2 = __commonJS({ var kOnDestroyed = /* @__PURE__ */ Symbol("onDestroyed"); var kOnClosed = /* @__PURE__ */ Symbol("onClosed"); var kWebSocketOptions = /* @__PURE__ */ Symbol("webSocketOptions"); + var kEventSourceOptions = /* @__PURE__ */ Symbol("eventSourceOptions"); var DispatcherBase = class extends Dispatcher { /** @type {boolean} */ [kDestroyed] = false; @@ -28701,6 +28803,7 @@ var require_dispatcher_base2 = __commonJS({ constructor(opts) { super(); this[kWebSocketOptions] = opts?.webSocket ?? {}; + this[kEventSourceOptions] = opts?.eventSource ?? {}; } /** * @returns {import('../../types/dispatcher').WebSocketOptions} @@ -28712,6 +28815,14 @@ var require_dispatcher_base2 = __commonJS({ // 128 MB default }; } + /** + * @returns {import('../../types/client').Client.EventSourceOptions} + */ + get eventSourceOptions() { + return { + maxEventSize: this[kEventSourceOptions].maxEventSize ?? buffer.kStringMaxLength + }; + } /** @returns {boolean} */ get destroyed() { return this[kDestroyed]; @@ -28857,15 +28968,19 @@ var require_connect2 = __commonJS({ if (this._sessionCache.has(sessionKey)) { this._sessionCache.delete(sessionKey); } else if (this._sessionCache.size >= this._maxCachedSessions) { + let evicted = false; for (const [key, ref] of this._sessionCache) { if (ref.deref() === void 0) { this._sessionCache.delete(key); - return; + evicted = true; + break; } } - const oldest = this._sessionCache.keys().next(); - if (!oldest.done) { - this._sessionCache.delete(oldest.value); + if (!evicted) { + const oldest = this._sessionCache.keys().next(); + if (!oldest.done) { + this._sessionCache.delete(oldest.value); + } } } this._sessionCache.set(sessionKey, new WeakRef(session)); @@ -29924,6 +30039,10 @@ var require_infra = __commonJS({ return input.slice(start, position.position); } var ASCII_WHITESPACE_REPLACE_REGEX = /[\u0009\u000A\u000C\u000D\u0020]/g; + var nonASCIIRegex = /[^\x00-\x7F]/; + function asciiLowercase(str) { + return nonASCIIRegex.test(str) ? str.replace(/[A-Z]+/g, (upper) => upper.toLowerCase()) : str.toLowerCase(); + } function forgivingBase64(data) { data = data.replace(ASCII_WHITESPACE_REPLACE_REGEX, ""); let dataLength = data.length; @@ -29998,6 +30117,7 @@ var require_infra = __commonJS({ return result; } module2.exports = { + asciiLowercase, collectASequenceOfCodePoints, collectASequenceOfCodePointsFast, forgivingBase64, @@ -32307,19 +32427,38 @@ var require_body2 = __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 iterator2 = result?.[Symbol.asyncIterator]?.(); + if (iterator2 == 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 iterator2.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" }); @@ -32376,7 +32515,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r length = null; } source = object; - action = async function* () { + const parts = (async function* () { for (const part of blobParts) { if (part.stream) { yield* part.stream(); @@ -32384,7 +32523,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r yield part; } } - }; + })(); + action = () => parts; type = `multipart/form-data; boundary=${boundary}`; } else if (webidl.is.Blob(object)) { source = object; @@ -32404,28 +32544,8 @@ Content-Type: ${value.type || "application/octet-stream"}\r stream = webidl.is.ReadableStream(object) ? object : ReadableStreamFrom(object); } if (typeof source === "string" || isUint8Array(source)) { - action = () => { - length = typeof source === "string" ? Buffer.byteLength(source) : source.length; - return source; - }; - } - if (action != null) { - ; - (async () => { - const result = action(); - const iterator2 = result?.[Symbol.asyncIterator]?.(); - if (iterator2) { - for await (const bytes of iterator2) { - 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 = () => source; + length = typeof source === "string" ? Buffer.byteLength(source) : source.length; } const body = { stream, source, length }; return [body, type]; @@ -32618,6 +32738,7 @@ var require_client_h12 = __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_wasm2() : void 0; @@ -33277,7 +33398,6 @@ var require_client_h12 = __commonJS({ }; } function onHttpSocketError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); const parser = this[kParser]; if (err.code === "ECONNRESET" && parser.statusCode && !parser.shouldKeepAlive) { const parserErr = parser.finish(); @@ -33406,6 +33526,24 @@ var require_client_h12 = __commonJS({ function shouldSendContentLength(method) { return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT"; } + function setTypeOfService(socket, request2) { + if (typeof socket.setTypeOfService !== "function") { + return; + } + const typeOfService = request2.typeOfService; + if (typeOfService === void 0) { + return; + } + const currentTypeOfService = socket[kTypeOfService]; + if (currentTypeOfService === typeOfService) { + return; + } + try { + socket.setTypeOfService(typeOfService); + socket[kTypeOfService] = typeOfService; + } catch { + } + } function writeH1(client, request2) { const { method, path, host, upgrade, blocking, reset } = request2; let { body, headers, contentLength } = request2; @@ -33482,9 +33620,7 @@ var require_client_h12 = __commonJS({ if (blocking) { socket[kBlocking] = true; } - if (socket.setTypeOfService) { - socket.setTypeOfService(request2.typeOfService); - } + setTypeOfService(socket, request2); let header = `${method} ${path} HTTP/1.1\r `; if (typeof host === "string") { @@ -34057,7 +34193,6 @@ var require_client_h22 = __commonJS({ } } function onHttp2SessionError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kSocket][kError] = err; this[kClient][kOnError](err); } @@ -34147,7 +34282,6 @@ var require_client_h22 = __commonJS({ client[kResume](); } function onHttp2SocketError(err) { - assert(err.code !== "ERR_TLS_CERT_ALTNAME_INVALID"); this[kError] = err; this[kClient][kOnError](err); } @@ -34708,7 +34842,8 @@ var require_client2 = __commonJS({ initialWindowSize, connectionWindowSize, pingInterval, - webSocket + webSocket, + eventSource } = {}) { if (keepAlive !== void 0) { throw new InvalidArgumentError("unsupported keepAlive, use pipelining=0 instead"); @@ -34786,7 +34921,7 @@ var require_client2 = __commonJS({ if (pingInterval != null && (typeof pingInterval !== "number" || !Number.isInteger(pingInterval) || pingInterval < 0)) { throw new InvalidArgumentError("pingInterval must be a positive integer, greater or equal to 0"); } - super({ webSocket }); + super({ webSocket, eventSource }); if (typeof connect2 !== "function") { connect2 = buildConnector({ ...tls, @@ -35767,7 +35902,7 @@ var require_agent2 = __commonJS({ return opts && opts.connections === 1 ? new Client(origin, opts) : new Pool(origin, opts); } var Agent = class extends DispatcherBase { - constructor({ factory = defaultFactory, maxOrigins = Infinity, connect, ...options } = {}) { + constructor({ factory = defaultFactory, maxOrigins = Infinity, connect, tls, ...options } = {}) { if (typeof factory !== "function") { throw new InvalidArgumentError("factory must be a function."); } @@ -35781,7 +35916,10 @@ var require_agent2 = __commonJS({ if (connect && typeof connect !== "function") { connect = { ...connect }; } - this[kOptions] = { ...util.deepClone(options), maxOrigins, connect }; + if (tls && typeof tls !== "function") { + tls = { ...tls }; + } + this[kOptions] = { ...util.deepClone(options), maxOrigins, connect, tls }; this[kFactory] = factory; this[kClients] = /* @__PURE__ */ new Map(); this[kOrigins] = /* @__PURE__ */ new Set(); @@ -40645,7 +40783,7 @@ var require_redirect_handler2 = __commonJS({ "node_modules/@octokit/action/node_modules/undici/lib/handler/redirect-handler.js"(exports2, module2) { "use strict"; var util = require_util10(); - var { kBodyUsed } = require_symbols6(); + var { kBodyUsed, kRedirectCacheControl } = require_symbols6(); var assert = require("node:assert"); var { InvalidArgumentError } = require_errors3(); var EE = require("node:events"); @@ -40683,6 +40821,10 @@ var require_redirect_handler2 = __commonJS({ this.maxRedirections = maxRedirections; this.handler = handler2; this.history = []; + Object.defineProperty(this.history, kRedirectCacheControl, { + value: [], + enumerable: false + }); if (util.isStream(this.opts.body)) { if (util.bodyLength(this.opts.body) === 0) { this.opts.body.on("data", function() { @@ -40733,6 +40875,11 @@ var require_redirect_handler2 = __commonJS({ this.handler.onResponseStart?.(controller, statusCode, headers, statusMessage); return; } + 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; const redirectUrlString = `${origin}${path}`; @@ -40779,9 +40926,17 @@ var require_redirect_handler2 = __commonJS({ 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]); + if (headers.length > 0 && Array.isArray(headers[0])) { + for (const [key, value] of headers) { + if (!shouldRemoveHeader(key, removeContent, unknownOrigin)) { + ret.push(key, value); + } + } + } else { + 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") { @@ -41600,15 +41755,46 @@ var require_cache2 = __commonJS({ } else if (typeof opts.headers === "object") { 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)) { + 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)) { @@ -42434,6 +42620,7 @@ var require_cache_handler = __commonJS({ "node_modules/@octokit/action/node_modules/undici/lib/handler/cache-handler.js"(exports2, module2) { "use strict"; var util = require_util10(); + var { kRedirectCacheControl } = require_symbols6(); var { parseCacheControlHeader, hasInvalidCacheControlDirective, @@ -42445,6 +42632,13 @@ var require_cache_handler = __commonJS({ var { parseHttpDate } = require_date(); function noop4() { } + function sameOrigin(a, b) { + try { + return new URL(String(a)).origin === new URL(String(b)).origin; + } catch { + return String(a) === String(b); + } + } var HEURISTICALLY_CACHEABLE_STATUS_CODES = [ 200, 203, @@ -42463,6 +42657,7 @@ var require_cache_handler = __commonJS({ 206 ]; var MAX_RESPONSE_AGE = 2147483647e3; + var REVALIDATION_ONLY_RETENTION = 864e5; function trimOWS(value) { return value.replace(/^[\t ]+|[\t ]+$/g, ""); } @@ -42474,6 +42669,15 @@ var require_cache_handler = __commonJS({ } 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]; for (let i = 0; i < values.length; i++) { @@ -42535,6 +42739,9 @@ var require_cache_handler = __commonJS({ deleteLocationTargets(store, cacheKey, resHeaders.location); deleteLocationTargets(store, cacheKey, resHeaders["content-location"]); } + function requestCarriesCredentials(headers) { + return headers != null && (Object.hasOwn(headers, "authorization") || Object.hasOwn(headers, "cookie") || Object.hasOwn(headers, "proxy-authorization")); + } var CacheHandler = class { /** * @type {import('../../types/cache-interceptor.d.ts').default.CacheKey} @@ -42560,6 +42767,19 @@ var require_cache_handler = __commonJS({ * @type {import('node:stream').Writable | undefined} */ #writeStream; + /** + * The URLs visited while following redirects, shared by reference from the + * redirect handler through the request context. Carries the suppressed hops' + * 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 @@ -42575,6 +42795,10 @@ var require_cache_handler = __commonJS({ onRequestStart(controller, context) { this.#writeStream?.destroy(); this.#writeStream = void 0; + this.#replaying304 = false; + this.#suppress304End = false; + this.#pending304End = void 0; + this.#history = context?.history; this.#handler.onRequestStart?.(controller, context); } onRequestUpgrade(controller, statusCode, headers, socket) { @@ -42598,6 +42822,29 @@ var require_cache_handler = __commonJS({ invalidateUnsafeRequest(this.#store, this.#cacheKey, resHeaders); return downstreamOnHeaders(); } + if (this.#history && this.#history.length > 1 && requestCarriesCredentials(this.#cacheKey.headers)) { + return downstreamOnHeaders(); + } + if (this.#history && this.#history.length > 0) { + for (const hopUrl of this.#history) { + if (!sameOrigin(hopUrl.origin, this.#cacheKey.origin)) { + return downstreamOnHeaders(); + } + } + } + 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 + ) : void 0; + if (redirectHopInfo?.length > 0 && redirectPolicy === void 0) { + return downstreamOnHeaders(); + } const cacheControlHeader = resHeaders["cache-control"]; const cacheControlDirectives = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {}; if (revalidationResponseDisallowsCachedReuse(this.#cacheType, resHeaders, cacheControlDirectives)) { @@ -42617,7 +42864,6 @@ var require_cache_handler = __commonJS({ } return downstreamOnHeaders(); } - const now = Date.now(); const resAge = Object.hasOwn(resHeaders, "age") ? getAge(resHeaders.age) : void 0; if (resAge !== void 0 && resAge >= MAX_RESPONSE_AGE) { deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); @@ -42630,43 +42876,102 @@ var require_cache_handler = __commonJS({ } const apparentAge = resDate ? Math.max(0, now - resDate.getTime()) : 0; const currentAge = Math.max(apparentAge, resAge ?? 0); - const staleAt = determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives) ?? this.#cacheByDefault; - if (staleAt === void 0 || currentAge >= staleAt) { + const hasValidator = typeof resHeaders.etag === "string" && isEtagUsable(resHeaders.etag) || typeof resHeaders["last-modified"] === "string"; + const staleAt = determineStaleAt(this.#cacheType, now, resAge, resHeaders, resDate, cacheControlDirectives, hasValidator) ?? this.#cacheByDefault; + const revalidationOnly = staleAt === 0 && hasValidator; + if (staleAt === void 0 || currentAge >= staleAt && !revalidationOnly) { if (cacheControlHeader || staleAt !== void 0) { deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); } return downstreamOnHeaders(); } const baseTime = now - currentAge; - const absoluteStaleAt = staleAt + baseTime; - if (now >= absoluteStaleAt) { + let absoluteStaleAt = staleAt + baseTime; + if (redirectPolicy !== void 0) { + absoluteStaleAt = Math.min(absoluteStaleAt, redirectPolicy.staleAt); + } + if (now >= absoluteStaleAt && !revalidationOnly) { deleteCachedValueIfNotModified(statusCode, this.#store, this.#cacheKey); return downstreamOnHeaders(); } let varyDirectives; - if (this.#cacheKey.headers && resHeaders.vary) { - varyDirectives = parseVaryHeader(resHeaders.vary, this.#cacheKey.headers); - if (!varyDirectives) { - 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)) { + return downstreamOnHeaders(); + } + } + if (this.#cacheKey.headers) { + varyDirectives = parseVaryHeader(combinedVary, this.#cacheKey.headers); + if (!varyDirectives) { + return downstreamOnHeaders(); + } + } + } + let effectiveCacheControlDirectives = cacheControlDirectives; + if (redirectPolicy !== void 0) { + 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); const value = { statusCode, statusMessage, headers: strippedHeaders, vary: varyDirectives, - cacheControlDirectives, + cacheControlDirectives: effectiveCacheControlDirectives, cachedAt, staleAt: absoluteStaleAt, deleteAt }; if (statusCode === 304) { + this.#replaying304 = true; + let done = false; + const finish304 = () => { + if (done) { + return; + } + done = true; + this.#replaying304 = false; + if (this.#pending304End) { + const { controller: controller2, trailers } = this.#pending304End; + this.#pending304End = void 0; + this.#writeStream?.end(); + this.#handler.onResponseEnd?.(controller2, trailers); + } + }; + const failReplay = (err) => { + if (done) { + return; + } + done = true; + this.#replaying304 = false; + this.#suppress304End = true; + this.#pending304End = void 0; + this.#writeStream?.destroy(); + try { + this.#handler.onResponseError?.(controller, err); + } catch { + } + }; const handle304 = (cachedValue) => { if (!cachedValue) { - return downstreamOnHeaders(); + downstreamOnHeaders(); + finish304(); + return; } value.statusCode = cachedValue.statusCode; value.statusMessage = cachedValue.statusMessage; @@ -42676,39 +42981,57 @@ var require_cache_handler = __commonJS({ downstreamOnHeaders(); this.#writeStream = this.#store.createWriteStream(this.#cacheKey, value); if (!this.#writeStream || !cachedValue?.body) { + finish304(); return; } if (typeof cachedValue.body.values === "function") { const bodyIterator = cachedValue.body.values(); const streamCachedBody = () => { - for (const chunk of bodyIterator) { - const full = this.#writeStream.write(chunk) === false; - this.#handler.onResponseData?.(controller, chunk); - if (full) { - break; + if (done) { + return; + } + try { + for (const chunk of bodyIterator) { + const full = this.#writeStream?.write(chunk) === false; + this.#handler.onResponseData?.(controller, chunk); + if (full) { + return; + } } + finish304(); + } catch (err) { + failReplay(err); } }; this.#writeStream.on("error", function() { handler2.#writeStream = void 0; handler2.#store.delete(handler2.#cacheKey); + streamCachedBody(); }).on("drain", () => { streamCachedBody(); }).on("close", function() { if (handler2.#writeStream === this) { handler2.#writeStream = void 0; + streamCachedBody(); } }); streamCachedBody(); } else if (typeof cachedValue.body.on === "function") { 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 = void 0; this.#store.delete(this.#cacheKey); + finish304(); }); this.#writeStream.on("error", function() { handler2.#writeStream = void 0; @@ -42718,11 +43041,15 @@ var require_cache_handler = __commonJS({ handler2.#writeStream = void 0; } }); + } else { + finish304(); } }; const result = this.#store.get(this.#cacheKey); if (result && typeof result.then === "function") { - result.then(handle304); + result.then(handle304, () => handle304(void 0)).catch((err) => { + failReplay(err); + }); } else { handle304(result); } @@ -42753,10 +43080,20 @@ var require_cache_handler = __commonJS({ this.#handler.onResponseData?.(controller, chunk); } 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 = void 0; this.#writeStream?.destroy(err); this.#writeStream = void 0; this.#handler.onResponseError?.(controller, err); @@ -42812,6 +43149,74 @@ var require_cache_handler = __commonJS({ } return true; } + 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 === void 0 || hopPolicy.staleAt <= now) { + return void 0; + } + staleAt = Math.min(staleAt, hopPolicy.staleAt); + requiresRevalidation ||= hopPolicy.requiresRevalidation; + } + return { staleAt, requiresRevalidation }; + } + function getRedirectHopPolicy(cacheType, method, hop, reqHeaders, cacheByDefault) { + if (!Number.isInteger(hop?.statusCode) || !Number.isFinite(hop?.receivedAt)) { + return void 0; + } + const hopHeaders = hop.headers ?? {}; + const cacheControlHeader = hopHeaders["cache-control"]; + const hopCacheControl = cacheControlHeader ? parseCacheControlHeader(cacheControlHeader) : {}; + if (hopHeaders.vary && hasVaryStar(hopHeaders.vary)) { + return void 0; + } + if (hopCacheControl["no-store"] === true) { + return void 0; + } + if (cacheType === "shared" && Object.hasOwn(hopCacheControl, "private")) { + return void 0; + } + if (Object.hasOwn(hopCacheControl, "no-cache") || hopCacheControl["must-revalidate"] === true || cacheType === "shared" && hopCacheControl["proxy-revalidate"] === true) { + return void 0; + } + const heuristicallyCacheable = hopHeaders["last-modified"] && arrayIncludes(HEURISTICALLY_CACHEABLE_STATUS_CODES, hop.statusCode); + if (!cacheControlHeader && !hopHeaders.expires && !heuristicallyCacheable && !cacheByDefault) { + return void 0; + } + if (!canCacheResponse(cacheType, method, hop.statusCode, hopHeaders, hopCacheControl, reqHeaders)) { + return void 0; + } + const age = Object.hasOwn(hopHeaders, "age") ? getAge(hopHeaders.age) : void 0; + if (age !== void 0 && age >= MAX_RESPONSE_AGE) { + return void 0; + } + const responseDate = Object.hasOwn(hopHeaders, "date") ? getDate(hopHeaders.date) : void 0; + if (responseDate === null) { + return void 0; + } + 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 === void 0) { + return void 0; + } + 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") + }; + } function getDate(dateHeader) { let dateValue = dateHeader; if (Array.isArray(dateValue)) { @@ -42842,7 +43247,7 @@ var require_cache_handler = __commonJS({ } return Number(age) * 1e3; } - function determineStaleAt(cacheType, now, age, resHeaders, responseDate, cacheControlDirectives) { + function determineStaleAt(cacheType, now, age, resHeaders, responseDate, cacheControlDirectives, hasValidator) { if (cacheType === "shared") { if (hasInvalidCacheControlDirective(cacheControlDirectives, "s-maxage")) { return 0; @@ -42895,6 +43300,9 @@ var require_cache_handler = __commonJS({ if (cacheControlDirectives.immutable) { return 31536e6; } + if (cacheControlDirectives["no-cache"] === true && hasValidator) { + return 0; + } return void 0; } function determineDeleteAt(baseTime, cachedAt, cacheControlDirectives, staleAt) { @@ -42912,6 +43320,9 @@ var require_cache_handler = __commonJS({ } if (staleWhileRevalidate === -Infinity && staleIfError === -Infinity && immutable === -Infinity) { const freshnessLifetime = staleAt - baseTime; + if (freshnessLifetime <= 0) { + return cachedAt + REVALIDATION_ONLY_RETENTION; + } const datePrecisionPadding = Math.min(Math.max(cachedAt - baseTime, 0), 1e3); return staleAt + freshnessLifetime + datePrecisionPadding; } @@ -43257,7 +43668,16 @@ var require_cache3 = __commonJS({ var CacheHandler = require_cache_handler(); var MemoryCacheStore = require_memory_cache_store(); var CacheRevalidationHandler = require_cache_revalidation_handler(); - var { assertCacheStore, assertCacheMethods, makeCacheKey, normalizeHeaders, parseCacheControlHeader, isInvalidOrWildcardVaryHeader } = require_cache2(); + var { + assertCacheStore, + assertCacheMethods, + makeCacheKey, + normalizeHeaders, + parseCacheControlHeader, + isInvalidOrWildcardVaryHeader, + parseVaryHeader, + isEtagUsable + } = require_cache2(); var { AbortError } = require_errors3(); var { parseHttpDate } = require_date(); function assertCacheOrigins(origins, name) { @@ -43336,6 +43756,17 @@ var require_cache3 = __commonJS({ function revalidationResponseUpdatesCacheControl(headers) { return headers["cache-control"] !== void 0; } + 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); @@ -43365,6 +43796,34 @@ var require_cache3 = __commonJS({ } 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; + } function isStale(result, cacheControlDirectives, cacheType) { const now = Date.now(); if (now > result.staleAt) { @@ -43446,18 +43905,23 @@ var require_cache3 = __commonJS({ }; stream.on("error", function(err) { if (!this.readableEnded) { - if (typeof handler2.onResponseError === "function") { - handler2.onResponseError(controller, err); - } else { - throw err; - } + handler2.onResponseError?.(controller, err); } }).on("close", function() { if (!this.errored) { - handler2.onResponseEnd?.(controller, {}); + try { + handler2.onResponseEnd?.(controller, {}); + } catch (err) { + handler2.onResponseError?.(controller, err); + } } }); - handler2.onRequestStart?.(controller, context); + try { + handler2.onRequestStart?.(controller, context); + } catch (err) { + stream.destroy(err); + return; + } if (stream.destroyed) { return; } @@ -43465,12 +43929,22 @@ var require_cache3 = __commonJS({ if (isStale2) { headers.warning = '110 - "response is stale"'; } - handler2.onResponseStart?.(controller, result.statusCode, headers, result.statusMessage); + controller.rawHeaders = util.toRawHeaders(headers); + try { + handler2.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) { - handler2.onResponseData?.(controller, chunk); + try { + handler2.onResponseData?.(controller, chunk); + } catch (err) { + stream.destroy(err); + } }); } } @@ -43533,6 +44007,13 @@ var require_cache3 = __commonJS({ } } 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, handler2)); + }; return dispatch( { ...opts, @@ -43542,15 +44023,13 @@ var require_cache3 = __commonJS({ (success, context, statusCode, headers2) => { if (success) { if (statusCode === 304) { - if (revalidationResponseDisallowsCachedReuse(globalOpts.type, headers2)) { - if (util.isStream(result.body)) { - result.body.on("error", nop).destroy(); - } - deleteCachedValue(globalOpts.store, cacheKey); - return dispatch(opts, new CacheHandler(globalOpts, cacheKey, handler2)); + if (!revalidationTargetMatchesCacheKey(cacheKey, context) || !revalidationEtagMatchesCachedValue(result, headers2) || revalidationResponseDisallowsCachedReuse(globalOpts.type, headers2)) { + return refetch(); } if (revalidationResponseUpdatesCacheControl(headers2)) { deleteCachedValue(globalOpts.store, cacheKey); + } else if (revalidationResponseAddsVary(result, headers2.vary ? parseVaryHeader(headers2.vary, opts.headers) : void 0)) { + return refetch(); } } sendCachedValue(handler2, opts, result, age, context, stale); @@ -43647,7 +44126,31 @@ var require_cache3 = __commonJS({ opts2, reqCacheControl, result2 - )); + )).catch((err) => { + if (typeof handler2.onResponseError === "function") { + handler2.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, @@ -43861,9 +44364,14 @@ var require_decompress = __commonJS({ } this.#decompressedSize = decompressedSize; } - const result = super.onResponseData(this.#controller, chunk); - if (result === false && !this.#controller.paused) { - this.#controller.pause(); + try { + const result = super.onResponseData(this.#controller, chunk); + if (result === false && !this.#controller.paused) { + this.#controller.pause(); + } + } catch (err) { + this.#fail(err); + return; } } } while (this.#drainRequested && !this.#terminated && !this.#controller.paused); @@ -43877,9 +44385,14 @@ var require_decompress = __commonJS({ if (this.#terminated || !this.#completionPending || this.#controller.paused || this.#draining) { return; } - this.#terminated = true; this.#cleanupDecompressors(); - super.onResponseEnd(this.#controller, this.#trailers); + try { + super.onResponseEnd(this.#controller, this.#trailers); + } catch (err) { + this.#fail(err); + return; + } + this.#terminated = true; } #onDecompressionEnd() { if (this.#terminated) { @@ -44024,7 +44537,8 @@ var require_decompress = __commonJS({ * @returns {void} */ onResponseStart(controller, statusCode, headers, statusMessage) { - const contentEncoding = headers["content-encoding"]; + const rawContentEncoding = headers["content-encoding"]; + const contentEncoding = Array.isArray(rawContentEncoding) ? rawContentEncoding.join(",") : rawContentEncoding; if (this.#shouldSkipDecompression(contentEncoding, statusCode)) { return super.onResponseStart(this.#controller, statusCode, headers, statusMessage); } @@ -44142,6 +44656,18 @@ var require_deduplication_handler = __commonJS({ * @type {DispatchHandler} */ #primaryHandler; + /** + * Whether the primary request has started (onRequestStart received). Until + * then the request context is unknown and cannot be given to waiting handlers. + * @type {boolean} + */ + #requestStarted = false; + /** + * The primary request context, replayed to waiting handlers so they observe + * the same redirect history as the primary. + * @type {any} + */ + #context = null; /** * @type {WaitingHandler[]} */ @@ -44210,18 +44736,22 @@ var require_deduplication_handler = __commonJS({ const waitingHandler = this.#createWaitingHandler(handler2); const waitingController = waitingHandler.controller; try { - handler2.onRequestStart?.(waitingController, null); - if (waitingController.aborted) { - waitingHandler.done = true; - return true; - } - if (this.#responseStarted) { - handler2.onResponseStart?.( - waitingController, - this.#statusCode, - this.#headers, - this.#statusMessage - ); + if (this.#requestStarted) { + handler2.onRequestStart?.(waitingController, this.#context); + if (waitingController.aborted) { + waitingHandler.done = true; + return true; + } + if (this.#responseStarted) { + handler2.onResponseStart?.( + waitingController, + this.#statusCode, + this.#headers, + this.#statusMessage + ); + } + } else { + waitingHandler.pendingStart = true; } } catch { waitingHandler.done = true; @@ -44238,6 +44768,21 @@ var require_deduplication_handler = __commonJS({ */ onRequestStart(controller, context) { this.#controller = controller; + if (!this.#requestStarted) { + this.#requestStarted = true; + this.#context = context; + for (const waitingHandler of this.#waitingHandlers) { + if (waitingHandler.pendingStart && !waitingHandler.done && !waitingHandler.controller.aborted) { + waitingHandler.pendingStart = false; + try { + waitingHandler.handler.onRequestStart?.(waitingHandler.controller, context); + } catch { + waitingHandler.done = true; + } + } + } + this.#pruneDoneWaitingHandlers(); + } this.#primaryHandler.onRequestStart?.(controller, context); } /** @@ -44375,7 +44920,8 @@ var require_deduplication_handler = __commonJS({ bufferedChunks: [], bufferedBytes: 0, pendingTrailers: null, - done: false + done: false, + pendingStart: false }; const state = { aborted: false, @@ -44582,7 +45128,7 @@ var require_sqlite_cache_store = __commonJS({ var { Writable } = require("node:stream"); var { assertCacheKey, assertCacheValue } = require_cache2(); var DatabaseSync; - var VERSION10 = 3; + var VERSION10 = 4; var MAX_ENTRY_SIZE = 2 * 1e3 * 1e3 * 1e3; module2.exports = class SqliteCacheStore { #maxEntrySize = MAX_ENTRY_SIZE; @@ -46584,6 +47130,7 @@ var require_subresource_integrity = __commonJS({ "use strict"; var assert = require("node:assert"); var { runtimeFeatures } = require_runtime_features(); + var { asciiLowercase } = require_infra(); var validSRIHashAlgorithmTokenSet = /* @__PURE__ */ new Map([["sha256", 0], ["sha384", 1], ["sha512", 2]]); var crypto; if (runtimeFeatures.has("crypto")) { @@ -46606,10 +47153,7 @@ var require_subresource_integrity = __commonJS({ validSRIHashAlgorithmTokenSet ) ); - var isValidSRIHashAlgorithm = ( - /** @type {IsValidSRIHashAlgorithm} */ - Map.prototype.has.bind(validSRIHashAlgorithmTokenSet) - ); + var isValidSRIHashAlgorithm = (algorithm) => validSRIHashAlgorithmTokenSet.has(asciiLowercase(algorithm)); var bytesMatch = runtimeFeatures.has("crypto") === false || validSRIHashAlgorithmTokenSet.size === 0 ? () => true : (bytes, metadataList) => { const parsedMetadata = parseMetadata(metadataList); if (parsedMetadata.length === 0) { @@ -46657,7 +47201,7 @@ var require_subresource_integrity = __commonJS({ } 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 = ""; @@ -46670,7 +47214,8 @@ var require_subresource_integrity = __commonJS({ base64Value = algorithmAndValue[1]; } const metadata2 = { - alg: algorithm, + // Possible spec bug? + alg: asciiLowercase(algorithm), val: base64Value }; result.push(metadata2); @@ -47719,7 +48264,6 @@ var require_fetch2 = __commonJS({ } } const location = headersList.get("location", true); - this.body = new Readable({ read: resume }); const willFollow = location && request2.redirect === "follow" && redirectStatusSet.has(status); const decoders = []; if (request2.method !== "HEAD" && request2.method !== "CONNECT" && !nullBodyStatus.includes(status) && !willFollow) { @@ -47727,7 +48271,7 @@ var require_fetch2 = __commonJS({ const codings = contentEncoding ? contentEncoding.toLowerCase().split(",") : []; const maxContentEncodings = 5; if (codings.length > maxContentEncodings) { - reject(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); + this.abort(new Error(`too many content-encodings in response: ${codings.length}, maximum allowed is ${maxContentEncodings}`)); return true; } for (let i = codings.length - 1; i >= 0; --i) { @@ -47762,6 +48306,7 @@ var require_fetch2 = __commonJS({ } } } + this.body = new Readable({ read: resume }); const onError = this.onError.bind(this); resolve({ status, @@ -48741,8 +49286,12 @@ var require_util13 = __commonJS({ validateCookiePath(cookie.path); out.push(`Path=${cookie.path}`); } - if (cookie.expires && cookie.expires.toString() !== "Invalid Date") { - out.push(`Expires=${toIMFDate(cookie.expires)}`); + if (cookie.expires != null) { + const expiresMs = cookie.expires instanceof Date ? cookie.expires.getTime() : cookie.expires; + const maxTimeValue = 864e13; + if (typeof expiresMs === "number" && Number.isFinite(expiresMs) && Math.abs(expiresMs) <= maxTimeValue) { + out.push(`Expires=${toIMFDate(cookie.expires)}`); + } } if (cookie.sameSite) { out.push(`SameSite=${cookie.sameSite}`); @@ -48817,88 +49366,89 @@ var require_parse2 = __commonJS({ }; } function parseUnparsedAttributes(unparsedAttributes, cookieAttributeList = {}) { - if (unparsedAttributes.length === 0) { - return cookieAttributeList; - } - assert(unparsedAttributes[0] === ";"); - unparsedAttributes = unparsedAttributes.slice(1); - let cookieAv = ""; - if (unparsedAttributes.includes(";")) { - cookieAv = collectASequenceOfCodePointsFast( - ";", - unparsedAttributes, - { position: 0 } - ); - unparsedAttributes = unparsedAttributes.slice(cookieAv.length); - } else { - cookieAv = unparsedAttributes; - unparsedAttributes = ""; - } - let attributeName = ""; - let attributeValue = ""; - if (cookieAv.includes("=")) { - const position = { position: 0 }; - attributeName = collectASequenceOfCodePointsFast( - "=", - cookieAv, - position - ); - attributeValue = cookieAv.slice(position.position + 1); - } else { - attributeName = cookieAv; - } - attributeName = attributeName.trim(); - attributeValue = attributeValue.trim(); - if (attributeValue.length > maxAttributeValueSize) { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); - } - const attributeNameLowercase = attributeName.toLowerCase(); - if (attributeNameLowercase === "expires") { - const expiryTime = new Date(attributeValue); - cookieAttributeList.expires = expiryTime; - } else if (attributeNameLowercase === "max-age") { - const charCode = attributeValue.charCodeAt(0); - if ((charCode < 48 || charCode > 57) && attributeValue[0] !== "-") { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); - } - if (!/^\d+$/.test(attributeValue)) { - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); + while (true) { + if (unparsedAttributes.length === 0) { + return cookieAttributeList; + } + assert(unparsedAttributes[0] === ";"); + unparsedAttributes = unparsedAttributes.slice(1); + let cookieAv = ""; + if (unparsedAttributes.includes(";")) { + cookieAv = collectASequenceOfCodePointsFast( + ";", + unparsedAttributes, + { position: 0 } + ); + unparsedAttributes = unparsedAttributes.slice(cookieAv.length); + } else { + cookieAv = unparsedAttributes; + unparsedAttributes = ""; + } + let attributeName = ""; + let attributeValue = ""; + if (cookieAv.includes("=")) { + const position = { position: 0 }; + attributeName = collectASequenceOfCodePointsFast( + "=", + cookieAv, + position + ); + attributeValue = cookieAv.slice(position.position + 1); + } else { + attributeName = cookieAv; } - const deltaSeconds = Number(attributeValue); - cookieAttributeList.maxAge = deltaSeconds; - } else if (attributeNameLowercase === "domain") { - let cookieDomain = attributeValue; - if (cookieDomain[0] === ".") { - cookieDomain = cookieDomain.slice(1); + attributeName = attributeName.trim(); + attributeValue = attributeValue.trim(); + if (attributeValue.length > maxAttributeValueSize) { + continue; } - cookieDomain = cookieDomain.toLowerCase(); - cookieAttributeList.domain = cookieDomain; - } else if (attributeNameLowercase === "path") { - let cookiePath = ""; - if (attributeValue.length === 0 || attributeValue[0] !== "/") { - cookiePath = "/"; + const attributeNameLowercase = attributeName.toLowerCase(); + if (attributeNameLowercase === "expires") { + const expiryTime = new Date(attributeValue); + cookieAttributeList.expires = expiryTime; + } else if (attributeNameLowercase === "max-age") { + const charCode = attributeValue.charCodeAt(0); + if ((charCode < 48 || charCode > 57) && attributeValue[0] !== "-") { + continue; + } + if (!/^\d+$/.test(attributeValue)) { + continue; + } + const deltaSeconds = Number(attributeValue); + cookieAttributeList.maxAge = deltaSeconds; + } else if (attributeNameLowercase === "domain") { + let cookieDomain = attributeValue; + if (cookieDomain[0] === ".") { + cookieDomain = cookieDomain.slice(1); + } + cookieDomain = cookieDomain.toLowerCase(); + cookieAttributeList.domain = cookieDomain; + } else if (attributeNameLowercase === "path") { + let cookiePath = ""; + if (attributeValue.length === 0 || attributeValue[0] !== "/") { + cookiePath = "/"; + } else { + cookiePath = attributeValue; + } + cookieAttributeList.path = cookiePath; + } else if (attributeNameLowercase === "secure") { + cookieAttributeList.secure = true; + } else if (attributeNameLowercase === "httponly") { + cookieAttributeList.httpOnly = true; + } else if (attributeNameLowercase === "samesite") { + const attributeValueLowercase = attributeValue.toLowerCase(); + if (attributeValueLowercase === "none") { + cookieAttributeList.sameSite = "None"; + } else if (attributeValueLowercase === "strict") { + cookieAttributeList.sameSite = "Strict"; + } else if (attributeValueLowercase === "lax") { + cookieAttributeList.sameSite = "Lax"; + } } else { - cookiePath = attributeValue; + cookieAttributeList.unparsed ??= []; + cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`); } - cookieAttributeList.path = cookiePath; - } else if (attributeNameLowercase === "secure") { - cookieAttributeList.secure = true; - } else if (attributeNameLowercase === "httponly") { - cookieAttributeList.httpOnly = true; - } else if (attributeNameLowercase === "samesite") { - const attributeValueLowercase = attributeValue.toLowerCase(); - if (attributeValueLowercase === "none") { - cookieAttributeList.sameSite = "None"; - } else if (attributeValueLowercase === "strict") { - cookieAttributeList.sameSite = "Strict"; - } else if (attributeValueLowercase === "lax") { - cookieAttributeList.sameSite = "Lax"; - } - } else { - cookieAttributeList.unparsed ??= []; - cookieAttributeList.unparsed.push(`${attributeName}=${attributeValue}`); } - return parseUnparsedAttributes(unparsedAttributes, cookieAttributeList); } module2.exports = { parseSetCookie, @@ -48920,7 +49470,7 @@ var require_cookies2 = __commonJS({ webidl.argumentLengthCheck(arguments, 1, "getCookies"); brandChecks(headers); const cookie = headers.get("cookie"); - const out = {}; + const out = { __proto__: null }; if (!cookie) { return out; } @@ -50069,6 +50619,15 @@ var require_receiver2 = __commonJS({ if (isControlFrame(this.#info.opcode)) { this.#loop = this.parseControlFrame(body); this.#state = parserStates.INFO; + if (this.#loop && this.#handler.socket.writableNeedDrain) { + this.#loop = false; + this.#handler.socket.once("drain", () => { + if (this.destroyed) return; + this.#loop = true; + this.run(callback); + }); + return; + } } else { if (!this.#info.compressed) { if (!this.writeFragments(body)) { @@ -51244,6 +51803,7 @@ var require_util15 = __commonJS({ var require_eventsource_stream2 = __commonJS({ "node_modules/@octokit/action/node_modules/undici/lib/web/eventsource/eventsource-stream.js"(exports2, module2) { "use strict"; + var buffer = require("node:buffer"); var { Transform } = require("node:stream"); var { isASCIINumber, isValidLastEventId } = require_util15(); var BOM = [239, 187, 191]; @@ -51251,24 +51811,28 @@ var require_eventsource_stream2 = __commonJS({ var CR = 13; var COLON = 58; var SPACE = 32; + var defaultMaxEventSize = buffer.kStringMaxLength; var DATA = Buffer.from("data"); var EVENT = Buffer.from("event"); var ID = Buffer.from("id"); var RETRY = Buffer.from("retry"); - function isASCIINumberBytes(buffer, start) { - if (start >= buffer.length) { + var minParserItems = 1024; + var maxParserItems = 131072; + var bytesPerParserItem = 128; + function isASCIINumberBytes(buffer2, start) { + if (start >= buffer2.length) { return false; } - for (let i = start; i < buffer.length; i++) { - if (buffer[i] < 48 || buffer[i] > 57) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] < 48 || buffer2[i] > 57) { return false; } } return true; } - function isValidLastEventIdBytes(buffer, start) { - for (let i = start; i < buffer.length; i++) { - if (buffer[i] === 0) { + function isValidLastEventIdBytes(buffer2, start) { + for (let i = start; i < buffer2.length; i++) { + if (buffer2[i] === 0) { return false; } } @@ -51285,6 +51849,11 @@ var require_eventsource_stream2 = __commonJS({ } return true; } + function createMaxEventSizeExceededError() { + const error = new Error("EventSource message size exceeded"); + error.aborted = false; + return error; + } var EventSourceStream = class extends Transform { /** * @type {eventSourceSettings} @@ -51311,6 +51880,13 @@ var require_eventsource_stream2 = __commonJS({ pos = 0; lineChunkIndex = 0; linePos = 0; + lineLength = 0; + eventSize = 0; + eventFieldSizes = { data: 0, event: 0, id: 0, retry: 0 }; + dataLineCount = 0; + maxEventSize; + maxDataLines; + maxBufferedChunks; event = { data: void 0, event: void 0, @@ -51320,6 +51896,7 @@ var require_eventsource_stream2 = __commonJS({ /** * @param {object} options * @param {boolean} [options.readableObjectMode] + * @param {number} [options.maxEventSize] * @param {eventSourceSettings} [options.eventSourceSettings] * @param {(chunk: any, encoding?: BufferEncoding | undefined) => boolean} [options.push] */ @@ -51327,6 +51904,10 @@ var require_eventsource_stream2 = __commonJS({ options.readableObjectMode = true; super(options); this.state = options.eventSourceSettings || {}; + this.maxEventSize = options.maxEventSize ?? defaultMaxEventSize; + const parserItemLimit = this.maxEventSize > 0 ? Math.min(maxParserItems, Math.max(minParserItems, Math.floor(this.maxEventSize / bytesPerParserItem))) : 0; + this.maxDataLines = parserItemLimit; + this.maxBufferedChunks = parserItemLimit; if (options.push) { this.push = options.push; } @@ -51342,6 +51923,10 @@ var require_eventsource_stream2 = __commonJS({ callback(); return; } + if (this.maxEventSize > 0 && this.chunks.length >= this.maxBufferedChunks && chunk[0] !== LF && chunk[0] !== CR) { + callback(createMaxEventSizeExceededError()); + return; + } this.chunks.push(chunk); if (this.checkBOM) { if (this.handleBOM()) { @@ -51378,15 +51963,29 @@ var require_eventsource_stream2 = __commonJS({ if (byte === CR) { this.crlfCheck = true; } - this.parseLine(this.readLine(), this.event); + try { + this.parseLine(this.readLine(), this.event); + } catch (error) { + callback(error); + return; + } this.consumeCurrentByte(); this.eventEndCheck = true; continue; } + if (this.maxEventSize > 0 && ++this.lineLength > this.maxEventSize + 7) { + callback(createMaxEventSizeExceededError()); + return; + } this.advanceCursor(); } callback(); } + _destroy(error, callback) { + this.chunks.length = 0; + this.clearEvent(); + super._destroy(error, callback); + } /** * @param {Buffer} line * @param {EventSourceStreamEvent} event @@ -51409,6 +52008,12 @@ var require_eventsource_stream2 = __commonJS({ } } if (isFieldName(line, fieldLength, DATA)) { + if (this.maxEventSize > 0 && this.dataLineCount >= this.maxDataLines) { + throw createMaxEventSizeExceededError(); + } + const valueBytes = line.length - valueStart; + const dataSize = this.eventFieldSizes.data + (event.data === void 0 ? 0 : 1) + valueBytes; + this.setEventFieldSize("data", dataSize); const value = line.toString("utf8", valueStart); if (event.data === void 0) { event.data = value; @@ -51416,27 +52021,38 @@ var require_eventsource_stream2 = __commonJS({ event.data += ` ${value}`; } + this.dataLineCount++; return; } if (isFieldName(line, fieldLength, RETRY)) { if (isASCIINumberBytes(line, valueStart)) { + this.setEventFieldSize("retry", line.length - valueStart); event.retry = line.toString("utf8", valueStart); } return; } if (isFieldName(line, fieldLength, ID)) { if (isValidLastEventIdBytes(line, valueStart)) { + this.setEventFieldSize("id", line.length - valueStart); event.id = line.toString("utf8", valueStart); } return; } if (isFieldName(line, fieldLength, EVENT)) { - const value = line.toString("utf8", valueStart); - if (value.length > 0) { - event.event = value; + if (valueStart < line.length) { + this.setEventFieldSize("event", line.length - valueStart); + event.event = line.toString("utf8", valueStart); } } } + setEventFieldSize(field, size) { + const eventSize = this.eventSize - this.eventFieldSizes[field] + size; + if (this.maxEventSize > 0 && eventSize > this.maxEventSize) { + throw createMaxEventSizeExceededError(); + } + this.eventSize = eventSize; + this.eventFieldSizes[field] = size; + } /** * @param {EventSourceStreamEvent} event */ @@ -51463,6 +52079,12 @@ ${value}`; this.event.event = void 0; this.event.id = void 0; this.event.retry = void 0; + this.eventSize = 0; + this.dataLineCount = 0; + this.eventFieldSizes.data = 0; + this.eventFieldSizes.event = 0; + this.eventFieldSizes.id = 0; + this.eventFieldSizes.retry = 0; } hasPendingEvent() { return this.event.data !== void 0 || this.event.event !== void 0 || this.event.id !== void 0 || this.event.retry !== void 0; @@ -51487,13 +52109,15 @@ ${value}`; syncLineStartToCursor() { this.lineChunkIndex = this.chunkIndex; this.linePos = this.pos; + this.lineLength = 0; this.dropConsumedChunks(); } dropConsumedChunks() { - while (this.lineChunkIndex > 0) { - this.chunks.shift(); - this.lineChunkIndex--; - this.chunkIndex--; + if (this.lineChunkIndex > 0) { + const consumed = this.lineChunkIndex; + this.chunks.splice(0, consumed); + this.lineChunkIndex = 0; + this.chunkIndex -= consumed; } if (this.chunkIndex === this.chunks.length) { this.chunks.length = 0; @@ -51595,6 +52219,7 @@ var require_eventsource2 = __commonJS({ var { isNetworkError } = require_response2(); var { kEnumerableProperty } = require_util10(); var { environmentSettingsObject } = require_util11(); + var { getGlobalDispatcher } = require_global4(); var experimentalWarned = false; var defaultReconnectionTime = 3e3; var CONNECTING = 0; @@ -51736,6 +52361,7 @@ var require_eventsource2 = __commonJS({ this.#state.origin = response.urlList[response.urlList.length - 1].origin; const eventSourceStream = new EventSourceStream({ eventSourceSettings: this.#state, + maxEventSize: this.#dispatcher.eventSourceOptions?.maxEventSize, push: (event) => { this.dispatchEvent(createFastMessageEvent( event.type, @@ -51872,7 +52498,8 @@ var require_eventsource2 = __commonJS({ { key: "dispatcher", // undici only - converter: webidl.converters.any + converter: webidl.converters.any, + defaultValue: () => getGlobalDispatcher() }, { key: "node", diff --git a/package-lock.json b/package-lock.json index 391efebd..172a3ec3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -983,9 +983,9 @@ } }, "node_modules/@octokit/action/node_modules/undici": { - "version": "7.30.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.30.0.tgz", - "integrity": "sha512-dkrQXeHSaoamnItlYbmzG0wFYrM0ZwDxCIg0A7aKjTyyhh9svRzCNFEzV+Vm05/yehjCzjDZ31KXfGEjYSztDQ==", + "version": "7.30.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.30.2.tgz", + "integrity": "sha512-mLyPQnHwUxaM/rideoK/+KL8DaAJLRl4aBCfmX444aCSLnIaomqPLtNRe2jdCYcsk5wZzXrDIQC8ZeYNRAYyIA==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -7377,9 +7377,9 @@ } }, "node_modules/undici": { - "version": "6.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.29.0.tgz", - "integrity": "sha512-R+RODBqp6i2pPflGdq+xIOUkl+RNfGgHwoinecKu/JCuf2uO06cOKoDbI2P7Dn6KcswdKwrczbU6IYJ6K8X+wg==", + "version": "6.29.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.29.1.tgz", + "integrity": "sha512-EvRlUt/QqAEvXdQeRMYUfwOQsfzpDztykrG2owGEE/rBOBoYv9uF39ZzsNDh4lTFHhTr2XOZjKkYgueD12ZmGA==", "license": "MIT", "engines": { "node": ">=18.17"