import { B as BROWSER } from "./chunks/index.js"; import { a as assets, b as base, o as override, r as reset, c as app_dir } from "./chunks/paths.js"; import * as devalue from "devalue"; import { m as make_trackable, d as disable_search, a as decode_params, v as validate_layout_server_exports, b as validate_layout_exports, c as validate_page_server_exports, e as validate_page_exports, n as normalize_path, r as resolve, f as decode_pathname, g as validate_server_exports } from "./chunks/exports.js"; import { r as readable, w as writable } from "./chunks/index2.js"; import { p as public_env, s as safe_public_env, r as read_implementation, o as options, a as set_private_env, b as prerendering, c as set_public_env, g as get_hooks, d as set_safe_public_env, e as set_read_implementation } from "./chunks/internal.js"; import { parse, serialize } from "cookie"; import * as set_cookie_parser from "set-cookie-parser"; const SVELTE_KIT_ASSETS = "/_svelte_kit_assets"; const ENDPOINT_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD"]; const PAGE_METHODS = ["GET", "POST", "HEAD"]; function negotiate(accept, types) { const parts = []; accept.split(",").forEach((str, i) => { const match = /([^/ \t]+)\/([^; \t]+)[ \t]*(?:;[ \t]*q=([0-9.]+))?/.exec(str); if (match) { const [, type, subtype, q = "1"] = match; parts.push({ type, subtype, q: +q, i }); } }); parts.sort((a, b) => { if (a.q !== b.q) { return b.q - a.q; } if (a.subtype === "*" !== (b.subtype === "*")) { return a.subtype === "*" ? 1 : -1; } if (a.type === "*" !== (b.type === "*")) { return a.type === "*" ? 1 : -1; } return a.i - b.i; }); let accepted; let min_priority = Infinity; for (const mimetype of types) { const [type, subtype] = mimetype.split("/"); const priority = parts.findIndex( (part) => (part.type === type || part.type === "*") && (part.subtype === subtype || part.subtype === "*") ); if (priority !== -1 && priority < min_priority) { accepted = mimetype; min_priority = priority; } } return accepted; } function is_content_type(request, ...types) { const type = request.headers.get("content-type")?.split(";", 1)[0].trim() ?? ""; return types.includes(type.toLowerCase()); } function is_form_content_type(request) { return is_content_type( request, "application/x-www-form-urlencoded", "multipart/form-data", "text/plain" ); } let request_event = null; let als; import("node:async_hooks").then((hooks) => als = new hooks.AsyncLocalStorage()).catch(() => { }); function with_event(event, fn) { try { request_event = event; return als ? als.run(event, fn) : fn(); } finally { request_event = null; } } class HttpError { /** * @param {number} status * @param {{message: string} extends App.Error ? (App.Error | string | undefined) : App.Error} body */ constructor(status, body2) { this.status = status; if (typeof body2 === "string") { this.body = { message: body2 }; } else if (body2) { this.body = body2; } else { this.body = { message: `Error: ${status}` }; } } toString() { return JSON.stringify(this.body); } } class Redirect { /** * @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308} status * @param {string} location */ constructor(status, location) { this.status = status; this.location = location; } } class SvelteKitError extends Error { /** * @param {number} status * @param {string} text * @param {string} message */ constructor(status, text2, message) { super(message); this.status = status; this.text = text2; } } class ActionFailure { /** * @param {number} status * @param {T} data */ constructor(status, data) { this.status = status; this.data = data; } } const DATA_SUFFIX = "/__data.json"; const HTML_DATA_SUFFIX = ".html__data.json"; function has_data_suffix(pathname) { return pathname.endsWith(DATA_SUFFIX) || pathname.endsWith(HTML_DATA_SUFFIX); } function add_data_suffix(pathname) { if (pathname.endsWith(".html")) return pathname.replace(/\.html$/, HTML_DATA_SUFFIX); return pathname.replace(/\/$/, "") + DATA_SUFFIX; } function strip_data_suffix(pathname) { if (pathname.endsWith(HTML_DATA_SUFFIX)) { return pathname.slice(0, -HTML_DATA_SUFFIX.length) + ".html"; } return pathname.slice(0, -DATA_SUFFIX.length); } const ROUTE_SUFFIX = "/__route.js"; function has_resolution_suffix(pathname) { return pathname.endsWith(ROUTE_SUFFIX); } function add_resolution_suffix(pathname) { return pathname.replace(/\/$/, "") + ROUTE_SUFFIX; } function strip_resolution_suffix(pathname) { return pathname.slice(0, -ROUTE_SUFFIX.length); } function json(data, init2) { const body2 = JSON.stringify(data); const headers2 = new Headers(init2?.headers); if (!headers2.has("content-length")) { headers2.set("content-length", encoder$3.encode(body2).byteLength.toString()); } if (!headers2.has("content-type")) { headers2.set("content-type", "application/json"); } return new Response(body2, { ...init2, headers: headers2 }); } const encoder$3 = new TextEncoder(); function text(body2, init2) { const headers2 = new Headers(init2?.headers); if (!headers2.has("content-length")) { const encoded = encoder$3.encode(body2); headers2.set("content-length", encoded.byteLength.toString()); return new Response(encoded, { ...init2, headers: headers2 }); } return new Response(body2, { ...init2, headers: headers2 }); } function coalesce_to_error(err) { return err instanceof Error || err && /** @type {any} */ err.name && /** @type {any} */ err.message ? ( /** @type {Error} */ err ) : new Error(JSON.stringify(err)); } function normalize_error(error) { return ( /** @type {import('../runtime/control.js').Redirect | HttpError | SvelteKitError | Error} */ error ); } function get_status(error) { return error instanceof HttpError || error instanceof SvelteKitError ? error.status : 500; } function get_message(error) { return error instanceof SvelteKitError ? error.text : "Internal Error"; } const escape_html_attr_dict = { "&": "&", '"': """ // Svelte also escapes < because the escape function could be called inside a `noscript` there // https://github.com/sveltejs/svelte/security/advisories/GHSA-8266-84wp-wv5c // However, that doesn't apply in SvelteKit }; const escape_html_dict = { "&": "&", "<": "<" }; const surrogates = ( // high surrogate without paired low surrogate "[\\ud800-\\udbff](?![\\udc00-\\udfff])|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\udc00-\\udfff]" ); const escape_html_attr_regex = new RegExp( `[${Object.keys(escape_html_attr_dict).join("")}]|` + surrogates, "g" ); const escape_html_regex = new RegExp( `[${Object.keys(escape_html_dict).join("")}]|` + surrogates, "g" ); function escape_html(str, is_attr) { const dict = is_attr ? escape_html_attr_dict : escape_html_dict; const escaped_str = str.replace(is_attr ? escape_html_attr_regex : escape_html_regex, (match) => { if (match.length === 2) { return match; } return dict[match] ?? `&#${match.charCodeAt(0)};`; }); return escaped_str; } function method_not_allowed(mod, method) { return text(`${method} method not allowed`, { status: 405, headers: { // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405 // "The server must generate an Allow header field in a 405 status code response" allow: allowed_methods(mod).join(", ") } }); } function allowed_methods(mod) { const allowed = ENDPOINT_METHODS.filter((method) => method in mod); if ("GET" in mod || "HEAD" in mod) allowed.push("HEAD"); return allowed; } function static_error_page(options2, status, message) { let page = options2.templates.error({ status, message: escape_html(message) }); return text(page, { headers: { "content-type": "text/html; charset=utf-8" }, status }); } async function handle_fatal_error(event, options2, error) { error = error instanceof HttpError ? error : coalesce_to_error(error); const status = get_status(error); const body2 = await handle_error_and_jsonify(event, options2, error); const type = negotiate(event.request.headers.get("accept") || "text/html", [ "application/json", "text/html" ]); if (event.isDataRequest || type === "application/json") { return json(body2, { status }); } return static_error_page(options2, status, body2.message); } async function handle_error_and_jsonify(event, options2, error) { if (error instanceof HttpError) { return error.body; } const status = get_status(error); const message = get_message(error); return await options2.hooks.handleError({ error, event, status, message }) ?? { message }; } function redirect_response(status, location) { const response = new Response(void 0, { status, headers: { location } }); return response; } function clarify_devalue_error(event, error) { if (error.path) { return `Data returned from \`load\` while rendering ${event.route.id} is not serializable: ${error.message} (data${error.path})`; } if (error.path === "") { return `Data returned from \`load\` while rendering ${event.route.id} is not a plain object`; } return error.message; } function stringify_uses(node) { const uses = []; if (node.uses && node.uses.dependencies.size > 0) { uses.push(`"dependencies":${JSON.stringify(Array.from(node.uses.dependencies))}`); } if (node.uses && node.uses.search_params.size > 0) { uses.push(`"search_params":${JSON.stringify(Array.from(node.uses.search_params))}`); } if (node.uses && node.uses.params.size > 0) { uses.push(`"params":${JSON.stringify(Array.from(node.uses.params))}`); } if (node.uses?.parent) uses.push('"parent":1'); if (node.uses?.route) uses.push('"route":1'); if (node.uses?.url) uses.push('"url":1'); return `"uses":{${uses.join(",")}}`; } function has_prerendered_path(manifest, pathname) { return manifest._.prerendered_routes.has(pathname) || pathname.at(-1) === "/" && manifest._.prerendered_routes.has(pathname.slice(0, -1)); } async function render_endpoint(event, mod, state) { const method = ( /** @type {import('types').HttpMethod} */ event.request.method ); let handler = mod[method] || mod.fallback; if (method === "HEAD" && mod.GET && !mod.HEAD) { handler = mod.GET; } if (!handler) { return method_not_allowed(mod, method); } const prerender = mod.prerender ?? state.prerender_default; if (prerender && (mod.POST || mod.PATCH || mod.PUT || mod.DELETE)) { throw new Error("Cannot prerender endpoints that have mutative methods"); } if (state.prerendering && !state.prerendering.inside_reroute && !prerender) { if (state.depth > 0) { throw new Error(`${event.route.id} is not prerenderable`); } else { return new Response(void 0, { status: 204 }); } } try { const response = await with_event( event, () => handler( /** @type {import('@sveltejs/kit').RequestEvent>} */ event ) ); if (!(response instanceof Response)) { throw new Error( `Invalid response from route ${event.url.pathname}: handler should return a Response object` ); } if (state.prerendering && (!state.prerendering.inside_reroute || prerender)) { const cloned = new Response(response.clone().body, { status: response.status, statusText: response.statusText, headers: new Headers(response.headers) }); cloned.headers.set("x-sveltekit-prerender", String(prerender)); if (state.prerendering.inside_reroute && prerender) { cloned.headers.set( "x-sveltekit-routeid", encodeURI( /** @type {string} */ event.route.id ) ); state.prerendering.dependencies.set(event.url.pathname, { response: cloned, body: null }); } else { return cloned; } } return response; } catch (e) { if (e instanceof Redirect) { return new Response(void 0, { status: e.status, headers: { location: e.location } }); } throw e; } } function is_endpoint_request(event) { const { method, headers: headers2 } = event.request; if (ENDPOINT_METHODS.includes(method) && !PAGE_METHODS.includes(method)) { return true; } if (method === "POST" && headers2.get("x-sveltekit-action") === "true") return false; const accept = event.request.headers.get("accept") ?? "*/*"; return negotiate(accept, ["*", "text/html"]) !== "text/html"; } function compact(arr) { return arr.filter( /** @returns {val is NonNullable} */ (val) => val != null ); } function is_action_json_request(event) { const accept = negotiate(event.request.headers.get("accept") ?? "*/*", [ "application/json", "text/html" ]); return accept === "application/json" && event.request.method === "POST"; } async function handle_action_json_request(event, options2, server) { const actions = server?.actions; if (!actions) { const no_actions_error = new SvelteKitError( 405, "Method Not Allowed", `POST method not allowed. No form actions exist for ${"this page"}` ); return action_json( { type: "error", error: await handle_error_and_jsonify(event, options2, no_actions_error) }, { status: no_actions_error.status, headers: { // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405 // "The server must generate an Allow header field in a 405 status code response" allow: "GET" } } ); } check_named_default_separate(actions); try { const data = await call_action(event, actions); if (false) ; if (data instanceof ActionFailure) { return action_json({ type: "failure", status: data.status, // @ts-expect-error we assign a string to what is supposed to be an object. That's ok // because we don't use the object outside, and this way we have better code navigation // through knowing where the related interface is used. data: stringify_action_response( data.data, /** @type {string} */ event.route.id, options2.hooks.transport ) }); } else { return action_json({ type: "success", status: data ? 200 : 204, // @ts-expect-error see comment above data: stringify_action_response( data, /** @type {string} */ event.route.id, options2.hooks.transport ) }); } } catch (e) { const err = normalize_error(e); if (err instanceof Redirect) { return action_json_redirect(err); } return action_json( { type: "error", error: await handle_error_and_jsonify(event, options2, check_incorrect_fail_use(err)) }, { status: get_status(err) } ); } } function check_incorrect_fail_use(error) { return error instanceof ActionFailure ? new Error('Cannot "throw fail()". Use "return fail()"') : error; } function action_json_redirect(redirect) { return action_json({ type: "redirect", status: redirect.status, location: redirect.location }); } function action_json(data, init2) { return json(data, init2); } function is_action_request(event) { return event.request.method === "POST"; } async function handle_action_request(event, server) { const actions = server?.actions; if (!actions) { event.setHeaders({ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/405 // "The server must generate an Allow header field in a 405 status code response" allow: "GET" }); return { type: "error", error: new SvelteKitError( 405, "Method Not Allowed", `POST method not allowed. No form actions exist for ${"this page"}` ) }; } check_named_default_separate(actions); try { const data = await call_action(event, actions); if (false) ; if (data instanceof ActionFailure) { return { type: "failure", status: data.status, data: data.data }; } else { return { type: "success", status: 200, // @ts-expect-error this will be removed upon serialization, so `undefined` is the same as omission data }; } } catch (e) { const err = normalize_error(e); if (err instanceof Redirect) { return { type: "redirect", status: err.status, location: err.location }; } return { type: "error", error: check_incorrect_fail_use(err) }; } } function check_named_default_separate(actions) { if (actions.default && Object.keys(actions).length > 1) { throw new Error( "When using named actions, the default action cannot be used. See the docs for more info: https://svelte.dev/docs/kit/form-actions#named-actions" ); } } async function call_action(event, actions) { const url = new URL(event.request.url); let name = "default"; for (const param of url.searchParams) { if (param[0].startsWith("/")) { name = param[0].slice(1); if (name === "default") { throw new Error('Cannot use reserved action name "default"'); } break; } } const action = actions[name]; if (!action) { throw new SvelteKitError(404, "Not Found", `No action with name '${name}' found`); } if (!is_form_content_type(event.request)) { throw new SvelteKitError( 415, "Unsupported Media Type", `Form actions expect form-encoded data — received ${event.request.headers.get( "content-type" )}` ); } return with_event(event, () => action(event)); } function validate_action_return(data) { if (data instanceof Redirect) { throw new Error("Cannot `return redirect(...)` — use `redirect(...)` instead"); } if (data instanceof HttpError) { throw new Error("Cannot `return error(...)` — use `error(...)` or `return fail(...)` instead"); } } function uneval_action_response(data, route_id, transport) { const replacer = (thing) => { for (const key2 in transport) { const encoded = transport[key2].encode(thing); if (encoded) { return `app.decode('${key2}', ${devalue.uneval(encoded, replacer)})`; } } }; return try_serialize(data, (value) => devalue.uneval(value, replacer), route_id); } function stringify_action_response(data, route_id, transport) { const encoders = Object.fromEntries( Object.entries(transport).map(([key2, value]) => [key2, value.encode]) ); return try_serialize(data, (value) => devalue.stringify(value, encoders), route_id); } function try_serialize(data, fn, route_id) { try { return fn(data); } catch (e) { const error = ( /** @type {any} */ e ); if (data instanceof Response) { throw new Error( `Data returned from action inside ${route_id} is not serializable. Form actions need to return plain objects or fail(). E.g. return { success: true } or return fail(400, { message: "invalid" });` ); } if ("path" in error) { let message = `Data returned from action inside ${route_id} is not serializable: ${error.message}`; if (error.path !== "") message += ` (data.${error.path})`; throw new Error(message); } throw error; } } function validate_depends(route_id, dep) { const match = /^(moz-icon|view-source|jar):/.exec(dep); if (match) { console.warn( `${route_id}: Calling \`depends('${dep}')\` will throw an error in Firefox because \`${match[1]}\` is a special URI scheme` ); } } const INVALIDATED_PARAM = "x-sveltekit-invalidated"; const TRAILING_SLASH_PARAM = "x-sveltekit-trailing-slash"; function b64_encode(buffer) { if (globalThis.Buffer) { return Buffer.from(buffer).toString("base64"); } const little_endian = new Uint8Array(new Uint16Array([1]).buffer)[0] > 0; return btoa( new TextDecoder(little_endian ? "utf-16le" : "utf-16be").decode( new Uint16Array(new Uint8Array(buffer)) ) ); } function get_relative_path(from, to) { const from_parts = from.split(/[/\\]/); const to_parts = to.split(/[/\\]/); from_parts.pop(); while (from_parts[0] === to_parts[0]) { from_parts.shift(); to_parts.shift(); } let i = from_parts.length; while (i--) from_parts[i] = ".."; return from_parts.concat(to_parts).join("/"); } async function load_server_data({ event, state, node, parent }) { if (!node?.server) return null; let is_tracking = true; const uses = { dependencies: /* @__PURE__ */ new Set(), params: /* @__PURE__ */ new Set(), parent: false, route: false, url: false, search_params: /* @__PURE__ */ new Set() }; const load = node.server.load; const slash = node.server.trailingSlash; if (!load) { return { type: "data", data: null, uses, slash }; } const url = make_trackable( event.url, () => { if (is_tracking) { uses.url = true; } }, (param) => { if (is_tracking) { uses.search_params.add(param); } } ); if (state.prerendering) { disable_search(url); } let done = false; const result = await with_event( event, () => load.call(null, { ...event, fetch: (info, init2) => { const url2 = new URL(info instanceof Request ? info.url : info, event.url); if (BROWSER && done && !uses.dependencies.has(url2.href)) ; return event.fetch(info, init2); }, /** @param {string[]} deps */ depends: (...deps) => { for (const dep of deps) { const { href } = new URL(dep, event.url); if (BROWSER) ; uses.dependencies.add(href); } }, params: new Proxy(event.params, { get: (target, key2) => { if (BROWSER && done && typeof key2 === "string" && !uses.params.has(key2)) ; if (is_tracking) { uses.params.add(key2); } return target[ /** @type {string} */ key2 ]; } }), parent: async () => { if (BROWSER && done && !uses.parent) ; if (is_tracking) { uses.parent = true; } return parent(); }, route: new Proxy(event.route, { get: (target, key2) => { if (BROWSER && done && typeof key2 === "string" && !uses.route) ; if (is_tracking) { uses.route = true; } return target[ /** @type {'id'} */ key2 ]; } }), url, untrack(fn) { is_tracking = false; try { return fn(); } finally { is_tracking = true; } } }) ); done = true; return { type: "data", data: result ?? null, uses, slash }; } async function load_data({ event, fetched, node, parent, server_data_promise, state, resolve_opts, csr }) { const server_data_node = await server_data_promise; if (!node?.universal?.load) { return server_data_node?.data ?? null; } const result = await node.universal.load.call(null, { url: event.url, params: event.params, data: server_data_node?.data ?? null, route: event.route, fetch: create_universal_fetch(event, state, fetched, csr, resolve_opts), setHeaders: event.setHeaders, depends: () => { }, parent, untrack: (fn) => fn() }); return result ?? null; } function create_universal_fetch(event, state, fetched, csr, resolve_opts) { const universal_fetch = async (input, init2) => { const cloned_body = input instanceof Request && input.body ? input.clone().body : null; const cloned_headers = input instanceof Request && [...input.headers].length ? new Headers(input.headers) : init2?.headers; let response = await event.fetch(input, init2); const url = new URL(input instanceof Request ? input.url : input, event.url); const same_origin = url.origin === event.url.origin; let dependency; if (same_origin) { if (state.prerendering) { dependency = { response, body: null }; state.prerendering.dependencies.set(url.pathname, dependency); } } else if (url.protocol === "https:" || url.protocol === "http:") { const mode = input instanceof Request ? input.mode : init2?.mode ?? "cors"; if (mode === "no-cors") { response = new Response("", { status: response.status, statusText: response.statusText, headers: response.headers }); } else { const acao = response.headers.get("access-control-allow-origin"); if (!acao || acao !== event.url.origin && acao !== "*") { throw new Error( `CORS error: ${acao ? "Incorrect" : "No"} 'Access-Control-Allow-Origin' header is present on the requested resource` ); } } } const proxy = new Proxy(response, { get(response2, key2, _receiver) { async function push_fetched(body2, is_b64) { const status_number = Number(response2.status); if (isNaN(status_number)) { throw new Error( `response.status is not a number. value: "${response2.status}" type: ${typeof response2.status}` ); } fetched.push({ url: same_origin ? url.href.slice(event.url.origin.length) : url.href, method: event.request.method, request_body: ( /** @type {string | ArrayBufferView | undefined} */ input instanceof Request && cloned_body ? await stream_to_string(cloned_body) : init2?.body ), request_headers: cloned_headers, response_body: body2, response: response2, is_b64 }); } if (key2 === "arrayBuffer") { return async () => { const buffer = await response2.arrayBuffer(); if (dependency) { dependency.body = new Uint8Array(buffer); } if (buffer instanceof ArrayBuffer) { await push_fetched(b64_encode(buffer), true); } return buffer; }; } async function text2() { const body2 = await response2.text(); if (!body2 || typeof body2 === "string") { await push_fetched(body2, false); } if (dependency) { dependency.body = body2; } return body2; } if (key2 === "text") { return text2; } if (key2 === "json") { return async () => { return JSON.parse(await text2()); }; } return Reflect.get(response2, key2, response2); } }); if (csr) { const get = response.headers.get; response.headers.get = (key2) => { const lower = key2.toLowerCase(); const value = get.call(response.headers, lower); if (value && !lower.startsWith("x-sveltekit-")) { const included = resolve_opts.filterSerializedResponseHeaders(lower, value); if (!included) { throw new Error( `Failed to get response header "${lower}" — it must be included by the \`filterSerializedResponseHeaders\` option: https://svelte.dev/docs/kit/hooks#Server-hooks-handle (at ${event.route.id})` ); } } return value; }; } return proxy; }; return (input, init2) => { const response = universal_fetch(input, init2); response.catch(() => { }); return response; }; } async function stream_to_string(stream) { let result = ""; const reader = stream.getReader(); const decoder = new TextDecoder(); while (true) { const { done, value } = await reader.read(); if (done) { break; } result += decoder.decode(value); } return result; } function hash(...values) { let hash2 = 5381; for (const value of values) { if (typeof value === "string") { let i = value.length; while (i) hash2 = hash2 * 33 ^ value.charCodeAt(--i); } else if (ArrayBuffer.isView(value)) { const buffer = new Uint8Array(value.buffer, value.byteOffset, value.byteLength); let i = buffer.length; while (i) hash2 = hash2 * 33 ^ buffer[--i]; } else { throw new TypeError("value must be a string or TypedArray"); } } return (hash2 >>> 0).toString(36); } const replacements = { "<": "\\u003C", "\u2028": "\\u2028", "\u2029": "\\u2029" }; const pattern = new RegExp(`[${Object.keys(replacements).join("")}]`, "g"); function serialize_data(fetched, filter, prerendering2 = false) { const headers2 = {}; let cache_control = null; let age = null; let varyAny = false; for (const [key2, value] of fetched.response.headers) { if (filter(key2, value)) { headers2[key2] = value; } if (key2 === "cache-control") cache_control = value; else if (key2 === "age") age = value; else if (key2 === "vary" && value.trim() === "*") varyAny = true; } const payload = { status: fetched.response.status, statusText: fetched.response.statusText, headers: headers2, body: fetched.response_body }; const safe_payload = JSON.stringify(payload).replace(pattern, (match) => replacements[match]); const attrs = [ 'type="application/json"', "data-sveltekit-fetched", `data-url="${escape_html(fetched.url, true)}"` ]; if (fetched.is_b64) { attrs.push("data-b64"); } if (fetched.request_headers || fetched.request_body) { const values = []; if (fetched.request_headers) { values.push([...new Headers(fetched.request_headers)].join(",")); } if (fetched.request_body) { values.push(fetched.request_body); } attrs.push(`data-hash="${hash(...values)}"`); } if (!prerendering2 && fetched.method === "GET" && cache_control && !varyAny) { const match = /s-maxage=(\d+)/g.exec(cache_control) ?? /max-age=(\d+)/g.exec(cache_control); if (match) { const ttl = +match[1] - +(age ?? "0"); attrs.push(`data-ttl="${ttl}"`); } } return `