horse/horse-client/.svelte-kit/output/server/index.js
mmm8955405 dc2dc7a8f3 xg
2024-06-21 18:24:11 +08:00

2784 lines
83 KiB
JavaScript

import { b as base, a as assets, r as reset, p as public_env, o as options, g as get_hooks, s as set_public_env } from "./chunks/internal.js";
import * as devalue from "devalue";
import { n as noop, s as safe_not_equal } from "./chunks/index.js";
import { parse, serialize } from "cookie";
import * as set_cookie_parser from "set-cookie-parser";
const DEV = false;
function negotiate(accept, types) {
const parts = [];
accept.split(",").forEach((str, i) => {
const match = /([^/]+)\/([^;]+)(?:;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);
}
function is_form_content_type(request) {
return is_content_type(request, "application/x-www-form-urlencoded", "multipart/form-data");
}
let HttpError = class HttpError2 {
/**
* @param {number} status
* @param {{message: string} extends App.Error ? (App.Error | string | undefined) : App.Error} body
*/
constructor(status, body) {
this.status = status;
if (typeof body === "string") {
this.body = { message: body };
} else if (body) {
this.body = body;
} else {
this.body = { message: `Error: ${status}` };
}
}
toString() {
return JSON.stringify(this.body);
}
};
let Redirect = class Redirect2 {
/**
* @param {300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308} status
* @param {string} location
*/
constructor(status, location) {
this.status = status;
this.location = location;
}
};
let ActionFailure = class ActionFailure2 {
/**
* @param {number} status
* @param {T} [data]
*/
constructor(status, data) {
this.status = status;
this.data = data;
}
};
function error(status, message) {
if (isNaN(status) || status < 400 || status > 599) {
throw new Error(`HTTP error status codes must be between 400 and 599 — ${status} is invalid`);
}
return new HttpError(status, message);
}
function json(data, init2) {
const body = JSON.stringify(data);
const headers = new Headers(init2?.headers);
if (!headers.has("content-length")) {
headers.set("content-length", encoder$3.encode(body).byteLength.toString());
}
if (!headers.has("content-type")) {
headers.set("content-type", "application/json");
}
return new Response(body, {
...init2,
headers
});
}
const encoder$3 = new TextEncoder();
function text(body, init2) {
const headers = new Headers(init2?.headers);
if (!headers.has("content-length")) {
headers.set("content-length", encoder$3.encode(body).byteLength.toString());
}
return new Response(body, {
...init2,
headers
});
}
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(error2) {
return (
/** @type {Redirect | HttpError | Error} */
error2
);
}
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 = [];
for (const method in ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]) {
if (method in mod)
allowed.push(method);
}
if (mod.GET || mod.HEAD)
allowed.push("HEAD");
return allowed;
}
function static_error_page(options2, status, message) {
return text(options2.templates.error({ status, message }), {
headers: { "content-type": "text/html; charset=utf-8" },
status
});
}
async function handle_fatal_error(event, options2, error2) {
error2 = error2 instanceof HttpError ? error2 : coalesce_to_error(error2);
const status = error2 instanceof HttpError ? error2.status : 500;
const body = await handle_error_and_jsonify(event, options2, error2);
const type = negotiate(event.request.headers.get("accept") || "text/html", [
"application/json",
"text/html"
]);
if (event.isDataRequest || type === "application/json") {
return json(body, {
status
});
}
return static_error_page(options2, status, body.message);
}
async function handle_error_and_jsonify(event, options2, error2) {
if (error2 instanceof HttpError) {
return error2.body;
} else {
return await options2.hooks.handleError({ error: error2, event }) ?? {
message: event.route.id != null ? "Internal Error" : "Not Found"
};
}
}
function redirect_response(status, location) {
const response = new Response(void 0, {
status,
headers: { location }
});
return response;
}
function clarify_devalue_error(event, error2) {
if (error2.path) {
return `Data returned from \`load\` while rendering ${event.route.id} is not serializable: ${error2.message} (data${error2.path})`;
}
if (error2.path === "") {
return `Data returned from \`load\` while rendering ${event.route.id} is not a plain object`;
}
return error2.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.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(",")}}`;
}
async function render_endpoint(event, mod, state) {
const method = (
/** @type {import('types').HttpMethod} */
event.request.method
);
let handler = mod[method];
if (!handler && method === "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 && !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 handler(
/** @type {import('types').RequestEvent<Record<string, any>>} */
event
);
if (!(response instanceof Response)) {
throw new Error(
`Invalid response from route ${event.url.pathname}: handler should return a Response object`
);
}
if (state.prerendering) {
response.headers.set("x-sveltekit-prerender", String(prerender));
}
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 } = event.request;
if (method === "PUT" || method === "PATCH" || method === "DELETE" || method === "OPTIONS") {
return true;
}
if (method === "POST" && headers.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<T>} */
(val) => val != null
);
}
function normalize_path(path, trailing_slash) {
if (path === "/" || trailing_slash === "ignore")
return path;
if (trailing_slash === "never") {
return path.endsWith("/") ? path.slice(0, -1) : path;
} else if (trailing_slash === "always" && !path.endsWith("/")) {
return path + "/";
}
return path;
}
function decode_pathname(pathname) {
return pathname.split("%25").map(decodeURI).join("%25");
}
function decode_params(params) {
for (const key2 in params) {
params[key2] = decodeURIComponent(params[key2]);
}
return params;
}
const tracked_url_properties = ["href", "pathname", "search", "searchParams", "toString", "toJSON"];
function make_trackable(url, callback) {
const tracked = new URL(url);
for (const property of tracked_url_properties) {
let value = tracked[property];
Object.defineProperty(tracked, property, {
get() {
callback();
return value;
},
enumerable: true,
configurable: true
});
}
{
tracked[Symbol.for("nodejs.util.inspect.custom")] = (depth, opts, inspect) => {
return inspect(url, opts);
};
}
disable_hash(tracked);
return tracked;
}
function disable_hash(url) {
Object.defineProperty(url, "hash", {
get() {
throw new Error(
"Cannot access event.url.hash. Consider using `$page.url.hash` inside a component instead"
);
}
});
}
function disable_search(url) {
for (const property of ["search", "searchParams"]) {
Object.defineProperty(url, property, {
get() {
throw new Error(`Cannot access url.${property} on a page with prerendering enabled`);
}
});
}
}
const DATA_SUFFIX = "/__data.json";
function has_data_suffix(pathname) {
return pathname.endsWith(DATA_SUFFIX);
}
function add_data_suffix(pathname) {
return pathname.replace(/\/$/, "") + DATA_SUFFIX;
}
function strip_data_suffix(pathname) {
return pathname.slice(0, -DATA_SUFFIX.length);
}
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 = error(405, "POST method not allowed. No 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
)
});
} 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
)
});
}
} catch (e) {
const err = normalize_error(e);
if (err instanceof Redirect) {
return action_json({
type: "redirect",
status: err.status,
location: err.location
});
}
return action_json(
{
type: "error",
error: await handle_error_and_jsonify(event, options2, check_incorrect_fail_use(err))
},
{
status: err instanceof HttpError ? err.status : 500
}
);
}
}
function check_incorrect_fail_use(error2) {
return error2 instanceof ActionFailure ? new Error(`Cannot "throw fail()". Use "return fail()"`) : error2;
}
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: error(405, "POST method not allowed. No 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://kit.svelte.dev/docs/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 Error(`No action with name '${name}' found`);
}
if (!is_form_content_type(event.request)) {
throw new Error(
`Actions expect form-encoded data (received ${event.request.headers.get("content-type")}`
);
}
return action(event);
}
function validate_action_return(data) {
if (data instanceof Redirect) {
throw new Error(`Cannot \`return redirect(...)\` — use \`throw redirect(...)\` instead`);
}
if (data instanceof HttpError) {
throw new Error(
`Cannot \`return error(...)\` — use \`throw error(...)\` or \`return fail(...)\` instead`
);
}
}
function uneval_action_response(data, route_id) {
return try_deserialize(data, devalue.uneval, route_id);
}
function stringify_action_response(data, route_id) {
return try_deserialize(data, devalue.stringify, route_id);
}
function try_deserialize(data, fn, route_id) {
try {
return fn(data);
} catch (e) {
const error2 = (
/** @type {any} */
e
);
if ("path" in error2) {
let message = `Data returned from action inside ${route_id} is not serializable: ${error2.message}`;
if (error2.path !== "")
message += ` (data.${error2.path})`;
throw new Error(message);
}
throw error2;
}
}
async function unwrap_promises(object) {
for (const key2 in object) {
if (typeof object[key2]?.then === "function") {
return Object.fromEntries(
await Promise.all(Object.entries(object).map(async ([key3, value]) => [key3, await value]))
);
}
}
return object;
}
async function load_server_data({ event, state, node, parent }) {
if (!node?.server)
return null;
const uses = {
dependencies: /* @__PURE__ */ new Set(),
params: /* @__PURE__ */ new Set(),
parent: false,
route: false,
url: false
};
const url = make_trackable(event.url, () => {
uses.url = true;
});
if (state.prerendering) {
disable_search(url);
}
const result = await node.server.load?.call(null, {
...event,
fetch: (info, init2) => {
const url2 = new URL(info instanceof Request ? info.url : info, event.url);
uses.dependencies.add(url2.href);
return event.fetch(info, init2);
},
/** @param {string[]} deps */
depends: (...deps) => {
for (const dep of deps) {
const { href } = new URL(dep, event.url);
uses.dependencies.add(href);
}
},
params: new Proxy(event.params, {
get: (target, key2) => {
uses.params.add(key2);
return target[
/** @type {string} */
key2
];
}
}),
parent: async () => {
uses.parent = true;
return parent();
},
route: new Proxy(event.route, {
get: (target, key2) => {
uses.route = true;
return target[
/** @type {'id'} */
key2
];
}
}),
url
});
const data = result ? await unwrap_promises(result) : null;
return {
type: "data",
data,
uses,
slash: node.server.trailingSlash
};
}
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
});
const data = result ? await unwrap_promises(result) : null;
return data;
}
function create_universal_fetch(event, state, fetched, csr, resolve_opts) {
return async (input, init2) => {
const cloned_body = input instanceof Request && input.body ? input.clone().body : null;
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 {
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 text2() {
const body = await response2.text();
if (!body || typeof body === "string") {
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: init2?.headers,
response_body: body,
response: response2
});
}
if (dependency) {
dependency.body = body;
}
return body;
}
if (key2 === "arrayBuffer") {
return async () => {
const buffer = await response2.arrayBuffer();
if (dependency) {
dependency.body = new Uint8Array(buffer);
}
return buffer;
};
}
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://kit.svelte.dev/docs/hooks#server-hooks-handle (at ${event.route.id})`
);
}
}
return value;
};
}
return proxy;
};
}
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;
}
const subscriber_queue = [];
function readable(value, start) {
return {
subscribe: writable(value, start).subscribe
};
}
function writable(value, start = noop) {
let stop;
const subscribers = /* @__PURE__ */ new Set();
function set(new_value) {
if (safe_not_equal(value, new_value)) {
value = new_value;
if (stop) {
const run_queue = !subscriber_queue.length;
for (const subscriber of subscribers) {
subscriber[1]();
subscriber_queue.push(subscriber, value);
}
if (run_queue) {
for (let i = 0; i < subscriber_queue.length; i += 2) {
subscriber_queue[i][0](subscriber_queue[i + 1]);
}
subscriber_queue.length = 0;
}
}
}
}
function update(fn) {
set(fn(value));
}
function subscribe(run, invalidate = noop) {
const subscriber = [run, invalidate];
subscribers.add(subscriber);
if (subscribers.size === 1) {
stop = start(set) || noop;
}
run(value);
return () => {
subscribers.delete(subscriber);
if (subscribers.size === 0 && stop) {
stop();
stop = null;
}
};
}
return { set, update, subscribe };
}
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 escape_html_attr_dict = {
"&": "&amp;",
'"': "&quot;"
};
const escape_html_attr_regex = new RegExp(
// special characters
`[${Object.keys(escape_html_attr_dict).join("")}]|[\\ud800-\\udbff](?![\\udc00-\\udfff])|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\udc00-\\udfff]`,
"g"
);
function escape_html_attr(str) {
const escaped_str = str.replace(escape_html_attr_regex, (match) => {
if (match.length === 2) {
return match;
}
return escape_html_attr_dict[match] ?? `&#${match.charCodeAt(0)};`;
});
return `"${escaped_str}"`;
}
const replacements = {
"<": "\\u003C",
"\u2028": "\\u2028",
"\u2029": "\\u2029"
};
const pattern = new RegExp(`[${Object.keys(replacements).join("")}]`, "g");
function serialize_data(fetched, filter, prerendering = false) {
const headers = {};
let cache_control = null;
let age = null;
let vary = false;
for (const [key2, value] of fetched.response.headers) {
if (filter(key2, value)) {
headers[key2] = value;
}
if (key2 === "cache-control")
cache_control = value;
if (key2 === "age")
age = value;
if (key2 === "vary")
vary = true;
}
const payload = {
status: fetched.response.status,
statusText: fetched.response.statusText,
headers,
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_attr(fetched.url)}`
];
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 (!prerendering && fetched.method === "GET" && cache_control && !vary) {
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 `<script ${attrs.join(" ")}>${safe_payload}<\/script>`;
}
const s = JSON.stringify;
const encoder$2 = new TextEncoder();
function sha256(data) {
if (!key[0])
precompute();
const out = init.slice(0);
const array2 = encode(data);
for (let i = 0; i < array2.length; i += 16) {
const w = array2.subarray(i, i + 16);
let tmp;
let a;
let b;
let out0 = out[0];
let out1 = out[1];
let out2 = out[2];
let out3 = out[3];
let out4 = out[4];
let out5 = out[5];
let out6 = out[6];
let out7 = out[7];
for (let i2 = 0; i2 < 64; i2++) {
if (i2 < 16) {
tmp = w[i2];
} else {
a = w[i2 + 1 & 15];
b = w[i2 + 14 & 15];
tmp = w[i2 & 15] = (a >>> 7 ^ a >>> 18 ^ a >>> 3 ^ a << 25 ^ a << 14) + (b >>> 17 ^ b >>> 19 ^ b >>> 10 ^ b << 15 ^ b << 13) + w[i2 & 15] + w[i2 + 9 & 15] | 0;
}
tmp = tmp + out7 + (out4 >>> 6 ^ out4 >>> 11 ^ out4 >>> 25 ^ out4 << 26 ^ out4 << 21 ^ out4 << 7) + (out6 ^ out4 & (out5 ^ out6)) + key[i2];
out7 = out6;
out6 = out5;
out5 = out4;
out4 = out3 + tmp | 0;
out3 = out2;
out2 = out1;
out1 = out0;
out0 = tmp + (out1 & out2 ^ out3 & (out1 ^ out2)) + (out1 >>> 2 ^ out1 >>> 13 ^ out1 >>> 22 ^ out1 << 30 ^ out1 << 19 ^ out1 << 10) | 0;
}
out[0] = out[0] + out0 | 0;
out[1] = out[1] + out1 | 0;
out[2] = out[2] + out2 | 0;
out[3] = out[3] + out3 | 0;
out[4] = out[4] + out4 | 0;
out[5] = out[5] + out5 | 0;
out[6] = out[6] + out6 | 0;
out[7] = out[7] + out7 | 0;
}
const bytes = new Uint8Array(out.buffer);
reverse_endianness(bytes);
return base64(bytes);
}
const init = new Uint32Array(8);
const key = new Uint32Array(64);
function precompute() {
function frac(x) {
return (x - Math.floor(x)) * 4294967296;
}
let prime = 2;
for (let i = 0; i < 64; prime++) {
let is_prime = true;
for (let factor = 2; factor * factor <= prime; factor++) {
if (prime % factor === 0) {
is_prime = false;
break;
}
}
if (is_prime) {
if (i < 8) {
init[i] = frac(prime ** (1 / 2));
}
key[i] = frac(prime ** (1 / 3));
i++;
}
}
}
function reverse_endianness(bytes) {
for (let i = 0; i < bytes.length; i += 4) {
const a = bytes[i + 0];
const b = bytes[i + 1];
const c = bytes[i + 2];
const d = bytes[i + 3];
bytes[i + 0] = d;
bytes[i + 1] = c;
bytes[i + 2] = b;
bytes[i + 3] = a;
}
}
function encode(str) {
const encoded = encoder$2.encode(str);
const length = encoded.length * 8;
const size = 512 * Math.ceil((length + 65) / 512);
const bytes = new Uint8Array(size / 8);
bytes.set(encoded);
bytes[encoded.length] = 128;
reverse_endianness(bytes);
const words = new Uint32Array(bytes.buffer);
words[words.length - 2] = Math.floor(length / 4294967296);
words[words.length - 1] = length;
return words;
}
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");
function base64(bytes) {
const l = bytes.length;
let result = "";
let i;
for (i = 2; i < l; i += 3) {
result += chars[bytes[i - 2] >> 2];
result += chars[(bytes[i - 2] & 3) << 4 | bytes[i - 1] >> 4];
result += chars[(bytes[i - 1] & 15) << 2 | bytes[i] >> 6];
result += chars[bytes[i] & 63];
}
if (i === l + 1) {
result += chars[bytes[i - 2] >> 2];
result += chars[(bytes[i - 2] & 3) << 4];
result += "==";
}
if (i === l) {
result += chars[bytes[i - 2] >> 2];
result += chars[(bytes[i - 2] & 3) << 4 | bytes[i - 1] >> 4];
result += chars[(bytes[i - 1] & 15) << 2];
result += "=";
}
return result;
}
const array = new Uint8Array(16);
function generate_nonce() {
crypto.getRandomValues(array);
return base64(array);
}
const quoted = /* @__PURE__ */ new Set([
"self",
"unsafe-eval",
"unsafe-hashes",
"unsafe-inline",
"none",
"strict-dynamic",
"report-sample",
"wasm-unsafe-eval",
"script"
]);
const crypto_pattern = /^(nonce|sha\d\d\d)-/;
class BaseProvider {
/** @type {boolean} */
#use_hashes;
/** @type {boolean} */
#script_needs_csp;
/** @type {boolean} */
#style_needs_csp;
/** @type {import('types').CspDirectives} */
#directives;
/** @type {import('types').Csp.Source[]} */
#script_src;
/** @type {import('types').Csp.Source[]} */
#style_src;
/** @type {string} */
#nonce;
/**
* @param {boolean} use_hashes
* @param {import('types').CspDirectives} directives
* @param {string} nonce
*/
constructor(use_hashes, directives, nonce) {
this.#use_hashes = use_hashes;
this.#directives = directives;
const d = this.#directives;
this.#script_src = [];
this.#style_src = [];
const effective_script_src = d["script-src"] || d["default-src"];
const effective_style_src = d["style-src"] || d["default-src"];
this.#script_needs_csp = !!effective_script_src && effective_script_src.filter((value) => value !== "unsafe-inline").length > 0;
this.#style_needs_csp = !!effective_style_src && effective_style_src.filter((value) => value !== "unsafe-inline").length > 0;
this.script_needs_nonce = this.#script_needs_csp && !this.#use_hashes;
this.style_needs_nonce = this.#style_needs_csp && !this.#use_hashes;
this.#nonce = nonce;
}
/** @param {string} content */
add_script(content) {
if (this.#script_needs_csp) {
if (this.#use_hashes) {
this.#script_src.push(`sha256-${sha256(content)}`);
} else if (this.#script_src.length === 0) {
this.#script_src.push(`nonce-${this.#nonce}`);
}
}
}
/** @param {string} content */
add_style(content) {
if (this.#style_needs_csp) {
if (this.#use_hashes) {
this.#style_src.push(`sha256-${sha256(content)}`);
} else if (this.#style_src.length === 0) {
this.#style_src.push(`nonce-${this.#nonce}`);
}
}
}
/**
* @param {boolean} [is_meta]
*/
get_header(is_meta = false) {
const header = [];
const directives = { ...this.#directives };
if (this.#style_src.length > 0) {
directives["style-src"] = [
...directives["style-src"] || directives["default-src"] || [],
...this.#style_src
];
}
if (this.#script_src.length > 0) {
directives["script-src"] = [
...directives["script-src"] || directives["default-src"] || [],
...this.#script_src
];
}
for (const key2 in directives) {
if (is_meta && (key2 === "frame-ancestors" || key2 === "report-uri" || key2 === "sandbox")) {
continue;
}
const value = (
/** @type {string[] | true} */
directives[key2]
);
if (!value)
continue;
const directive = [key2];
if (Array.isArray(value)) {
value.forEach((value2) => {
if (quoted.has(value2) || crypto_pattern.test(value2)) {
directive.push(`'${value2}'`);
} else {
directive.push(value2);
}
});
}
header.push(directive.join(" "));
}
return header.join("; ");
}
}
class CspProvider extends BaseProvider {
get_meta() {
const content = escape_html_attr(this.get_header(true));
return `<meta http-equiv="content-security-policy" content=${content}>`;
}
}
class CspReportOnlyProvider extends BaseProvider {
/**
* @param {boolean} use_hashes
* @param {import('types').CspDirectives} directives
* @param {string} nonce
*/
constructor(use_hashes, directives, nonce) {
super(use_hashes, directives, nonce);
if (Object.values(directives).filter((v) => !!v).length > 0) {
const has_report_to = directives["report-to"]?.length ?? 0 > 0;
const has_report_uri = directives["report-uri"]?.length ?? 0 > 0;
if (!has_report_to && !has_report_uri) {
throw Error(
"`content-security-policy-report-only` must be specified with either the `report-to` or `report-uri` directives, or both"
);
}
}
}
}
class Csp {
/** @readonly */
nonce = generate_nonce();
/** @type {CspProvider} */
csp_provider;
/** @type {CspReportOnlyProvider} */
report_only_provider;
/**
* @param {import('./types').CspConfig} config
* @param {import('./types').CspOpts} opts
*/
constructor({ mode, directives, reportOnly }, { prerender }) {
const use_hashes = mode === "hash" || mode === "auto" && prerender;
this.csp_provider = new CspProvider(use_hashes, directives, this.nonce);
this.report_only_provider = new CspReportOnlyProvider(use_hashes, reportOnly, this.nonce);
}
get script_needs_nonce() {
return this.csp_provider.script_needs_nonce || this.report_only_provider.script_needs_nonce;
}
get style_needs_nonce() {
return this.csp_provider.style_needs_nonce || this.report_only_provider.style_needs_nonce;
}
/** @param {string} content */
add_script(content) {
this.csp_provider.add_script(content);
this.report_only_provider.add_script(content);
}
/** @param {string} content */
add_style(content) {
this.csp_provider.add_style(content);
this.report_only_provider.add_style(content);
}
}
function defer() {
let fulfil;
let reject;
const promise = new Promise((f, r) => {
fulfil = f;
reject = r;
});
return { promise, fulfil, reject };
}
function create_async_iterator() {
let deferred = [defer()];
return {
iterator: {
[Symbol.asyncIterator]() {
return {
next: async () => {
const next = await deferred[0].promise;
if (!next.done)
deferred.shift();
return next;
}
};
}
},
push: (value) => {
deferred[deferred.length - 1].fulfil({
value,
done: false
});
deferred.push(defer());
},
done: () => {
deferred[deferred.length - 1].fulfil({ done: true });
}
};
}
const SVELTE_KIT_ASSETS = "/_svelte_kit_assets";
const updated = {
...readable(false),
check: () => false
};
const encoder$1 = new TextEncoder();
async function render_response({
branch,
fetched,
options: options2,
manifest,
state,
page_config,
status,
error: error2 = null,
event,
resolve_opts,
action_result
}) {
if (state.prerendering) {
if (options2.csp.mode === "nonce") {
throw new Error('Cannot use prerendering if config.kit.csp.mode === "nonce"');
}
if (options2.app_template_contains_nonce) {
throw new Error("Cannot use prerendering if page template contains %sveltekit.nonce%");
}
}
const { client } = manifest._;
const modulepreloads = /* @__PURE__ */ new Set([...client.start.imports, ...client.app.imports]);
const stylesheets = new Set(client.app.stylesheets);
const fonts = new Set(client.app.fonts);
const link_header_preloads = /* @__PURE__ */ new Set();
const inline_styles = /* @__PURE__ */ new Map();
let rendered;
const form_value = action_result?.type === "success" || action_result?.type === "failure" ? action_result.data ?? null : null;
let base$1 = base;
let assets$1 = assets;
let base_expression = s(base);
if (!state.prerendering?.fallback) {
const segments = event.url.pathname.slice(base.length).split("/");
if (segments.length === 1 && base !== "") {
base$1 = `./${base.split("/").at(-1)}`;
base_expression = `new URL(${s(base$1)}, location).pathname`;
} else {
base$1 = segments.slice(2).map(() => "..").join("/") || ".";
base_expression = `new URL(${s(base$1)}, location).pathname.slice(0, -1)`;
}
if (!assets || assets[0] === "/" && assets !== SVELTE_KIT_ASSETS) {
assets$1 = base$1;
}
}
if (page_config.ssr) {
const props = {
stores: {
page: writable(null),
navigating: writable(null),
updated
},
constructors: await Promise.all(branch.map(({ node }) => node.component())),
form: form_value
};
let data2 = {};
for (let i = 0; i < branch.length; i += 1) {
data2 = { ...data2, ...branch[i].data };
props[`data_${i}`] = data2;
}
props.page = {
error: error2,
params: (
/** @type {Record<string, any>} */
event.params
),
route: event.route,
status,
url: event.url,
data: data2,
form: form_value
};
{
try {
rendered = options2.root.render(props);
} finally {
reset();
}
}
for (const { node } of branch) {
for (const url of node.imports)
modulepreloads.add(url);
for (const url of node.stylesheets)
stylesheets.add(url);
for (const url of node.fonts)
fonts.add(url);
if (node.inline_styles) {
Object.entries(await node.inline_styles()).forEach(([k, v]) => inline_styles.set(k, v));
}
}
} else {
rendered = { head: "", html: "", css: { code: "", map: null } };
}
let head = "";
let body = rendered.html;
const csp = new Csp(options2.csp, {
prerender: !!state.prerendering
});
const prefixed = (path) => {
if (path.startsWith("/")) {
return base + path;
}
return `${assets$1}/${path}`;
};
if (inline_styles.size > 0) {
const content = Array.from(inline_styles.values()).join("\n");
const attributes = [];
if (csp.style_needs_nonce)
attributes.push(` nonce="${csp.nonce}"`);
csp.add_style(content);
head += `
<style${attributes.join("")}>${content}</style>`;
}
for (const dep of stylesheets) {
const path = prefixed(dep);
const attributes = ['rel="stylesheet"'];
if (inline_styles.has(dep)) {
attributes.push("disabled", 'media="(max-width: 0)"');
} else {
if (resolve_opts.preload({ type: "css", path })) {
const preload_atts = ['rel="preload"', 'as="style"'];
link_header_preloads.add(`<${encodeURI(path)}>; ${preload_atts.join(";")}; nopush`);
}
}
head += `
<link href="${path}" ${attributes.join(" ")}>`;
}
for (const dep of fonts) {
const path = prefixed(dep);
if (resolve_opts.preload({ type: "font", path })) {
const ext = dep.slice(dep.lastIndexOf(".") + 1);
const attributes = [
'rel="preload"',
'as="font"',
`type="font/${ext}"`,
`href="${path}"`,
"crossorigin"
];
head += `
<link ${attributes.join(" ")}>`;
}
}
const global = `__sveltekit_${options2.version_hash}`;
const { data, chunks } = get_data(
event,
options2,
branch.map((b) => b.server_data),
global
);
if (page_config.ssr && page_config.csr) {
body += `
${fetched.map(
(item) => serialize_data(item, resolve_opts.filterSerializedResponseHeaders, !!state.prerendering)
).join("\n ")}`;
}
if (page_config.csr) {
const included_modulepreloads = Array.from(modulepreloads, (dep) => prefixed(dep)).filter(
(path) => resolve_opts.preload({ type: "js", path })
);
for (const path of included_modulepreloads) {
link_header_preloads.add(`<${encodeURI(path)}>; rel="modulepreload"; nopush`);
if (options2.preload_strategy !== "modulepreload") {
head += `
<link rel="preload" as="script" crossorigin="anonymous" href="${path}">`;
} else if (state.prerendering) {
head += `
<link rel="modulepreload" href="${path}">`;
}
}
const blocks = [];
const properties = [
`env: ${s(public_env)}`,
assets && `assets: ${s(assets)}`,
`base: ${base_expression}`,
`element: document.currentScript.parentElement`
].filter(Boolean);
if (chunks) {
blocks.push(`const deferred = new Map();`);
properties.push(`defer: (id) => new Promise((fulfil, reject) => {
deferred.set(id, { fulfil, reject });
})`);
properties.push(`resolve: ({ id, data, error }) => {
const { fulfil, reject } = deferred.get(id);
deferred.delete(id);
if (error) reject(error);
else fulfil(data);
}`);
}
blocks.push(`${global} = {
${properties.join(",\n ")}
};`);
const args = [`app`, `${global}.element`];
if (page_config.ssr) {
const serialized = { form: "null", error: "null" };
blocks.push(`const data = ${data};`);
if (form_value) {
serialized.form = uneval_action_response(
form_value,
/** @type {string} */
event.route.id
);
}
if (error2) {
serialized.error = devalue.uneval(error2);
}
const hydrate = [
`node_ids: [${branch.map(({ node }) => node.index).join(", ")}]`,
`data`,
`form: ${serialized.form}`,
`error: ${serialized.error}`
];
if (status !== 200) {
hydrate.push(`status: ${status}`);
}
if (options2.embedded) {
hydrate.push(`params: ${devalue.uneval(event.params)}`, `route: ${s(event.route)}`);
}
args.push(`{
${hydrate.join(",\n ")}
}`);
}
blocks.push(`Promise.all([
import(${s(prefixed(client.start.file))}),
import(${s(prefixed(client.app.file))})
]).then(([kit, app]) => {
kit.start(${args.join(", ")});
});`);
if (options2.service_worker) {
const opts = "";
blocks.push(`if ('serviceWorker' in navigator) {
addEventListener('load', function () {
navigator.serviceWorker.register('${prefixed("service-worker.js")}'${opts});
});
}`);
}
const init_app = `
{
${blocks.join("\n\n ")}
}
`;
csp.add_script(init_app);
body += `
<script${csp.script_needs_nonce ? ` nonce="${csp.nonce}"` : ""}>${init_app}<\/script>
`;
}
const headers = new Headers({
"x-sveltekit-page": "true",
"content-type": "text/html"
});
if (state.prerendering) {
const http_equiv = [];
const csp_headers = csp.csp_provider.get_meta();
if (csp_headers) {
http_equiv.push(csp_headers);
}
if (state.prerendering.cache) {
http_equiv.push(`<meta http-equiv="cache-control" content="${state.prerendering.cache}">`);
}
if (http_equiv.length > 0) {
head = http_equiv.join("\n") + head;
}
} else {
const csp_header = csp.csp_provider.get_header();
if (csp_header) {
headers.set("content-security-policy", csp_header);
}
const report_only_header = csp.report_only_provider.get_header();
if (report_only_header) {
headers.set("content-security-policy-report-only", report_only_header);
}
if (link_header_preloads.size) {
headers.set("link", Array.from(link_header_preloads).join(", "));
}
}
head += rendered.head;
const html = options2.templates.app({
head,
body,
assets: assets$1,
nonce: (
/** @type {string} */
csp.nonce
),
env: public_env
});
const transformed = await resolve_opts.transformPageChunk({
html,
done: true
}) || "";
if (!chunks) {
headers.set("etag", `"${hash(transformed)}"`);
}
return !chunks ? text(transformed, {
status,
headers
}) : new Response(
new ReadableStream({
async start(controller) {
controller.enqueue(encoder$1.encode(transformed + "\n"));
for await (const chunk of chunks) {
controller.enqueue(encoder$1.encode(chunk));
}
controller.close();
},
type: "bytes"
}),
{
headers: {
"content-type": "text/html"
}
}
);
}
function get_data(event, options2, nodes, global) {
let promise_id = 1;
let count = 0;
const { iterator, push, done } = create_async_iterator();
function replacer(thing) {
if (typeof thing?.then === "function") {
const id = promise_id++;
count += 1;
thing.then(
/** @param {any} data */
(data) => ({ data })
).catch(
/** @param {any} error */
async (error2) => ({
error: await handle_error_and_jsonify(event, options2, error2)
})
).then(
/**
* @param {{data: any; error: any}} result
*/
async ({ data, error: error2 }) => {
count -= 1;
let str;
try {
str = devalue.uneval({ id, data, error: error2 }, replacer);
} catch (e) {
error2 = await handle_error_and_jsonify(
event,
options2,
new Error(`Failed to serialize promise while rendering ${event.route.id}`)
);
data = void 0;
str = devalue.uneval({ id, data, error: error2 }, replacer);
}
push(`<script>${global}.resolve(${str})<\/script>
`);
if (count === 0)
done();
}
);
return `${global}.defer(${id})`;
}
}
try {
const strings = nodes.map((node) => {
if (!node)
return "null";
return `{"type":"data","data":${devalue.uneval(node.data, replacer)},${stringify_uses(node)}${node.slash ? `,"slash":${JSON.stringify(node.slash)}` : ""}}`;
});
return {
data: `[${strings.join(",")}]`,
chunks: count > 0 ? iterator : null
};
} catch (e) {
throw new Error(clarify_devalue_error(
event,
/** @type {any} */
e
));
}
}
function get_option(nodes, option) {
return nodes.reduce(
(value, node) => {
return (
/** @type {any} TypeScript's too dumb to understand this */
node?.universal?.[option] ?? node?.server?.[option] ?? value
);
},
/** @type {Value | undefined} */
void 0
);
}
async function respond_with_error({
event,
options: options2,
manifest,
state,
status,
error: error2,
resolve_opts
}) {
const fetched = [];
try {
const branch = [];
const default_layout = await manifest._.nodes[0]();
const ssr = get_option([default_layout], "ssr") ?? true;
const csr = get_option([default_layout], "csr") ?? true;
if (ssr) {
state.error = true;
const server_data_promise = load_server_data({
event,
state,
node: default_layout,
parent: async () => ({})
});
const server_data = await server_data_promise;
const data = await load_data({
event,
fetched,
node: default_layout,
parent: async () => ({}),
resolve_opts,
server_data_promise,
state,
csr
});
branch.push(
{
node: default_layout,
server_data,
data
},
{
node: await manifest._.nodes[1](),
// 1 is always the root error
data: null,
server_data: null
}
);
}
return await render_response({
options: options2,
manifest,
state,
page_config: {
ssr,
csr: get_option([default_layout], "csr") ?? true
},
status,
error: await handle_error_and_jsonify(event, options2, error2),
branch,
fetched,
event,
resolve_opts
});
} catch (e) {
if (e instanceof Redirect) {
return redirect_response(e.status, e.location);
}
return static_error_page(
options2,
e instanceof HttpError ? e.status : 500,
(await handle_error_and_jsonify(event, options2, e)).message
);
}
}
function once(fn) {
let done = false;
let result;
return () => {
if (done)
return result;
done = true;
return result = fn();
};
}
const INVALIDATED_PARAM = "x-sveltekit-invalidated";
const encoder = new TextEncoder();
async function render_data(event, route, options2, manifest, state, invalidated_data_nodes, trailing_slash) {
if (!route.page) {
return new Response(void 0, {
status: 404
});
}
try {
const node_ids = [...route.page.layouts, route.page.leaf];
const invalidated = invalidated_data_nodes ?? node_ids.map(() => true);
let aborted = false;
const url = new URL(event.url);
url.pathname = normalize_path(url.pathname, trailing_slash);
const new_event = { ...event, url };
const functions = node_ids.map((n, i) => {
return once(async () => {
try {
if (aborted) {
return (
/** @type {import('types').ServerDataSkippedNode} */
{
type: "skip"
}
);
}
const node = n == void 0 ? n : await manifest._.nodes[n]();
return load_server_data({
event: new_event,
state,
node,
parent: async () => {
const data2 = {};
for (let j = 0; j < i; j += 1) {
const parent = (
/** @type {import('types').ServerDataNode | null} */
await functions[j]()
);
if (parent) {
Object.assign(data2, parent.data);
}
}
return data2;
}
});
} catch (e) {
aborted = true;
throw e;
}
});
});
const promises = functions.map(async (fn, i) => {
if (!invalidated[i]) {
return (
/** @type {import('types').ServerDataSkippedNode} */
{
type: "skip"
}
);
}
return fn();
});
let length = promises.length;
const nodes = await Promise.all(
promises.map(
(p, i) => p.catch(async (error2) => {
if (error2 instanceof Redirect) {
throw error2;
}
length = Math.min(length, i + 1);
return (
/** @type {import('types').ServerErrorNode} */
{
type: "error",
error: await handle_error_and_jsonify(event, options2, error2),
status: error2 instanceof HttpError ? error2.status : void 0
}
);
})
)
);
const { data, chunks } = get_data_json(event, options2, nodes);
if (!chunks) {
return json_response(data);
}
return new Response(
new ReadableStream({
async start(controller) {
controller.enqueue(encoder.encode(data));
for await (const chunk of chunks) {
controller.enqueue(encoder.encode(chunk));
}
controller.close();
},
type: "bytes"
}),
{
headers: {
// we use a proprietary content type to prevent buffering.
// the `text` prefix makes it inspectable
"content-type": "text/sveltekit-data",
"cache-control": "private, no-store"
}
}
);
} catch (e) {
const error2 = normalize_error(e);
if (error2 instanceof Redirect) {
return redirect_json_response(error2);
} else {
return json_response(await handle_error_and_jsonify(event, options2, error2), 500);
}
}
}
function json_response(json2, status = 200) {
return text(typeof json2 === "string" ? json2 : JSON.stringify(json2), {
status,
headers: {
"content-type": "application/json",
"cache-control": "private, no-store"
}
});
}
function redirect_json_response(redirect) {
return json_response({
type: "redirect",
location: redirect.location
});
}
function get_data_json(event, options2, nodes) {
let promise_id = 1;
let count = 0;
const { iterator, push, done } = create_async_iterator();
const reducers = {
/** @param {any} thing */
Promise: (thing) => {
if (typeof thing?.then === "function") {
const id = promise_id++;
count += 1;
let key2 = "data";
thing.catch(
/** @param {any} e */
async (e) => {
key2 = "error";
return handle_error_and_jsonify(
event,
options2,
/** @type {any} */
e
);
}
).then(
/** @param {any} value */
async (value) => {
let str;
try {
str = devalue.stringify(value, reducers);
} catch (e) {
const error2 = await handle_error_and_jsonify(
event,
options2,
new Error(`Failed to serialize promise while rendering ${event.route.id}`)
);
key2 = "error";
str = devalue.stringify(error2, reducers);
}
count -= 1;
push(`{"type":"chunk","id":${id},"${key2}":${str}}
`);
if (count === 0)
done();
}
);
return id;
}
}
};
try {
const strings = nodes.map((node) => {
if (!node)
return "null";
if (node.type === "error" || node.type === "skip") {
return JSON.stringify(node);
}
return `{"type":"data","data":${devalue.stringify(node.data, reducers)},${stringify_uses(
node
)}${node.slash ? `,"slash":${JSON.stringify(node.slash)}` : ""}}`;
});
return {
data: `{"type":"data","nodes":[${strings.join(",")}]}
`,
chunks: count > 0 ? iterator : null
};
} catch (e) {
throw new Error(clarify_devalue_error(
event,
/** @type {any} */
e
));
}
}
const MAX_DEPTH = 10;
async function render_page(event, page, options2, manifest, state, resolve_opts) {
if (state.depth > MAX_DEPTH) {
return text(`Not found: ${event.url.pathname}`, {
status: 404
// TODO in some cases this should be 500. not sure how to differentiate
});
}
if (is_action_json_request(event)) {
const node = await manifest._.nodes[page.leaf]();
return handle_action_json_request(event, options2, node?.server);
}
try {
const nodes = await Promise.all([
// we use == here rather than === because [undefined] serializes as "[null]"
...page.layouts.map((n) => n == void 0 ? n : manifest._.nodes[n]()),
manifest._.nodes[page.leaf]()
]);
const leaf_node = (
/** @type {import('types').SSRNode} */
nodes.at(-1)
);
let status = 200;
let action_result = void 0;
if (is_action_request(event)) {
action_result = await handle_action_request(event, leaf_node.server);
if (action_result?.type === "redirect") {
return redirect_response(action_result.status, action_result.location);
}
if (action_result?.type === "error") {
const error2 = action_result.error;
status = error2 instanceof HttpError ? error2.status : 500;
}
if (action_result?.type === "failure") {
status = action_result.status;
}
}
const should_prerender_data = nodes.some((node) => node?.server);
const data_pathname = add_data_suffix(event.url.pathname);
const should_prerender = get_option(nodes, "prerender") ?? false;
if (should_prerender) {
const mod = leaf_node.server;
if (mod?.actions) {
throw new Error("Cannot prerender pages with actions");
}
} else if (state.prerendering) {
return new Response(void 0, {
status: 204
});
}
state.prerender_default = should_prerender;
const fetched = [];
if (get_option(nodes, "ssr") === false) {
return await render_response({
branch: [],
fetched,
page_config: {
ssr: false,
csr: get_option(nodes, "csr") ?? true
},
status,
error: null,
event,
options: options2,
manifest,
state,
resolve_opts
});
}
let branch = [];
let load_error = null;
const server_promises = nodes.map((node, i) => {
if (load_error) {
throw load_error;
}
return Promise.resolve().then(async () => {
try {
if (node === leaf_node && action_result?.type === "error") {
throw action_result.error;
}
return await load_server_data({
event,
state,
node,
parent: async () => {
const data = {};
for (let j = 0; j < i; j += 1) {
const parent = await server_promises[j];
if (parent)
Object.assign(data, await parent.data);
}
return data;
}
});
} catch (e) {
load_error = /** @type {Error} */
e;
throw load_error;
}
});
});
const csr = get_option(nodes, "csr") ?? true;
const load_promises = nodes.map((node, i) => {
if (load_error)
throw load_error;
return Promise.resolve().then(async () => {
try {
return await load_data({
event,
fetched,
node,
parent: async () => {
const data = {};
for (let j = 0; j < i; j += 1) {
Object.assign(data, await load_promises[j]);
}
return data;
},
resolve_opts,
server_data_promise: server_promises[i],
state,
csr
});
} catch (e) {
load_error = /** @type {Error} */
e;
throw load_error;
}
});
});
for (const p of server_promises)
p.catch(() => {
});
for (const p of load_promises)
p.catch(() => {
});
for (let i = 0; i < nodes.length; i += 1) {
const node = nodes[i];
if (node) {
try {
const server_data = await server_promises[i];
const data = await load_promises[i];
branch.push({ node, server_data, data });
} catch (e) {
const err = normalize_error(e);
if (err instanceof Redirect) {
if (state.prerendering && should_prerender_data) {
const body = JSON.stringify({
type: "redirect",
location: err.location
});
state.prerendering.dependencies.set(data_pathname, {
response: text(body),
body
});
}
return redirect_response(err.status, err.location);
}
const status2 = err instanceof HttpError ? err.status : 500;
const error2 = await handle_error_and_jsonify(event, options2, err);
while (i--) {
if (page.errors[i]) {
const index = (
/** @type {number} */
page.errors[i]
);
const node2 = await manifest._.nodes[index]();
let j = i;
while (!branch[j])
j -= 1;
return await render_response({
event,
options: options2,
manifest,
state,
resolve_opts,
page_config: { ssr: true, csr: true },
status: status2,
error: error2,
branch: compact(branch.slice(0, j + 1)).concat({
node: node2,
data: null,
server_data: null
}),
fetched
});
}
}
return static_error_page(options2, status2, error2.message);
}
} else {
branch.push(null);
}
}
if (state.prerendering && should_prerender_data) {
let { data, chunks } = get_data_json(
event,
options2,
branch.map((node) => node?.server_data)
);
if (chunks) {
for await (const chunk of chunks) {
data += chunk;
}
}
state.prerendering.dependencies.set(data_pathname, {
response: text(data),
body: data
});
}
return await render_response({
event,
options: options2,
manifest,
state,
resolve_opts,
page_config: {
csr: get_option(nodes, "csr") ?? true,
ssr: true
},
status,
error: null,
branch: compact(branch),
action_result,
fetched
});
} catch (e) {
return await respond_with_error({
event,
options: options2,
manifest,
state,
status: 500,
error: e,
resolve_opts
});
}
}
function exec(match, params, matchers) {
const result = {};
const values = match.slice(1);
let buffered = 0;
for (let i = 0; i < params.length; i += 1) {
const param = params[i];
const value = values[i - buffered];
if (param.chained && param.rest && buffered) {
result[param.name] = values.slice(i - buffered, i + 1).filter((s2) => s2).join("/");
buffered = 0;
continue;
}
if (value === void 0) {
if (param.rest)
result[param.name] = "";
continue;
}
if (!param.matcher || matchers[param.matcher](value)) {
result[param.name] = value;
const next_param = params[i + 1];
const next_value = values[i + 1];
if (next_param && !next_param.rest && next_param.optional && next_value) {
buffered = 0;
}
continue;
}
if (param.optional && param.chained) {
buffered++;
continue;
}
return;
}
if (buffered)
return;
return result;
}
function get_cookies(request, url, trailing_slash) {
const header = request.headers.get("cookie") ?? "";
const initial_cookies = parse(header, { decode: (value) => value });
const normalized_url = normalize_path(url.pathname, trailing_slash);
const default_path = normalized_url.split("/").slice(0, -1).join("/") || "/";
const new_cookies = {};
const defaults = {
httpOnly: true,
sameSite: "lax",
secure: url.hostname === "localhost" && url.protocol === "http:" ? false : true
};
const cookies = {
// The JSDoc param annotations appearing below for get, set and delete
// are necessary to expose the `cookie` library types to
// typescript users. `@type {import('types').Cookies}` above is not
// sufficient to do so.
/**
* @param {string} name
* @param {import('cookie').CookieParseOptions} opts
*/
get(name, opts) {
const c = new_cookies[name];
if (c && domain_matches(url.hostname, c.options.domain) && path_matches(url.pathname, c.options.path)) {
return c.value;
}
const decoder = opts?.decode || decodeURIComponent;
const req_cookies = parse(header, { decode: decoder });
const cookie = req_cookies[name];
return cookie;
},
/**
* @param {import('cookie').CookieParseOptions} opts
*/
getAll(opts) {
const decoder = opts?.decode || decodeURIComponent;
const cookies2 = parse(header, { decode: decoder });
for (const c of Object.values(new_cookies)) {
if (domain_matches(url.hostname, c.options.domain) && path_matches(url.pathname, c.options.path)) {
cookies2[c.name] = c.value;
}
}
return Object.entries(cookies2).map(([name, value]) => ({ name, value }));
},
/**
* @param {string} name
* @param {string} value
* @param {import('cookie').CookieSerializeOptions} opts
*/
set(name, value, opts = {}) {
let path = opts.path ?? default_path;
new_cookies[name] = {
name,
value,
options: {
...defaults,
...opts,
path
}
};
},
/**
* @param {string} name
* @param {import('cookie').CookieSerializeOptions} opts
*/
delete(name, opts = {}) {
cookies.set(name, "", {
...opts,
maxAge: 0
});
},
/**
* @param {string} name
* @param {string} value
* @param {import('cookie').CookieSerializeOptions} opts
*/
serialize(name, value, opts) {
return serialize(name, value, {
...defaults,
...opts
});
}
};
function get_cookie_header(destination, header2) {
const combined_cookies = {
// cookies sent by the user agent have lowest precedence
...initial_cookies
};
for (const key2 in new_cookies) {
const cookie = new_cookies[key2];
if (!domain_matches(destination.hostname, cookie.options.domain))
continue;
if (!path_matches(destination.pathname, cookie.options.path))
continue;
const encoder2 = cookie.options.encode || encodeURIComponent;
combined_cookies[cookie.name] = encoder2(cookie.value);
}
if (header2) {
const parsed = parse(header2, { decode: (value) => value });
for (const name in parsed) {
combined_cookies[name] = parsed[name];
}
}
return Object.entries(combined_cookies).map(([name, value]) => `${name}=${value}`).join("; ");
}
return { cookies, new_cookies, get_cookie_header };
}
function domain_matches(hostname, constraint) {
if (!constraint)
return true;
const normalized = constraint[0] === "." ? constraint.slice(1) : constraint;
if (hostname === normalized)
return true;
return hostname.endsWith("." + normalized);
}
function path_matches(path, constraint) {
if (!constraint)
return true;
const normalized = constraint.endsWith("/") ? constraint.slice(0, -1) : constraint;
if (path === normalized)
return true;
return path.startsWith(normalized + "/");
}
function add_cookies_to_headers(headers, cookies) {
for (const new_cookie of cookies) {
const { name, value, options: options2 } = new_cookie;
headers.append("set-cookie", serialize(name, value, options2));
}
}
function create_fetch({ event, options: options2, manifest, state, get_cookie_header }) {
return async (info, init2) => {
const original_request = normalize_fetch_input(info, init2, event.url);
const request_body = init2?.body;
let mode = (info instanceof Request ? info.mode : init2?.mode) ?? "cors";
let credentials = (info instanceof Request ? info.credentials : init2?.credentials) ?? "same-origin";
return await options2.hooks.handleFetch({
event,
request: original_request,
fetch: async (info2, init3) => {
const request = normalize_fetch_input(info2, init3, event.url);
const url = new URL(request.url);
if (!request.headers.has("origin")) {
request.headers.set("origin", event.url.origin);
}
if (info2 !== original_request) {
mode = (info2 instanceof Request ? info2.mode : init3?.mode) ?? "cors";
credentials = (info2 instanceof Request ? info2.credentials : init3?.credentials) ?? "same-origin";
}
if ((request.method === "GET" || request.method === "HEAD") && (mode === "no-cors" && url.origin !== event.url.origin || url.origin === event.url.origin)) {
request.headers.delete("origin");
}
if (url.origin !== event.url.origin) {
if (`.${url.hostname}`.endsWith(`.${event.url.hostname}`) && credentials !== "omit") {
const cookie = get_cookie_header(url, request.headers.get("cookie"));
if (cookie)
request.headers.set("cookie", cookie);
}
return fetch(request);
}
let response;
const prefix = assets || base;
const decoded = decodeURIComponent(url.pathname);
const filename = (decoded.startsWith(prefix) ? decoded.slice(prefix.length) : decoded).slice(1);
const filename_html = `${filename}/index.html`;
const is_asset = manifest.assets.has(filename);
const is_asset_html = manifest.assets.has(filename_html);
if (is_asset || is_asset_html) {
const file = is_asset ? filename : filename_html;
if (state.read) {
const type = is_asset ? manifest.mimeTypes[filename.slice(filename.lastIndexOf("."))] : "text/html";
return new Response(state.read(file), {
headers: type ? { "content-type": type } : {}
});
}
return await fetch(request);
}
if (credentials !== "omit") {
const cookie = get_cookie_header(url, request.headers.get("cookie"));
if (cookie) {
request.headers.set("cookie", cookie);
}
const authorization = event.request.headers.get("authorization");
if (authorization && !request.headers.has("authorization")) {
request.headers.set("authorization", authorization);
}
}
if (request_body && typeof request_body !== "string" && !ArrayBuffer.isView(request_body)) {
throw new Error("Request body must be a string or TypedArray");
}
if (!request.headers.has("accept")) {
request.headers.set("accept", "*/*");
}
if (!request.headers.has("accept-language")) {
request.headers.set(
"accept-language",
/** @type {string} */
event.request.headers.get("accept-language")
);
}
response = await respond(request, options2, manifest, {
...state,
depth: state.depth + 1
});
const set_cookie = response.headers.get("set-cookie");
if (set_cookie) {
for (const str of set_cookie_parser.splitCookiesString(set_cookie)) {
const { name, value, ...options3 } = set_cookie_parser.parseString(str);
event.cookies.set(
name,
value,
/** @type {import('cookie').CookieSerializeOptions} */
options3
);
}
}
return response;
}
});
};
}
function normalize_fetch_input(info, init2, url) {
if (info instanceof Request) {
return info;
}
return new Request(typeof info === "string" ? new URL(info, url) : info, init2);
}
function validator(expected) {
const set = new Set(expected);
function validate(module, file) {
if (!module)
return;
for (const key2 in module) {
if (key2[0] === "_" || set.has(key2))
continue;
const hint = hint_for_supported_files(key2, file?.slice(file.lastIndexOf("."))) ?? `valid exports are ${expected.join(", ")}, or anything with a '_' prefix`;
throw new Error(`Invalid export '${key2}'${file ? ` in ${file}` : ""} (${hint})`);
}
}
return validate;
}
function hint_for_supported_files(key2, ext = ".js") {
let supported_files = [];
if (valid_common_exports.includes(key2)) {
supported_files.push(`+page${ext}`);
}
if (valid_page_server_exports.includes(key2)) {
supported_files.push(`+page.server${ext}`);
}
if (valid_server_exports.includes(key2)) {
supported_files.push(`+server${ext}`);
}
if (supported_files.length > 0) {
return `'${key2}' is a valid export in ${supported_files.join(` or `)}`;
}
}
const valid_common_exports = ["load", "prerender", "csr", "ssr", "trailingSlash", "config"];
const valid_page_server_exports = [
"load",
"prerender",
"csr",
"ssr",
"actions",
"trailingSlash",
"config"
];
const valid_server_exports = [
"GET",
"POST",
"PATCH",
"PUT",
"DELETE",
"OPTIONS",
"prerender",
"trailingSlash",
"config"
];
const validate_common_exports = validator(valid_common_exports);
const validate_page_server_exports = validator(valid_page_server_exports);
const validate_server_exports = validator(valid_server_exports);
const default_transform = ({ html }) => html;
const default_filter = () => false;
const default_preload = ({ type }) => type === "js" || type === "css";
async function respond(request, options2, manifest, state) {
let url = new URL(request.url);
if (options2.csrf_check_origin) {
const forbidden = request.method === "POST" && request.headers.get("origin") !== url.origin && is_form_content_type(request);
if (forbidden) {
const csrf_error = error(403, `Cross-site ${request.method} form submissions are forbidden`);
if (request.headers.get("accept") === "application/json") {
return json(csrf_error.body, { status: csrf_error.status });
}
return text(csrf_error.body.message, { status: csrf_error.status });
}
}
let decoded;
try {
decoded = decode_pathname(url.pathname);
} catch {
return text("Malformed URI", { status: 400 });
}
let route = null;
let params = {};
if (base && !state.prerendering?.fallback) {
if (!decoded.startsWith(base)) {
return text("Not found", { status: 404 });
}
decoded = decoded.slice(base.length) || "/";
}
const is_data_request = has_data_suffix(decoded);
let invalidated_data_nodes;
if (is_data_request) {
decoded = strip_data_suffix(decoded) || "/";
url.pathname = strip_data_suffix(url.pathname) || "/";
invalidated_data_nodes = url.searchParams.get(INVALIDATED_PARAM)?.split("_").map(Boolean);
url.searchParams.delete(INVALIDATED_PARAM);
}
if (!state.prerendering?.fallback) {
const matchers = await manifest._.matchers();
for (const candidate of manifest._.routes) {
const match = candidate.pattern.exec(decoded);
if (!match)
continue;
const matched = exec(match, candidate.params, matchers);
if (matched) {
route = candidate;
params = decode_params(matched);
break;
}
}
}
let trailing_slash = void 0;
const headers = {};
let cookies_to_add = {};
const event = {
// @ts-expect-error `cookies` and `fetch` need to be created after the `event` itself
cookies: null,
// @ts-expect-error
fetch: null,
getClientAddress: state.getClientAddress || (() => {
throw new Error(
`${void 0} does not specify getClientAddress. Please raise an issue`
);
}),
locals: {},
params,
platform: state.platform,
request,
route: { id: route?.id ?? null },
setHeaders: (new_headers) => {
for (const key2 in new_headers) {
const lower = key2.toLowerCase();
const value = new_headers[key2];
if (lower === "set-cookie") {
throw new Error(
`Use \`event.cookies.set(name, value, options)\` instead of \`event.setHeaders\` to set cookies`
);
} else if (lower in headers) {
throw new Error(`"${key2}" header is already set`);
} else {
headers[lower] = value;
if (state.prerendering && lower === "cache-control") {
state.prerendering.cache = /** @type {string} */
value;
}
}
}
},
url,
isDataRequest: is_data_request
};
let resolve_opts = {
transformPageChunk: default_transform,
filterSerializedResponseHeaders: default_filter,
preload: default_preload
};
try {
if (route && !is_data_request) {
if (route.page) {
const nodes = await Promise.all([
// we use == here rather than === because [undefined] serializes as "[null]"
...route.page.layouts.map((n) => n == void 0 ? n : manifest._.nodes[n]()),
manifest._.nodes[route.page.leaf]()
]);
if (DEV)
;
trailing_slash = get_option(nodes, "trailingSlash");
} else if (route.endpoint) {
const node = await route.endpoint();
trailing_slash = node.trailingSlash;
if (DEV)
;
}
const normalized = normalize_path(url.pathname, trailing_slash ?? "never");
if (normalized !== url.pathname && !state.prerendering?.fallback) {
return new Response(void 0, {
status: 308,
headers: {
"x-sveltekit-normalize": "1",
location: (
// ensure paths starting with '//' are not treated as protocol-relative
(normalized.startsWith("//") ? url.origin + normalized : normalized) + (url.search === "?" ? "" : url.search)
)
}
});
}
}
const { cookies, new_cookies, get_cookie_header } = get_cookies(
request,
url,
trailing_slash ?? "never"
);
cookies_to_add = new_cookies;
event.cookies = cookies;
event.fetch = create_fetch({ event, options: options2, manifest, state, get_cookie_header });
if (state.prerendering && !state.prerendering.fallback)
disable_search(url);
const response = await options2.hooks.handle({
event,
resolve: (event2, opts) => resolve(event2, opts).then((response2) => {
for (const key2 in headers) {
const value = headers[key2];
response2.headers.set(
key2,
/** @type {string} */
value
);
}
add_cookies_to_headers(response2.headers, Object.values(cookies_to_add));
if (state.prerendering && event2.route.id !== null) {
response2.headers.set("x-sveltekit-routeid", encodeURI(event2.route.id));
}
return response2;
})
});
if (response.status === 200 && response.headers.has("etag")) {
let if_none_match_value = request.headers.get("if-none-match");
if (if_none_match_value?.startsWith('W/"')) {
if_none_match_value = if_none_match_value.substring(2);
}
const etag = (
/** @type {string} */
response.headers.get("etag")
);
if (if_none_match_value === etag) {
const headers2 = new Headers({ etag });
for (const key2 of [
"cache-control",
"content-location",
"date",
"expires",
"vary",
"set-cookie"
]) {
const value = response.headers.get(key2);
if (value)
headers2.set(key2, value);
}
return new Response(void 0, {
status: 304,
headers: headers2
});
}
}
if (is_data_request && response.status >= 300 && response.status <= 308) {
const location = response.headers.get("location");
if (location) {
return redirect_json_response(new Redirect(
/** @type {any} */
response.status,
location
));
}
}
return response;
} catch (e) {
if (e instanceof Redirect) {
const response = is_data_request ? redirect_json_response(e) : redirect_response(e.status, e.location);
add_cookies_to_headers(response.headers, Object.values(cookies_to_add));
return response;
}
return await handle_fatal_error(event, options2, e);
}
async function resolve(event2, opts) {
try {
if (opts) {
if ("ssr" in opts) {
throw new Error(
"ssr has been removed, set it in the appropriate +layout.js instead. See the PR for more information: https://github.com/sveltejs/kit/pull/6197"
);
}
resolve_opts = {
transformPageChunk: opts.transformPageChunk || default_transform,
filterSerializedResponseHeaders: opts.filterSerializedResponseHeaders || default_filter,
preload: opts.preload || default_preload
};
}
if (state.prerendering?.fallback) {
return await render_response({
event: event2,
options: options2,
manifest,
state,
page_config: { ssr: false, csr: true },
status: 200,
error: null,
branch: [],
fetched: [],
resolve_opts
});
}
if (route) {
let response;
if (is_data_request) {
response = await render_data(
event2,
route,
options2,
manifest,
state,
invalidated_data_nodes,
trailing_slash ?? "never"
);
} else if (route.endpoint && (!route.page || is_endpoint_request(event2))) {
response = await render_endpoint(event2, await route.endpoint(), state);
} else if (route.page) {
response = await render_page(event2, route.page, options2, manifest, state, resolve_opts);
} else {
throw new Error("This should never happen");
}
return response;
}
if (state.error) {
return text("Internal Server Error", {
status: 500
});
}
if (state.depth === 0) {
return await respond_with_error({
event: event2,
options: options2,
manifest,
state,
status: 404,
error: new Error(`Not found: ${event2.url.pathname}`),
resolve_opts
});
}
if (state.prerendering) {
return text("not found", { status: 404 });
}
return await fetch(request);
} catch (e) {
return await handle_fatal_error(event2, options2, e);
} finally {
event2.cookies.set = () => {
throw new Error("Cannot use `cookies.set(...)` after the response has been generated");
};
event2.setHeaders = () => {
throw new Error("Cannot use `setHeaders(...)` after the response has been generated");
};
}
}
}
class Server {
/** @type {import('types').SSROptions} */
#options;
/** @type {import('types').SSRManifest} */
#manifest;
/** @param {import('types').SSRManifest} manifest */
constructor(manifest) {
this.#options = options;
this.#manifest = manifest;
}
/**
* @param {{
* env: Record<string, string>
* }} opts
*/
async init({ env }) {
const entries = Object.entries(env);
const prefix = this.#options.env_public_prefix;
Object.fromEntries(entries.filter(([k]) => !k.startsWith(prefix)));
const pub = Object.fromEntries(entries.filter(([k]) => k.startsWith(prefix)));
set_public_env(pub);
if (!this.#options.hooks) {
const module = await get_hooks();
this.#options.hooks = {
handle: module.handle || (({ event, resolve }) => resolve(event)),
// @ts-expect-error
handleError: module.handleError || (({ error: error2 }) => console.error(error2?.stack)),
handleFetch: module.handleFetch || (({ request, fetch: fetch2 }) => fetch2(request))
};
}
}
/**
* @param {Request} request
* @param {import('types').RequestOptions} options
*/
async respond(request, options2) {
if (!(request instanceof Request)) {
throw new Error(
"The first argument to server.respond must be a Request object. See https://github.com/sveltejs/kit/pull/3384 for details"
);
}
return respond(request, this.#options, this.#manifest, {
...options2,
error: false,
depth: 0
});
}
}
export {
Server
};