@torpor/build 1.4.2 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev.mjs +1 -1
- package/dist/{serverEntry-CnCVNNjp.mjs → serverEntry-D3uwudkX.mjs} +2 -2
- package/dist/{serverEntry-CnCVNNjp.mjs.map → serverEntry-D3uwudkX.mjs.map} +1 -1
- package/dist/serverEntry.mjs +1 -1
- package/dist/{serverHandlers-B6EcNfBP.mjs → serverHandlers-C8qzOSX-.mjs} +8 -7
- package/dist/serverHandlers-C8qzOSX-.mjs.map +1 -0
- package/dist/test.mjs +1 -1
- package/package.json +1 -1
- package/dist/serverHandlers-B6EcNfBP.mjs.map +0 -1
package/dist/dev.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as Router } from "./Router-C4ADUfhv.mjs";
|
|
2
2
|
import { o as setBasePath } from "./basePath-DQnbHc7o.mjs";
|
|
3
|
-
import { t as createServerLoad } from "./serverHandlers-
|
|
3
|
+
import { t as createServerLoad } from "./serverHandlers-C8qzOSX-.mjs";
|
|
4
4
|
import manifest from "@torpor/build/manifest";
|
|
5
5
|
//#region src/site/serverEntry.ts
|
|
6
6
|
setBasePath(manifest.base);
|
|
@@ -10,4 +10,4 @@ const load = createServerLoad(router, manifest.base, manifest.middleware ?? []);
|
|
|
10
10
|
//#endregion
|
|
11
11
|
export { router as n, load as t };
|
|
12
12
|
|
|
13
|
-
//# sourceMappingURL=serverEntry-
|
|
13
|
+
//# sourceMappingURL=serverEntry-D3uwudkX.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serverEntry-
|
|
1
|
+
{"version":3,"file":"serverEntry-D3uwudkX.mjs","names":[],"sources":["../src/site/serverEntry.ts"],"sourcesContent":["import manifest from \"@torpor/build/manifest\";\nimport Router from \"./Router.ts\";\nimport { setBasePath } from \"./basePath.ts\";\nimport { type ServerLoad, createServerLoad } from \"./serverHandlers.ts\";\n\n// Put adapter-specific functionality in the `adapter` property of\n// globalThis for now\nsetBasePath(manifest.base);\n\n// Build the router from the Site object created by the user\nexport const router: Router = new Router();\nrouter.addPages(manifest.routes);\n\n//console.log(`routes:\\n ${router.routes.map((r) => r.path).join(\"\\n \")}`);\n\nexport const load: ServerLoad = createServerLoad(router, manifest.base, manifest.middleware ?? []);\n"],"mappings":";;;;;AAOA,YAAY,SAAS,IAAI;AAGzB,MAAa,SAAiB,IAAI,OAAO;AACzC,OAAO,SAAS,SAAS,MAAM;AAI/B,MAAa,OAAmB,iBAAiB,QAAQ,SAAS,MAAM,SAAS,cAAc,CAAC,CAAC"}
|
package/dist/serverEntry.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as router, t as load } from "./serverEntry-
|
|
1
|
+
import { n as router, t as load } from "./serverEntry-D3uwudkX.mjs";
|
|
2
2
|
export { load, router };
|
|
@@ -309,7 +309,7 @@ async function loadData(ev, url, handler, functionName, params) {
|
|
|
309
309
|
throw error;
|
|
310
310
|
}
|
|
311
311
|
}
|
|
312
|
-
async function loadView(ev, url, handler, params, template, formStatus, form, fromForm) {
|
|
312
|
+
async function loadView(ev, url, handler, params, template, formStatus, form, fromForm, appData) {
|
|
313
313
|
const clientEndPoint = (await resolveModule(handler)).default;
|
|
314
314
|
if (!clientEndPoint?.component) return notFound();
|
|
315
315
|
$page.flash = ev.flash.get();
|
|
@@ -338,7 +338,7 @@ async function loadView(ev, url, handler, params, template, formStatus, form, fr
|
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
|
-
const serverParams = buildServerParams(ev, url, params, query ? { query } : {});
|
|
341
|
+
const serverParams = buildServerParams(ev, url, params, query ? { query } : {}, appData);
|
|
342
342
|
const serverHooks = fromForm ? [] : await loadServerHooks(handler);
|
|
343
343
|
let entered = 0;
|
|
344
344
|
let enterResponse = void 0;
|
|
@@ -442,10 +442,11 @@ async function runAction(ev, url, handler, serverEndPoint, params, query, templa
|
|
|
442
442
|
throw error;
|
|
443
443
|
}
|
|
444
444
|
let result;
|
|
445
|
+
let serverParams = void 0;
|
|
445
446
|
try {
|
|
446
447
|
const schema = endpointSchema(serverEndPoint, actionName);
|
|
447
448
|
const form = schema ? await validate(schema, await formDataToRecord(ev.request)) : void 0;
|
|
448
|
-
|
|
449
|
+
serverParams = buildServerParams(ev, url, params, form ? { form } : {});
|
|
449
450
|
const serverHooks = await loadServerHooks(handler);
|
|
450
451
|
let entered = 0;
|
|
451
452
|
let enterResponse = void 0;
|
|
@@ -485,7 +486,7 @@ async function runAction(ev, url, handler, serverEndPoint, params, query, templa
|
|
|
485
486
|
} else $page.form = {};
|
|
486
487
|
$page.form.status ??= formStatus ?? 0;
|
|
487
488
|
$page.form.message ??= formMessage ?? "";
|
|
488
|
-
return await loadView(ev, newUrl, handler, params, template, formStatus, $page.form, true);
|
|
489
|
+
return await loadView(ev, newUrl, handler, params, template, formStatus, $page.form, true, serverParams?.appData);
|
|
489
490
|
} else return result;
|
|
490
491
|
}
|
|
491
492
|
}
|
|
@@ -517,11 +518,11 @@ function buildClientParams(url, params, data) {
|
|
|
517
518
|
data
|
|
518
519
|
};
|
|
519
520
|
}
|
|
520
|
-
function buildServerParams(ev, url, params, values = {}) {
|
|
521
|
+
function buildServerParams(ev, url, params, values = {}, appData = {}) {
|
|
521
522
|
return {
|
|
522
523
|
url,
|
|
523
524
|
params,
|
|
524
|
-
appData
|
|
525
|
+
appData,
|
|
525
526
|
request: ev.request,
|
|
526
527
|
json: () => values.json !== void 0 ? Promise.resolve(values.json) : ev.json(),
|
|
527
528
|
form: () => values.form !== void 0 ? Promise.resolve(values.form) : formDataToRecord(ev.request),
|
|
@@ -548,4 +549,4 @@ function escapeHtml(value) {
|
|
|
548
549
|
//#endregion
|
|
549
550
|
export { createServerLoad as t };
|
|
550
551
|
|
|
551
|
-
//# sourceMappingURL=serverHandlers-
|
|
552
|
+
//# sourceMappingURL=serverHandlers-C8qzOSX-.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serverHandlers-C8qzOSX-.mjs","names":[],"sources":["../src/form/formDataToRecord.ts","../src/state/$serverPage.ts","../src/utils/searchParamsToRecord.ts","../src/validation/endpoint.ts","../src/site/layoutSlots.ts","../src/site/mergeHead.ts","../src/site/serverHandlers.ts"],"sourcesContent":["import type { FormDataRecord } from \"../types/ServerLoadEvent\";\n\n/**\n * Converts the submitted fields of a form request into a plain record: one\n * value per field, or an array when a field was submitted with multiple\n * values (e.g. a multi select). File inputs pass through as `File` values;\n * coercing them is left to the schema or the action.\n *\n * @param request The request (or FormData directly)\n * @returns The field values\n */\nexport default async function formDataToRecord(\n\trequest: Request | FormData,\n): Promise<FormDataRecord> {\n\tconst formData = request instanceof FormData ? request : await request.formData();\n\tconst result: FormDataRecord = {};\n\tfor (const key of formData.keys()) {\n\t\tif (key in result) continue;\n\t\tconst values = formData.getAll(key);\n\t\tresult[key] = values.length > 1 ? values : values[0];\n\t}\n\treturn result;\n}\n","import { $watch } from \"@torpor/view/ssr\";\nimport type PageState from \"../types/PageState\";\n\nconst PAGE_SYMBOL: unique symbol = Symbol.for(\"torp.Page\");\n\n// The server request path has no reactive subscribers, so the state is\n// stored plainly ($watch from `@torpor/view/ssr` is a no-op that returns\n// the object itself) instead of through a reactive proxy. Shares the same\n// `globalThis` slot as the client `$page`, so both variants always see the\n// same state object whichever loads first.\nconst $page: PageState =\n\t// @ts-ignore\n\t(globalThis[PAGE_SYMBOL] ??= $watch({\n\t\tstatus: 404,\n\t\turl: new URL(\"http://localhost\"),\n\t\tform: undefined,\n\t\tflash: undefined,\n\t\terror: {\n\t\t\tmessage: \"\",\n\t\t},\n\t}));\n\nexport default $page;\n","import type { QueryRecord } from \"../types/ServerLoadEvent\";\n\n/**\n * Converts a URL's query string into a plain record: one string per param,\n * or an array when a param was repeated.\n *\n * @param searchParams The URL's search params\n * @returns The param values\n */\nexport default function searchParamsToRecord(searchParams: URLSearchParams): QueryRecord {\n\tconst result: QueryRecord = {};\n\tfor (const key of searchParams.keys()) {\n\t\tif (key in result) continue;\n\t\tconst values = searchParams.getAll(key);\n\t\tresult[key] = values.length > 1 ? values : values[0];\n\t}\n\treturn result;\n}\n","import type PageServerEndPoint from \"../types/PageServerEndPoint\";\nimport type ServerEndPoint from \"../types/ServerEndPoint\";\nimport type { StandardSchemaV1 } from \"../types/StandardSchema\";\nimport type ServerEvent from \"../server/ServerEvent\";\nimport searchParamsToRecord from \"../utils/searchParamsToRecord\";\nimport unprocessable from \"../response/unprocessable\";\nimport ValidationError from \"./ValidationError\";\nimport validate from \"./validate\";\n\n/**\n * Loose views of an endpoint's schema map, keyed by handler/action name (plus\n * the reserved `params` key). The type-level constraint differs per endpoint\n * type, but the runtime treats them the same.\n */\ntype Schemas = Record<string, StandardSchemaV1 | undefined>;\n\ntype EndPoint = ServerEndPoint | PageServerEndPoint;\n\n/**\n * Gets the standard schema declared for a handler or action, if any. The\n * schemas map is keyed by name; the runtime treats it as a loose record.\n */\nexport function endpointSchema(endPoint: EndPoint, name: string): StandardSchemaV1 | undefined {\n\treturn (endPoint.schema as Schemas | undefined)?.[name];\n}\n\n/**\n * Validates the route params against the endpoint's `params` schema, if it\n * declares one, returning the coerced params. Throws a ValidationError when\n * they don't match, which callers turn into a 404 (params come from the URL,\n * so a failed validation means the resource doesn't exist).\n *\n * @param endPoint The endpoint declaring the (optional) `params` schema\n * @param params The route params from the matched route\n * @returns The validated params\n */\nexport async function validateEndpointParams(\n\tendPoint: EndPoint,\n\tparams: Record<string, any>,\n): Promise<Record<string, any>> {\n\tconst schema = endpointSchema(endPoint, \"params\");\n\treturn schema ? ((await validate(schema, params)) as Record<string, any>) : params;\n}\n\n/**\n * Validates a handler's input against its schema: get/head handlers and load\n * functions validate the URL's query string, other handlers validate the JSON\n * request body. Returns the validated values (an empty object when no schema\n * is declared), which callers pass through to the handler's event.\n *\n * @param schema The handler's (optional) schema\n * @param functionName The handler name (`get`, `post`, `load`, etc)\n * @param url The request URL, for the query string\n * @param ev The server event, for the request body\n * @returns The validated values\n */\nexport async function validateHandlerInput(\n\tschema: StandardSchemaV1 | undefined,\n\tfunctionName: string,\n\turl: URL,\n\tev: ServerEvent,\n): Promise<{ json?: unknown; form?: unknown; query?: unknown }> {\n\tif (!schema) return {};\n\tif (functionName === \"get\" || functionName === \"head\" || functionName === \"load\") {\n\t\treturn { query: await validate(schema, searchParamsToRecord(url.searchParams)) };\n\t}\n\treturn { json: await validate(schema, await ev.json()) };\n}\n\n/**\n * Turns a ValidationError thrown during endpoint validation into a 422\n * response with the schema's issues. Returns undefined for any other error,\n * which callers should rethrow.\n *\n * @param error The error thrown by a handler or validation\n * @returns A 422 response, or undefined when the error isn't a validation failure\n */\nexport function validationErrorResponse(error: unknown): Response | undefined {\n\tif (error instanceof ValidationError) {\n\t\treturn unprocessable({ message: error.message, issues: error.issues });\n\t}\n\treturn undefined;\n}\n","/**\n * Layouts are composed by the layout engine passing each layout (and finally\n * the page) as the default slot of its parent — so every `_layout` component\n * must render `<slot />`, or pass the default slot down to a child component\n * it renders. A layout that doesn't drops its entire content: the server\n * renders the layout's own markup with an empty content area (no error), and\n * the first client-side navigation that reuses the layout crashes on a null\n * slot region.\n *\n * The static `checkLayoutSlots` check catches this at build/dev time; these\n * helpers report it at request time for the cases static analysis can't see\n * (e.g. a `<slot />` rendered conditionally inside `@if`). They are\n * server-side only — nothing here is imported into the client bundle.\n */\n\n/**\n * Returns the path of the outermost layout that never rendered its\n * `<slot />`, or undefined when every level rendered.\n *\n * Slot level j (1-based) is the slot render that layout j - 1 receives: the\n * root layout (layouts[0]) renders level 1, layout i renders level i + 1,\n * and level layouts.length renders the page. A broken level makes every\n * deeper level unreachable, so the first level that never ran identifies\n * the offending layout.\n */\nexport function findMissingSlotLayout(\n\tlayouts: readonly { path: string }[],\n\tinvokedLevels: ReadonlySet<number>,\n): string | undefined {\n\tfor (let level = 1; level <= layouts.length; level++) {\n\t\tif (!invokedLevels.has(level)) {\n\t\t\treturn layouts[level - 1].path;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nconst warnedLayouts = new Set<string>();\n\n/**\n * Reports a layout that dropped its slot content. The condition is a genuine\n * rendering bug (the page content is missing from the output), so it is not\n * dev-gated — but it warns only once per layout path to avoid per-request\n * noise.\n */ export function warnMissingSlotContent(layoutPath: string): void {\n\tif (warnedLayouts.has(layoutPath)) return;\n\twarnedLayouts.add(layoutPath);\n\tconsole.warn(\n\t\t`[torpor] The layout at \"${layoutPath}\" never rendered <slot />, so the page content ` +\n\t\t\t`was not included in the render. Every _layout component must render <slot /> (or ` +\n\t\t\t`pass the default slot down to a child component it renders).`,\n\t);\n}\n","const TITLE_REGEX = /<title(?:\\s[^>]*)?>[\\s\\S]*?<\\/title>/g;\nconst FIRST_TITLE_REGEX = /<title(?:\\s[^>]*)?>[\\s\\S]*?<\\/title>/;\n\n/**\n * Merges the head string rendered by a page (and its layouts) into the site\n * template. The first <title> in the head string -- the page's, since pages\n * render before the layouts around them -- wins, overriding both any later\n * component title (e.g. from a child component) and a static <title> in the\n * template itself. All other head content (styles, meta elements, etc) is\n * appended where %COMPONENT_HEAD% sits in the template, before </head>.\n */\nexport default function mergeHead(template: string, head: string): string {\n\tconst titles = head.match(TITLE_REGEX);\n\tlet html = template;\n\tlet headHtml = head;\n\tif (titles?.length) {\n\t\theadHtml = head.replace(TITLE_REGEX, \"\");\n\t\thtml = html.replace(FIRST_TITLE_REGEX, \"\");\n\t\theadHtml = titles[0] + headHtml;\n\t}\n\treturn html.replace(\"%COMPONENT_HEAD%\", headHtml);\n}\n","import { type ServerComponent, type ServerSlotRender } from \"@torpor/view/ssr\";\nimport formDataToRecord from \"../form/formDataToRecord.ts\";\nimport notFound from \"../response/notFound.ts\";\nimport ok from \"../response/ok.ts\";\nimport seeOther from \"../response/seeOther.ts\";\nimport ServerEvent from \"../server/ServerEvent.ts\";\nimport type MiddlewareFunction from \"../server/types/MiddlewareFunction\";\nimport $page from \"../state/$serverPage.ts\";\nimport type PageEndPoint from \"../types/PageEndPoint.ts\";\nimport type { HeadElement } from \"../types/PageEndPoint.ts\";\nimport type PageLoadEvent from \"../types/PageLoadEvent.ts\";\nimport type PageServerEndPoint from \"../types/PageServerEndPoint.ts\";\nimport type RouteHandler from \"../types/RouteHandler.ts\";\nimport type ServerRequest from \"../types/ServerRequest.ts\";\nimport {\n\tERROR_ROUTE,\n\tHOOK_ROUTE,\n\tHOOK_SERVER_ROUTE,\n\tLAYOUT_ROUTE,\n\tLAYOUT_SERVER_ROUTE,\n\tPAGE_ROUTE,\n\tPAGE_SERVER_ROUTE,\n\tSERVER_ROUTE,\n} from \"../types/RouteType\";\nimport type ServerEndPoint from \"../types/ServerEndPoint.ts\";\nimport type ServerHook from \"../types/ServerHook.ts\";\nimport type ServerLoadEvent from \"../types/ServerLoadEvent.ts\";\nimport searchParamsToRecord from \"../utils/searchParamsToRecord.ts\";\nimport validate from \"../validation/validate.ts\";\nimport ValidationError from \"../validation/ValidationError.ts\";\nimport {\n\tendpointSchema,\n\tvalidateEndpointParams,\n\tvalidationErrorResponse,\n} from \"../validation/endpoint.ts\";\nimport { findMissingSlotLayout, warnMissingSlotContent } from \"./layoutSlots.ts\";\nimport { getBasePath, rewriteBaseInHtml, setBasePath, stripBaseFromUrl } from \"./basePath.ts\";\nimport mergeHead from \"./mergeHead.ts\";\nimport type Router from \"./Router.ts\";\n\n/**\n * The site's request handler, as created by `createServerLoad`.\n */\nexport type ServerLoad = (ev: ServerEvent, template?: string) => Promise<Response>;\n\n/**\n * Creates the site's request handler for the given router. This is kept\n * separate from serverEntry, which imports the virtual\n * `@torpor/build/manifest` module (it only exists when a site runs or\n * builds), so that tests can exercise the handlers with their own routes.\n *\n * @param router The router, built from the site's routes\n * @param basePath The site's base path, stripped from incoming URLs before\n * routing (see basePath.ts)\n * @param middleware Global middleware (from `site.middleware`), run for\n * every request before routing -- including requests that won't match a\n * route\n * @returns The request handler, which takes the site template\n */\nexport function createServerLoad(\n\trouter: Router,\n\tbasePath = \"\",\n\tmiddleware: MiddlewareFunction[] = [],\n): ServerLoad {\n\t// The base path is shared through module state, so that everything that\n\t// generates URLs (HTML attributes, redirect locations) sees the same\n\t// value the router strips\n\tsetBasePath(basePath);\n\n\tconst handle = async (ev: ServerEvent, template?: string): Promise<Response> => {\n\t\t// The base is stripped before routing, so that everything below (route\n\t\t// matching, params, user code reading `event.url`) is base-free.\n\t\t// Requests that don't carry the base aren't ours\n\t\tconst url = stripBaseFromUrl(ev.url, basePath);\n\t\tif (!url) {\n\t\t\treturn handleResponse(notFound());\n\t\t}\n\t\tconst path = url.pathname;\n\t\tconst query = url.searchParams;\n\n\t\t//console.log(`handling ${ev.request.method} for '${path}'${query.size ? ` with ${query}` : \"\"}`);\n\n\t\tlet route = router.match(path, query);\n\t\tif (!route) {\n\t\t\t// If the route wasn't found, the user may be posting a form to a\n\t\t\t// +page.server.ts route that doesn't have a corresponding +page.ts\n\t\t\t// route, which is allowed, so check for that as well\n\t\t\tif (ev.request.method === \"POST\" && !path.endsWith(\"/~server\")) {\n\t\t\t\tconst serverPath =\n\t\t\t\t\t(path.endsWith(\"/\") ? path.substring(0, path.length - 1) : path) + \"/~server\";\n\t\t\t\troute = router.match(serverPath, query);\n\t\t\t}\n\t\t}\n\t\tif (!route) {\n\t\t\treturn handleResponse(notFound());\n\t\t}\n\t\tconst handler = route.handler;\n\t\tconst params = route.params || {};\n\n\t\t// Route middleware, declared on the route's server endpoint\n\t\t// (+page.server.ts / +server.ts). Runs after the global middleware and\n\t\t// before folder hooks, so a guard can skip data loading entirely\n\t\tconst routeMiddleware: MiddlewareFunction[] = [];\n\t\tconst endPointModule = handler.serverEndPoint\n\t\t\t? (await handler.serverEndPoint())?.default\n\t\t\t: handler.type === PAGE_SERVER_ROUTE || handler.type === SERVER_ROUTE\n\t\t\t\t? (await resolveModule(handler))?.default\n\t\t\t\t: undefined;\n\t\tif (Array.isArray(endPointModule?.middleware)) {\n\t\t\trouteMiddleware.push(...endPointModule.middleware);\n\t\t}\n\n\t\t// Update $page before building the components\n\t\t$page.url = url;\n\t\tif (path.endsWith(\"/_error\")) {\n\t\t\t$page.status = parseInt(query.get(\"status\") ?? \"404\");\n\t\t\t$page.error = { message: query.get(\"message\") ?? \"\" };\n\t\t} else {\n\t\t\t$page.status = 200;\n\t\t}\n\n\t\t// TODO: Hit the server hook out here\n\t\t// We could maybe set up data loading as middleware on a route??????\n\n\t\t// Run the route's middleware around the handler: enter hooks in order\n\t\t// (a Response short-circuits the request), exit hooks in reverse\n\t\tlet enteredRoute = 0;\n\t\tlet routeResponse: Response | undefined = undefined;\n\t\ttry {\n\t\t\tfor (; enteredRoute < routeMiddleware.length && !routeResponse; enteredRoute++) {\n\t\t\t\tconst result = await routeMiddleware[enteredRoute].enter?.(ev);\n\t\t\t\tif (result) {\n\t\t\t\t\trouteResponse = result;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (routeResponse) {\n\t\t\t\treturn routeResponse;\n\t\t\t}\n\n\t\t\tswitch (handler.type) {\n\t\t\t\tcase PAGE_ROUTE:\n\t\t\t\tcase LAYOUT_ROUTE: {\n\t\t\t\t\t// It's a /+page.ts or /_layout.ts endpoint\n\t\t\t\t\tif (ev.request.method === \"GET\") {\n\t\t\t\t\t\treturn handleResponse(await loadView(ev, url, handler, params, template));\n\t\t\t\t\t} else if (ev.request.method === \"POST\") {\n\t\t\t\t\t\t// The server end point comes from the sibling /+page.server.ts, if applicable\n\t\t\t\t\t\tconst serverEndPoint: PageServerEndPoint | undefined =\n\t\t\t\t\t\t\thandler.serverEndPoint && (await handler.serverEndPoint()).default;\n\t\t\t\t\t\treturn handleResponse(\n\t\t\t\t\t\t\tawait runAction(ev, url, handler, serverEndPoint, params, query, template),\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase PAGE_SERVER_ROUTE:\n\t\t\t\tcase LAYOUT_SERVER_ROUTE: {\n\t\t\t\t\t// It's a /+page.server.ts or /_layout.server.ts endpoint\n\t\t\t\t\tif (ev.request.method === \"GET\") {\n\t\t\t\t\t\treturn await loadData(ev, url, handler, \"load\", params);\n\t\t\t\t\t} else if (ev.request.method === \"POST\") {\n\t\t\t\t\t\tconst serverEndPoint: PageServerEndPoint | undefined = (await resolveModule(handler))\n\t\t\t\t\t\t\t.default;\n\t\t\t\t\t\treturn handleResponse(\n\t\t\t\t\t\t\tawait runAction(ev, url, handler, serverEndPoint, params, query, template),\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase SERVER_ROUTE: {\n\t\t\t\t\t// It's a /+server.ts endpoint\n\t\t\t\t\tconst functionName = ev.request.method.toLowerCase().replace(\"delete\", \"del\");\n\t\t\t\t\treturn await loadData(ev, url, handler, functionName, params);\n\t\t\t\t}\n\t\t\t\tcase HOOK_ROUTE:\n\t\t\t\tcase HOOK_SERVER_ROUTE: {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase ERROR_ROUTE: {\n\t\t\t\t\treturn await loadView(ev, url, handler, params, template);\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\twhile (enteredRoute > 0) {\n\t\t\t\tenteredRoute--;\n\t\t\t\tawait routeMiddleware[enteredRoute].exit?.(ev);\n\t\t\t}\n\t\t}\n\n\t\treturn notFound();\n\t};\n\n\treturn async function load(ev: ServerEvent, template?: string): Promise<Response> {\n\t\t// Global middleware, from `site.middleware`: runs for every request\n\t\t// before routing, including ones that won't match a route\n\t\t// (maintenance mode, legacy url redirects, etc)\n\t\tlet entered = 0;\n\t\ttry {\n\t\t\tlet response: Response | undefined = undefined;\n\t\t\tfor (; entered < middleware.length && !response; entered++) {\n\t\t\t\tconst result = await middleware[entered].enter?.(ev);\n\t\t\t\tif (result) {\n\t\t\t\t\tresponse = result;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (response) {\n\t\t\t\treturn response;\n\t\t\t}\n\t\t\treturn await handle(ev, template);\n\t\t} catch (error) {\n\t\t\t// Middleware exits can inspect (and replace, in Server.fetch) the\n\t\t\t// error via `ev.error`\n\t\t\tev.error = error;\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\twhile (entered > 0) {\n\t\t\t\tentered--;\n\t\t\t\tawait middleware[entered].exit?.(ev);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Resolves the route's endpoint module, caching it on the handler so warm\n * requests don't pay for the loader promise.\n */\nasync function resolveModule(handler: RouteHandler): Promise<any> {\n\treturn (handler.resolvedModule ??= await (handler.modulePromise ??= handler.endPoint()));\n}\n\nasync function loadServerHooks(handler: RouteHandler): Promise<ServerHook[]> {\n\tif (!handler.serverHooks) return [];\n\t// Resolve each hook module once and cache the result on the handler\n\treturn (handler.resolvedHooks ??= Promise.all(\n\t\thandler.serverHooks.map(async (load) => (await load()).default),\n\t));\n}\n\nasync function handleResponse(response: Response, fromForm = false): Promise<Response> {\n\t$page.status = response.status;\n\n\t// Success codes and redirect codes are acceptable\n\tif (response.status >= 200 && response.status <= 399) {\n\t\treturn response;\n\t}\n\n\t// 4xx error codes are acceptable from form actions\n\tif (fromForm && response.status >= 400 && response.status <= 499) {\n\t\treturn response;\n\t}\n\n\t// It's an error, so redirect to the error page\n\t// We're just pushing the status and message in the URL, but maybe there's a\n\t// more sophisticated way to do this?\n\t// TODO: Should be returning loadView rather than redirecting\n\t// TODO: Should be returning the NEAREST error page to this path, including layouts\n\tlet params = new URLSearchParams();\n\tparams.append(\"status\", $page.status.toString());\n\tlet message = await response.text();\n\tif (response.headers.get(\"Content-Type\")?.includes(\"application/json\")) {\n\t\tconst data = JSON.parse(message);\n\t\tmessage = data.message ?? message;\n\t}\n\tif (message) {\n\t\tif ($page.error) {\n\t\t\t$page.error.message = message;\n\t\t} else {\n\t\t\t$page.error = { message };\n\t\t}\n\t\tparams.append(\"message\", message);\n\t}\n\treturn seeOther(`/_error?${params.toString()}`);\n}\n\nasync function loadData(\n\tev: ServerEvent,\n\turl: URL,\n\thandler: RouteHandler,\n\tfunctionName: string,\n\tparams: Record<string, any>,\n) {\n\t// The endpoint module is cached on the handler, so once warm this is a\n\t// plain property read\n\tconst mod = handler.resolvedModule ?? (await resolveModule(handler));\n\tconst serverEndPoint: ServerEndPoint | undefined = mod?.default;\n\t// `functionName` is computed from the request method, so the handlers are\n\t// accessed through a loose record\n\tconst handlerFn = (\n\t\tserverEndPoint as unknown as Record<string, ServerRequest | undefined> | undefined\n\t)?.[functionName];\n\tif (!serverEndPoint || !handlerFn) {\n\t\treturn notFound();\n\t}\n\n\t// Route params come from the URL, so a failed validation means the\n\t// resource doesn't exist. Only endpoints declaring a params schema pay\n\t// for validation\n\tconst paramsSchema = endpointSchema(serverEndPoint, \"params\");\n\tif (paramsSchema) {\n\t\ttry {\n\t\t\tparams = (await validate(paramsSchema, params)) as Record<string, any>;\n\t\t} catch (error) {\n\t\t\tif (error instanceof ValidationError) return notFound();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\ttry {\n\t\t// If the endpoint declares a schema for this handler, validate its\n\t\t// input up front and reject with 422 if it fails. get/head/load\n\t\t// schemas validate the query string; other schemas validate the json\n\t\t// body. Endpoints without a schema skip straight to the handler\n\t\tconst schema = endpointSchema(serverEndPoint, functionName);\n\t\tconst values = schema\n\t\t\t? functionName === \"get\" || functionName === \"head\" || functionName === \"load\"\n\t\t\t\t? { query: await validate(schema, searchParamsToRecord(url.searchParams)) }\n\t\t\t\t: { json: await validate(schema, await ev.json()) }\n\t\t\t: {};\n\n\t\tconst serverParams = buildServerParams(ev, url, params, values);\n\n\t\t// Hooks are resolved once per handler; routes without hooks don't\n\t\t// await anything here\n\t\tconst hooks = handler.serverHooks ? await loadServerHooks(handler) : [];\n\n\t\tlet entered = 0;\n\t\tlet enterResponse: Response | undefined = undefined;\n\t\ttry {\n\t\t\t// Hooks run from the root down; a hook's enter can return a\n\t\t\t// Response to short-circuit the request\n\t\t\tfor (; entered < hooks.length && !enterResponse; entered++) {\n\t\t\t\tconst hookResult = await hooks[entered].enter?.(serverParams);\n\t\t\t\tif (hookResult) {\n\t\t\t\t\tenterResponse = hookResult;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// A hook's enter response short-circuits the request; otherwise, if\n\t\t\t// there was no response returned from load (such as errors or a\n\t\t\t// redirect), send an ok response\n\t\t\treturn enterResponse || (await handlerFn(serverParams)) || ok();\n\t\t} finally {\n\t\t\t// Run exit hooks in reverse order for hooks that were entered\n\t\t\twhile (entered > 0) {\n\t\t\t\tentered--;\n\t\t\t\tawait hooks[entered].exit?.(serverParams);\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tconst response = validationErrorResponse(error);\n\t\tif (response) return response;\n\t\tthrow error;\n\t}\n}\n\nasync function loadView(\n\tev: ServerEvent,\n\turl: URL,\n\thandler: RouteHandler,\n\tparams: Record<string, any>,\n\ttemplate: string | undefined,\n\tformStatus?: number,\n\tform?: Record<string, string | number>,\n\tfromForm?: boolean,\n\t// The appData that the server hooks populated around the form action,\n\t// passed through so the re-render's loads see the same data\n\tappData?: Record<string, any>,\n) {\n\t// There must be a client endpoint with a component\n\tconst clientEndPoint: PageEndPoint | undefined = (await resolveModule(handler)).default;\n\tif (!clientEndPoint?.component) {\n\t\treturn notFound();\n\t}\n\n\t// Consume the flash message when a page is rendered (but not for API\n\t// requests), so that the following page -- and only that page -- can show\n\t// it. For a form action that re-renders instead of redirecting, the\n\t// message is set and read within this request\n\t$page.flash = ev.flash.get();\n\n\t// The template comes from site.html, which endpoints-only sites don't have\n\tif (!template) {\n\t\tthrow new Error(\n\t\t\t\"Page routes require a src/site.html file, which was not found; add it, or remove page/layout routes to serve endpoints only\",\n\t\t);\n\t}\n\n\t// There may be a server endpoint\n\tconst serverEndPoint: PageServerEndPoint | undefined =\n\t\thandler.serverEndPoint && (await handler.serverEndPoint())?.default;\n\n\t// Validate the route params and the load query against the server\n\t// endpoint's schemas, if it declares any. Params come from the URL, so a\n\t// failed validation means the resource doesn't exist; a failed query goes\n\t// to the error page like any other load failure\n\tlet query: unknown;\n\tif (serverEndPoint) {\n\t\ttry {\n\t\t\tparams = await validateEndpointParams(serverEndPoint, params);\n\t\t} catch (error) {\n\t\t\tif (error instanceof ValidationError) return notFound();\n\t\t\tthrow error;\n\t\t}\n\t\tconst loadSchema = endpointSchema(serverEndPoint, \"load\");\n\t\tif (loadSchema) {\n\t\t\tconst queryRecord = searchParamsToRecord(url.searchParams);\n\t\t\ttry {\n\t\t\t\tquery = await validate(loadSchema, queryRecord);\n\t\t\t} catch (error) {\n\t\t\t\t// A form re-render's url is the POST's, and a form action can\n\t\t\t\t// drop query params that the load schema requires, so failing\n\t\t\t\t// validation here would lose the form errors. Fall back to the\n\t\t\t\t// raw query values instead and let the load make of them what\n\t\t\t\t// it can\n\t\t\t\tif (fromForm) {\n\t\t\t\t\tquery = queryRecord;\n\t\t\t\t} else {\n\t\t\t\t\tconst response = validationErrorResponse(error);\n\t\t\t\t\tif (response) return response;\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Maybe hit the server hooks -- unless they already ran for this request,\n\t// which is the case when the view is re-rendered after a form action. In\n\t// that case the hooks' appData is passed through, so that the loads below\n\t// see the same data (e.g. the user set by an auth hook) as the action did\n\tconst serverParams = buildServerParams(ev, url, params, query ? { query } : {}, appData);\n\tconst serverHooks = fromForm ? [] : await loadServerHooks(handler);\n\tlet entered = 0;\n\tlet enterResponse: Response | undefined = undefined;\n\ttry {\n\t\t// Hooks run from the root down; a hook's enter can return a Response\n\t\t// to short-circuit the request\n\t\tfor (; entered < serverHooks.length && !enterResponse; entered++) {\n\t\t\tconst hookResult = await serverHooks[entered].enter?.(serverParams);\n\t\t\tif (hookResult) {\n\t\t\t\tenterResponse = hookResult;\n\t\t\t}\n\t\t}\n\t\tif (enterResponse) {\n\t\t\treturn enterResponse;\n\t\t}\n\n\t\t// Pass the data into $props\n\t\t// TODO: Promise.all\n\t\t// NOTE: We're loading data from top to bottom, overriding as we go, and I'm\n\t\t// not sure if this is the best way to go\n\t\tlet data = {};\n\t\tif (handler.layouts) {\n\t\t\tfor (let layout of handler.layouts) {\n\t\t\t\tconst layoutEndPoint: PageEndPoint | undefined = (await layout.endPoint())?.default;\n\t\t\t\tconst layoutServerEndPoint: PageServerEndPoint | undefined =\n\t\t\t\t\tlayout.serverEndPoint && (await layout.serverEndPoint())?.default;\n\t\t\t\tconst layoutResponse = await loadClientAndServerData(\n\t\t\t\t\turl,\n\t\t\t\t\tparams,\n\t\t\t\t\tserverParams,\n\t\t\t\t\tdata,\n\t\t\t\t\tlayoutEndPoint,\n\t\t\t\t\tlayoutServerEndPoint,\n\t\t\t\t);\n\t\t\t\tif (layoutResponse?.ok === false) {\n\t\t\t\t\treturn layoutResponse;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlet endPointResponse = await loadClientAndServerData(\n\t\t\turl,\n\t\t\tparams,\n\t\t\tserverParams,\n\t\t\tdata,\n\t\t\tclientEndPoint,\n\t\t\tserverEndPoint,\n\t\t);\n\t\tif (endPointResponse?.ok === false) {\n\t\t\treturn endPointResponse;\n\t\t}\n\t\tlet $props: Record<string, any> = { data, form };\n\n\t\tlet styles = \"\";\n\n\t\t// If there are layouts, work our way upwards, pushing each component into\n\t\t// the default slot of its parent\n\t\t// TODO: Also handle layout server data\n\t\t// TODO: There's probably a nicer way to do this with reducers or something\n\t\tlet component = clientEndPoint.component as ServerComponent;\n\t\tlet slots: Record<string, ServerSlotRender> | undefined = undefined;\n\t\t// Which slot levels actually ran during the render below, so a layout\n\t\t// that never rendered its <slot /> (silently dropping the page\n\t\t// content) can be reported (see findMissingSlotLayout)\n\t\tconst invokedLevels = new Set<number>();\n\t\tconst trackSlot = (level: number, slot: ServerSlotRender): ServerSlotRender => {\n\t\t\treturn ($slot, $context) => {\n\t\t\t\tinvokedLevels.add(level);\n\t\t\t\treturn slot($slot, $context);\n\t\t\t};\n\t\t};\n\t\tif (handler.layouts) {\n\t\t\tlet slotFunctions: ServerSlotRender[] = [];\n\t\t\t// The last slot function will render the client component\n\t\t\tslotFunctions[handler.layouts.length] = trackSlot(\n\t\t\t\thandler.layouts.length,\n\t\t\t\tasync (_, $context) => {\n\t\t\t\t\tlet { body, head } = await (clientEndPoint.component as ServerComponent)(\n\t\t\t\t\t\t$props,\n\t\t\t\t\t\t$context,\n\t\t\t\t\t);\n\t\t\t\t\tstyles += head;\n\t\t\t\t\treturn body;\n\t\t\t\t},\n\t\t\t);\n\t\t\tfor (let i = handler.layouts.length - 1; i >= 0; i--) {\n\t\t\t\tconst layoutEndPoint: PageEndPoint | undefined = (await handler.layouts[i].endPoint())\n\t\t\t\t\t?.default;\n\t\t\t\tif (layoutEndPoint?.component) {\n\t\t\t\t\tif (i === 0) {\n\t\t\t\t\t\tcomponent = layoutEndPoint.component as ServerComponent;\n\t\t\t\t\t\tslots = { _: slotFunctions[i + 1] };\n\t\t\t\t\t} else {\n\t\t\t\t\t\tslotFunctions[i] = trackSlot(i, async (_, $context) => {\n\t\t\t\t\t\t\tlet { body, head } = await (layoutEndPoint.component as ServerComponent)(\n\t\t\t\t\t\t\t\t$props,\n\t\t\t\t\t\t\t\t$context,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t_: slotFunctions[i + 1],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tstyles += head;\n\t\t\t\t\t\t\treturn body;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet html;\n\t\ttry {\n\t\t\tlet { body, head } = await component($props, undefined, slots);\n\n\t\t\t// Render the page's (and its layouts') head element data, if the\n\t\t\t// endpoint declared any. Layouts lose to the page (the nearest\n\t\t\t// endpoint wins, as with @head content), and everything loses to\n\t\t\t// the first title in the compiled head -- which mergeHead keeps\n\t\t\tlet headData = \"\";\n\t\t\tconst event = { url, params, data } as PageLoadEvent;\n\t\t\tconst layoutEndPoints = await Promise.all(\n\t\t\t\t(handler.layouts ?? []).map(async (layout) => await layout.endPoint()),\n\t\t\t);\n\t\t\tconst headPoints = [clientEndPoint, ...layoutEndPoints].reverse();\n\t\t\tfor (const endPoint of headPoints) {\n\t\t\t\tconst headElements =\n\t\t\t\t\ttypeof endPoint.head === \"function\" ? await endPoint.head(event) : endPoint.head;\n\t\t\t\tif (headElements) {\n\t\t\t\t\theadData += headElements.map((element: HeadElement) => markupOf(element)).join(\"\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Put the form info in a hidden input so that it can be accessed on the client\n\t\t\tif (form) {\n\t\t\t\tbody += `\\n<input type=\"hidden\" id=\"t-form-data\" value='${JSON.stringify(form).replaceAll(\"'\", \"\\\\'\")}' />`;\n\t\t\t}\n\n\t\t\tstyles += head;\n\t\t\thtml = rewriteBaseInHtml(\n\t\t\t\tmergeHead(template, styles + headData).replace(\"%COMPONENT_BODY%\", body),\n\t\t\t\tgetBasePath(),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\t// TODO: Show a proper Error component\n\t\t\thtml = '<span style=\"color: red\">Script syntax error</span><p>' + error + \"</p>\";\n\t\t\tconsole.log(error);\n\t\t}\n\n\t\t// A layout that never rendered <slot /> silently drops the whole page\n\t\t// content from the output; find and report the outermost one\n\t\tif (handler.layouts) {\n\t\t\tconst missingLayout = findMissingSlotLayout(handler.layouts, invokedLevels);\n\t\t\tif (missingLayout !== undefined) {\n\t\t\t\twarnMissingSlotContent(missingLayout);\n\t\t\t}\n\t\t}\n\n\t\treturn new Response(html, {\n\t\t\tstatus: formStatus ?? 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/html\",\n\t\t\t},\n\t\t});\n\t} finally {\n\t\t// Run exit hooks in reverse order for hooks that were entered\n\t\twhile (entered > 0) {\n\t\t\tentered--;\n\t\t\tawait serverHooks[entered].exit?.(serverParams);\n\t\t}\n\t}\n}\n\nasync function runAction(\n\tev: ServerEvent,\n\turl: URL,\n\thandler: RouteHandler,\n\tserverEndPoint: PageServerEndPoint | undefined,\n\tparams: Record<string, any>,\n\tquery: URLSearchParams,\n\ttemplate: string | undefined,\n) {\n\t// The action name rides in the query, so look for a `?/name` key rather\n\t// than taking the first key -- the url may carry ordinary load query\n\t// params as well (e.g. `?page=3&/like`, or a default action posted to a\n\t// url that already has a query). A key that names a declared action also\n\t// matches (e.g. `?set`), and a form without an action attribute calls the\n\t// `default` action\n\tconst queryKeys = Array.from(query.keys());\n\tconst actionKey =\n\t\tqueryKeys.find((key) => key.startsWith(\"/\")) ??\n\t\tqueryKeys.find((key) => !!serverEndPoint?.actions?.[key.replace(/^\\//, \"\")]);\n\tconst actionName = (actionKey ?? \"default\").replace(/^\\//, \"\");\n\tif (serverEndPoint?.actions) {\n\t\tconst action = serverEndPoint.actions[actionName];\n\t\tif (action) {\n\t\t\tif (actionName === \"load\" || actionName === \"params\") {\n\t\t\t\t// These names are reserved in the endpoint's schema map: `load`\n\t\t\t\t// validates the query string and `params` the route params, so\n\t\t\t\t// an action with one of these names would get the wrong schema\n\t\t\t\t// applied to its form data\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The action name \"${actionName}\" is reserved. ` +\n\t\t\t\t\t\t`Rename the action (and its schema key, if any), e.g. to \"save\".`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Route params come from the URL, so a failed validation means the\n\t\t\t// resource doesn't exist\n\t\t\ttry {\n\t\t\t\tparams = await validateEndpointParams(serverEndPoint, params);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof ValidationError) return notFound();\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tlet result: Response | undefined | void;\n\t\t\t// The event that the hooks and action run with. It's kept around so\n\t\t\t// that the view re-render below can pass its appData (populated by\n\t\t\t// the hooks' enter functions) through to the loads\n\t\t\tlet serverParams: ServerLoadEvent | undefined = undefined;\n\t\t\ttry {\n\t\t\t\t// If the endpoint declares a schema for this action, validate the\n\t\t\t\t// submitted form data up front and reject with 422 if it fails\n\t\t\t\tconst schema = endpointSchema(serverEndPoint, actionName);\n\t\t\t\tconst form = schema\n\t\t\t\t\t? await validate(schema, await formDataToRecord(ev.request))\n\t\t\t\t\t: undefined;\n\n\t\t\t\tserverParams = buildServerParams(ev, url, params, form ? { form } : {});\n\n\t\t\t\tconst serverHooks = await loadServerHooks(handler);\n\t\t\t\tlet entered = 0;\n\t\t\t\tlet enterResponse: Response | undefined = undefined;\n\t\t\t\ttry {\n\t\t\t\t\t// Hooks run from the root down; a hook's enter can return a\n\t\t\t\t\t// Response to short-circuit the action\n\t\t\t\t\tfor (; entered < serverHooks.length && !enterResponse; entered++) {\n\t\t\t\t\t\tconst hookResult = await serverHooks[entered].enter?.(serverParams);\n\t\t\t\t\t\tif (hookResult) {\n\t\t\t\t\t\t\tenterResponse = hookResult;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tresult = enterResponse || (await action(serverParams));\n\t\t\t\t} finally {\n\t\t\t\t\t// Run exit hooks in reverse order for hooks that were entered\n\t\t\t\t\twhile (entered > 0) {\n\t\t\t\t\t\tentered--;\n\t\t\t\t\t\tawait serverHooks[entered].exit?.(serverParams);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconst response = validationErrorResponse(error);\n\t\t\t\tif (response) return response;\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tif (ev.request.headers.has(\"X-Torpor-Form-Submit\")) {\n\t\t\t\t// If the form was submitted from javascript, just return the\n\t\t\t\t// response and it will be handled on the client\n\t\t\t\t// TODO: Should we make the user return a response??\n\t\t\t\tresult ??= ok();\n\n\t\t\t\t// If it's a redirect, we need to stop the browser handling it\n\t\t\t\tif (result.status >= 300 && result.status <= 399) {\n\t\t\t\t\tconst location = result.headers.get(\"Location\") ?? \"\";\n\t\t\t\t\tresult = ok();\n\t\t\t\t\tresult.headers.set(\"X-Torpor-Form-Redirect\", \"\");\n\t\t\t\t\tresult.headers.set(\"Location\", location);\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t} else if (\n\t\t\t\t!result ||\n\t\t\t\t(result.status >= 200 && result.status <= 299) ||\n\t\t\t\t(result.status >= 400 && result.status <= 499)\n\t\t\t) {\n\t\t\t\t// If the form was submitted without javascript, and there was\n\t\t\t\t// no result, an ok result, or a 4xx error, re-render the view\n\t\t\t\t// with the form result. The server hooks already ran around the\n\t\t\t\t// action, so they are not run again here -- but their appData\n\t\t\t\t// is passed through, so that loads guarding on it (e.g. an\n\t\t\t\t// auth hook's user) re-render the page instead of erroring\n\t\t\t\t// Keep the query string, so that loads validating the query see\n\t\t\t\t// the same values as the original GET. If the form action\n\t\t\t\t// dropped params that the load schema requires, loadView falls\n\t\t\t\t// back to the raw query instead of failing validation\n\t\t\t\tconst newUrl = new URL(url.pathname + url.search, url);\n\t\t\t\tconst formStatus = result?.status;\n\t\t\t\tlet formMessage = await result?.text();\n\t\t\t\tif (formMessage && result?.headers.get(\"Content-Type\")?.includes(\"application/json\")) {\n\t\t\t\t\t$page.form = JSON.parse(formMessage);\n\t\t\t\t\tformMessage = undefined;\n\t\t\t\t} else {\n\t\t\t\t\t$page.form = {};\n\t\t\t\t}\n\t\t\t\t// Set status and message if they haven't already been set,\n\t\t\t\t// which means that you can just return e.g. forbidden() or\n\t\t\t\t// forbidden(\"no!\") and there will be something you can work\n\t\t\t\t// with in your component, or you can set a completely custom\n\t\t\t\t// object with whatever info you need\n\t\t\t\t$page.form!.status ??= formStatus ?? 0;\n\t\t\t\t$page.form!.message ??= formMessage ?? \"\";\n\t\t\t\treturn await loadView(\n\t\t\t\t\tev,\n\t\t\t\t\tnewUrl,\n\t\t\t\t\thandler,\n\t\t\t\t\tparams,\n\t\t\t\t\ttemplate,\n\t\t\t\t\tformStatus,\n\t\t\t\t\t$page.form,\n\t\t\t\t\ttrue,\n\t\t\t\t\tserverParams?.appData,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// If the form was submitted without javascript and there was a\n\t\t\t\t// redirect or server error, just return the result to handle it\n\t\t\t\t// as normal\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn notFound();\n}\n\nasync function loadClientAndServerData(\n\turl: URL,\n\tparams: Record<string, any>,\n\tserverParams: ServerLoadEvent,\n\tdata: Record<string, any>,\n\tclientEndPoint?: PageEndPoint,\n\tserverEndPoint?: PageServerEndPoint,\n) {\n\tif (clientEndPoint?.load) {\n\t\tconst clientParams = buildClientParams(url, params, data);\n\t\tconst clientResponse = await clientEndPoint.load(clientParams);\n\t\tif (clientResponse) {\n\t\t\tif (clientResponse.ok) {\n\t\t\t\tif (clientResponse.headers.get(\"Content-Type\")?.includes(\"application/json\")) {\n\t\t\t\t\tObject.assign(data, await clientResponse.json());\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn clientResponse;\n\t\t\t}\n\t\t}\n\t}\n\tif (serverEndPoint?.load) {\n\t\tconst serverResponse = await serverEndPoint.load(serverParams);\n\t\tif (serverResponse) {\n\t\t\tif (serverResponse.ok) {\n\t\t\t\tif (serverResponse.headers.get(\"Content-Type\")?.includes(\"application/json\")) {\n\t\t\t\t\tObject.assign(data, await serverResponse.json());\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn serverResponse;\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction buildClientParams(url: URL, params: Record<string, any>, data: Record<string, any>) {\n\treturn {\n\t\turl,\n\t\tparams,\n\t\tdata,\n\t};\n}\n\nfunction buildServerParams(\n\tev: ServerEvent,\n\turl: URL,\n\tparams: Record<string, any>,\n\tvalues: { json?: unknown; form?: unknown; query?: unknown } = {},\n\tappData: Record<string, any> = {},\n): ServerLoadEvent {\n\treturn {\n\t\turl,\n\t\tparams,\n\t\tappData,\n\t\trequest: ev.request,\n\t\t// The inputs may have been validated already, in which case the request\n\t\t// body has been consumed and the parsed values are returned instead.\n\t\t// Their types come from the endpoint's schemas, so they are loosely\n\t\t// typed here\n\t\tjson: (): Promise<any> =>\n\t\t\tvalues.json !== undefined ? Promise.resolve(values.json) : ev.json(),\n\t\tform: (): Promise<any> =>\n\t\t\tvalues.form !== undefined ? Promise.resolve(values.form) : formDataToRecord(ev.request),\n\t\tquery: (): Promise<any> =>\n\t\t\tvalues.query !== undefined\n\t\t\t\t? Promise.resolve(values.query)\n\t\t\t\t: Promise.resolve(searchParamsToRecord(url.searchParams)),\n\t\tcookies: ev.cookies,\n\t\theaders: ev.headers,\n\t\tsession: ev.session,\n\t\tflash: ev.flash,\n\t\tadapter: ev.adapter,\n\t};\n}\n\n/**\n * Renders a head element as markup. Attribute values are escaped, since\n * they can come from user data (e.g. a post title passed to `seo()`).\n */\nfunction markupOf(element: HeadElement): string {\n\tif (\"title\" in element) {\n\t\treturn `<title>${escapeHtml(element.title)}</title>`;\n\t}\n\tif (\"name\" in element) {\n\t\treturn `<meta name=\"${escapeHtml(element.name)}\" content=\"${escapeHtml(element.content)}\" />`;\n\t}\n\treturn `<meta property=\"${escapeHtml(element.property)}\" content=\"${escapeHtml(element.content)}\" />`;\n}\n\nfunction escapeHtml(value: string): string {\n\treturn value\n\t\t.replaceAll(\"&\", \"&\")\n\t\t.replaceAll(\"<\", \"<\")\n\t\t.replaceAll(\">\", \">\")\n\t\t.replaceAll('\"', \""\");\n}\n"],"mappings":"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"}
|
package/dist/test.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as Router } from "./Router-C4ADUfhv.mjs";
|
|
2
2
|
import { t as ServerEvent } from "./ServerEvent-BY4f3RVF.mjs";
|
|
3
|
-
import { t as createServerLoad } from "./serverHandlers-
|
|
3
|
+
import { t as createServerLoad } from "./serverHandlers-C8qzOSX-.mjs";
|
|
4
4
|
import fpath from "node:path";
|
|
5
5
|
//#region src/test/runTest.ts
|
|
6
6
|
/**
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"serverHandlers-B6EcNfBP.mjs","names":[],"sources":["../src/form/formDataToRecord.ts","../src/state/$serverPage.ts","../src/utils/searchParamsToRecord.ts","../src/validation/endpoint.ts","../src/site/layoutSlots.ts","../src/site/mergeHead.ts","../src/site/serverHandlers.ts"],"sourcesContent":["import type { FormDataRecord } from \"../types/ServerLoadEvent\";\n\n/**\n * Converts the submitted fields of a form request into a plain record: one\n * value per field, or an array when a field was submitted with multiple\n * values (e.g. a multi select). File inputs pass through as `File` values;\n * coercing them is left to the schema or the action.\n *\n * @param request The request (or FormData directly)\n * @returns The field values\n */\nexport default async function formDataToRecord(\n\trequest: Request | FormData,\n): Promise<FormDataRecord> {\n\tconst formData = request instanceof FormData ? request : await request.formData();\n\tconst result: FormDataRecord = {};\n\tfor (const key of formData.keys()) {\n\t\tif (key in result) continue;\n\t\tconst values = formData.getAll(key);\n\t\tresult[key] = values.length > 1 ? values : values[0];\n\t}\n\treturn result;\n}\n","import { $watch } from \"@torpor/view/ssr\";\nimport type PageState from \"../types/PageState\";\n\nconst PAGE_SYMBOL: unique symbol = Symbol.for(\"torp.Page\");\n\n// The server request path has no reactive subscribers, so the state is\n// stored plainly ($watch from `@torpor/view/ssr` is a no-op that returns\n// the object itself) instead of through a reactive proxy. Shares the same\n// `globalThis` slot as the client `$page`, so both variants always see the\n// same state object whichever loads first.\nconst $page: PageState =\n\t// @ts-ignore\n\t(globalThis[PAGE_SYMBOL] ??= $watch({\n\t\tstatus: 404,\n\t\turl: new URL(\"http://localhost\"),\n\t\tform: undefined,\n\t\tflash: undefined,\n\t\terror: {\n\t\t\tmessage: \"\",\n\t\t},\n\t}));\n\nexport default $page;\n","import type { QueryRecord } from \"../types/ServerLoadEvent\";\n\n/**\n * Converts a URL's query string into a plain record: one string per param,\n * or an array when a param was repeated.\n *\n * @param searchParams The URL's search params\n * @returns The param values\n */\nexport default function searchParamsToRecord(searchParams: URLSearchParams): QueryRecord {\n\tconst result: QueryRecord = {};\n\tfor (const key of searchParams.keys()) {\n\t\tif (key in result) continue;\n\t\tconst values = searchParams.getAll(key);\n\t\tresult[key] = values.length > 1 ? values : values[0];\n\t}\n\treturn result;\n}\n","import type PageServerEndPoint from \"../types/PageServerEndPoint\";\nimport type ServerEndPoint from \"../types/ServerEndPoint\";\nimport type { StandardSchemaV1 } from \"../types/StandardSchema\";\nimport type ServerEvent from \"../server/ServerEvent\";\nimport searchParamsToRecord from \"../utils/searchParamsToRecord\";\nimport unprocessable from \"../response/unprocessable\";\nimport ValidationError from \"./ValidationError\";\nimport validate from \"./validate\";\n\n/**\n * Loose views of an endpoint's schema map, keyed by handler/action name (plus\n * the reserved `params` key). The type-level constraint differs per endpoint\n * type, but the runtime treats them the same.\n */\ntype Schemas = Record<string, StandardSchemaV1 | undefined>;\n\ntype EndPoint = ServerEndPoint | PageServerEndPoint;\n\n/**\n * Gets the standard schema declared for a handler or action, if any. The\n * schemas map is keyed by name; the runtime treats it as a loose record.\n */\nexport function endpointSchema(endPoint: EndPoint, name: string): StandardSchemaV1 | undefined {\n\treturn (endPoint.schema as Schemas | undefined)?.[name];\n}\n\n/**\n * Validates the route params against the endpoint's `params` schema, if it\n * declares one, returning the coerced params. Throws a ValidationError when\n * they don't match, which callers turn into a 404 (params come from the URL,\n * so a failed validation means the resource doesn't exist).\n *\n * @param endPoint The endpoint declaring the (optional) `params` schema\n * @param params The route params from the matched route\n * @returns The validated params\n */\nexport async function validateEndpointParams(\n\tendPoint: EndPoint,\n\tparams: Record<string, any>,\n): Promise<Record<string, any>> {\n\tconst schema = endpointSchema(endPoint, \"params\");\n\treturn schema ? ((await validate(schema, params)) as Record<string, any>) : params;\n}\n\n/**\n * Validates a handler's input against its schema: get/head handlers and load\n * functions validate the URL's query string, other handlers validate the JSON\n * request body. Returns the validated values (an empty object when no schema\n * is declared), which callers pass through to the handler's event.\n *\n * @param schema The handler's (optional) schema\n * @param functionName The handler name (`get`, `post`, `load`, etc)\n * @param url The request URL, for the query string\n * @param ev The server event, for the request body\n * @returns The validated values\n */\nexport async function validateHandlerInput(\n\tschema: StandardSchemaV1 | undefined,\n\tfunctionName: string,\n\turl: URL,\n\tev: ServerEvent,\n): Promise<{ json?: unknown; form?: unknown; query?: unknown }> {\n\tif (!schema) return {};\n\tif (functionName === \"get\" || functionName === \"head\" || functionName === \"load\") {\n\t\treturn { query: await validate(schema, searchParamsToRecord(url.searchParams)) };\n\t}\n\treturn { json: await validate(schema, await ev.json()) };\n}\n\n/**\n * Turns a ValidationError thrown during endpoint validation into a 422\n * response with the schema's issues. Returns undefined for any other error,\n * which callers should rethrow.\n *\n * @param error The error thrown by a handler or validation\n * @returns A 422 response, or undefined when the error isn't a validation failure\n */\nexport function validationErrorResponse(error: unknown): Response | undefined {\n\tif (error instanceof ValidationError) {\n\t\treturn unprocessable({ message: error.message, issues: error.issues });\n\t}\n\treturn undefined;\n}\n","/**\n * Layouts are composed by the layout engine passing each layout (and finally\n * the page) as the default slot of its parent — so every `_layout` component\n * must render `<slot />`, or pass the default slot down to a child component\n * it renders. A layout that doesn't drops its entire content: the server\n * renders the layout's own markup with an empty content area (no error), and\n * the first client-side navigation that reuses the layout crashes on a null\n * slot region.\n *\n * The static `checkLayoutSlots` check catches this at build/dev time; these\n * helpers report it at request time for the cases static analysis can't see\n * (e.g. a `<slot />` rendered conditionally inside `@if`). They are\n * server-side only — nothing here is imported into the client bundle.\n */\n\n/**\n * Returns the path of the outermost layout that never rendered its\n * `<slot />`, or undefined when every level rendered.\n *\n * Slot level j (1-based) is the slot render that layout j - 1 receives: the\n * root layout (layouts[0]) renders level 1, layout i renders level i + 1,\n * and level layouts.length renders the page. A broken level makes every\n * deeper level unreachable, so the first level that never ran identifies\n * the offending layout.\n */\nexport function findMissingSlotLayout(\n\tlayouts: readonly { path: string }[],\n\tinvokedLevels: ReadonlySet<number>,\n): string | undefined {\n\tfor (let level = 1; level <= layouts.length; level++) {\n\t\tif (!invokedLevels.has(level)) {\n\t\t\treturn layouts[level - 1].path;\n\t\t}\n\t}\n\treturn undefined;\n}\n\nconst warnedLayouts = new Set<string>();\n\n/**\n * Reports a layout that dropped its slot content. The condition is a genuine\n * rendering bug (the page content is missing from the output), so it is not\n * dev-gated — but it warns only once per layout path to avoid per-request\n * noise.\n */ export function warnMissingSlotContent(layoutPath: string): void {\n\tif (warnedLayouts.has(layoutPath)) return;\n\twarnedLayouts.add(layoutPath);\n\tconsole.warn(\n\t\t`[torpor] The layout at \"${layoutPath}\" never rendered <slot />, so the page content ` +\n\t\t\t`was not included in the render. Every _layout component must render <slot /> (or ` +\n\t\t\t`pass the default slot down to a child component it renders).`,\n\t);\n}\n","const TITLE_REGEX = /<title(?:\\s[^>]*)?>[\\s\\S]*?<\\/title>/g;\nconst FIRST_TITLE_REGEX = /<title(?:\\s[^>]*)?>[\\s\\S]*?<\\/title>/;\n\n/**\n * Merges the head string rendered by a page (and its layouts) into the site\n * template. The first <title> in the head string -- the page's, since pages\n * render before the layouts around them -- wins, overriding both any later\n * component title (e.g. from a child component) and a static <title> in the\n * template itself. All other head content (styles, meta elements, etc) is\n * appended where %COMPONENT_HEAD% sits in the template, before </head>.\n */\nexport default function mergeHead(template: string, head: string): string {\n\tconst titles = head.match(TITLE_REGEX);\n\tlet html = template;\n\tlet headHtml = head;\n\tif (titles?.length) {\n\t\theadHtml = head.replace(TITLE_REGEX, \"\");\n\t\thtml = html.replace(FIRST_TITLE_REGEX, \"\");\n\t\theadHtml = titles[0] + headHtml;\n\t}\n\treturn html.replace(\"%COMPONENT_HEAD%\", headHtml);\n}\n","import { type ServerComponent, type ServerSlotRender } from \"@torpor/view/ssr\";\nimport formDataToRecord from \"../form/formDataToRecord.ts\";\nimport notFound from \"../response/notFound.ts\";\nimport ok from \"../response/ok.ts\";\nimport seeOther from \"../response/seeOther.ts\";\nimport ServerEvent from \"../server/ServerEvent.ts\";\nimport type MiddlewareFunction from \"../server/types/MiddlewareFunction\";\nimport $page from \"../state/$serverPage.ts\";\nimport type PageEndPoint from \"../types/PageEndPoint.ts\";\nimport type { HeadElement } from \"../types/PageEndPoint.ts\";\nimport type PageLoadEvent from \"../types/PageLoadEvent.ts\";\nimport type PageServerEndPoint from \"../types/PageServerEndPoint.ts\";\nimport type RouteHandler from \"../types/RouteHandler.ts\";\nimport type ServerRequest from \"../types/ServerRequest.ts\";\nimport {\n\tERROR_ROUTE,\n\tHOOK_ROUTE,\n\tHOOK_SERVER_ROUTE,\n\tLAYOUT_ROUTE,\n\tLAYOUT_SERVER_ROUTE,\n\tPAGE_ROUTE,\n\tPAGE_SERVER_ROUTE,\n\tSERVER_ROUTE,\n} from \"../types/RouteType\";\nimport type ServerEndPoint from \"../types/ServerEndPoint.ts\";\nimport type ServerHook from \"../types/ServerHook.ts\";\nimport type ServerLoadEvent from \"../types/ServerLoadEvent.ts\";\nimport searchParamsToRecord from \"../utils/searchParamsToRecord.ts\";\nimport validate from \"../validation/validate.ts\";\nimport ValidationError from \"../validation/ValidationError.ts\";\nimport {\n\tendpointSchema,\n\tvalidateEndpointParams,\n\tvalidationErrorResponse,\n} from \"../validation/endpoint.ts\";\nimport { findMissingSlotLayout, warnMissingSlotContent } from \"./layoutSlots.ts\";\nimport { getBasePath, rewriteBaseInHtml, setBasePath, stripBaseFromUrl } from \"./basePath.ts\";\nimport mergeHead from \"./mergeHead.ts\";\nimport type Router from \"./Router.ts\";\n\n/**\n * The site's request handler, as created by `createServerLoad`.\n */\nexport type ServerLoad = (ev: ServerEvent, template?: string) => Promise<Response>;\n\n/**\n * Creates the site's request handler for the given router. This is kept\n * separate from serverEntry, which imports the virtual\n * `@torpor/build/manifest` module (it only exists when a site runs or\n * builds), so that tests can exercise the handlers with their own routes.\n *\n * @param router The router, built from the site's routes\n * @param basePath The site's base path, stripped from incoming URLs before\n * routing (see basePath.ts)\n * @param middleware Global middleware (from `site.middleware`), run for\n * every request before routing -- including requests that won't match a\n * route\n * @returns The request handler, which takes the site template\n */\nexport function createServerLoad(\n\trouter: Router,\n\tbasePath = \"\",\n\tmiddleware: MiddlewareFunction[] = [],\n): ServerLoad {\n\t// The base path is shared through module state, so that everything that\n\t// generates URLs (HTML attributes, redirect locations) sees the same\n\t// value the router strips\n\tsetBasePath(basePath);\n\n\tconst handle = async (ev: ServerEvent, template?: string): Promise<Response> => {\n\t\t// The base is stripped before routing, so that everything below (route\n\t\t// matching, params, user code reading `event.url`) is base-free.\n\t\t// Requests that don't carry the base aren't ours\n\t\tconst url = stripBaseFromUrl(ev.url, basePath);\n\t\tif (!url) {\n\t\t\treturn handleResponse(notFound());\n\t\t}\n\t\tconst path = url.pathname;\n\t\tconst query = url.searchParams;\n\n\t\t//console.log(`handling ${ev.request.method} for '${path}'${query.size ? ` with ${query}` : \"\"}`);\n\n\t\tlet route = router.match(path, query);\n\t\tif (!route) {\n\t\t\t// If the route wasn't found, the user may be posting a form to a\n\t\t\t// +page.server.ts route that doesn't have a corresponding +page.ts\n\t\t\t// route, which is allowed, so check for that as well\n\t\t\tif (ev.request.method === \"POST\" && !path.endsWith(\"/~server\")) {\n\t\t\t\tconst serverPath =\n\t\t\t\t\t(path.endsWith(\"/\") ? path.substring(0, path.length - 1) : path) + \"/~server\";\n\t\t\t\troute = router.match(serverPath, query);\n\t\t\t}\n\t\t}\n\t\tif (!route) {\n\t\t\treturn handleResponse(notFound());\n\t\t}\n\t\tconst handler = route.handler;\n\t\tconst params = route.params || {};\n\n\t\t// Route middleware, declared on the route's server endpoint\n\t\t// (+page.server.ts / +server.ts). Runs after the global middleware and\n\t\t// before folder hooks, so a guard can skip data loading entirely\n\t\tconst routeMiddleware: MiddlewareFunction[] = [];\n\t\tconst endPointModule = handler.serverEndPoint\n\t\t\t? (await handler.serverEndPoint())?.default\n\t\t\t: handler.type === PAGE_SERVER_ROUTE || handler.type === SERVER_ROUTE\n\t\t\t\t? (await resolveModule(handler))?.default\n\t\t\t\t: undefined;\n\t\tif (Array.isArray(endPointModule?.middleware)) {\n\t\t\trouteMiddleware.push(...endPointModule.middleware);\n\t\t}\n\n\t\t// Update $page before building the components\n\t\t$page.url = url;\n\t\tif (path.endsWith(\"/_error\")) {\n\t\t\t$page.status = parseInt(query.get(\"status\") ?? \"404\");\n\t\t\t$page.error = { message: query.get(\"message\") ?? \"\" };\n\t\t} else {\n\t\t\t$page.status = 200;\n\t\t}\n\n\t\t// TODO: Hit the server hook out here\n\t\t// We could maybe set up data loading as middleware on a route??????\n\n\t\t// Run the route's middleware around the handler: enter hooks in order\n\t\t// (a Response short-circuits the request), exit hooks in reverse\n\t\tlet enteredRoute = 0;\n\t\tlet routeResponse: Response | undefined = undefined;\n\t\ttry {\n\t\t\tfor (; enteredRoute < routeMiddleware.length && !routeResponse; enteredRoute++) {\n\t\t\t\tconst result = await routeMiddleware[enteredRoute].enter?.(ev);\n\t\t\t\tif (result) {\n\t\t\t\t\trouteResponse = result;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (routeResponse) {\n\t\t\t\treturn routeResponse;\n\t\t\t}\n\n\t\t\tswitch (handler.type) {\n\t\t\t\tcase PAGE_ROUTE:\n\t\t\t\tcase LAYOUT_ROUTE: {\n\t\t\t\t\t// It's a /+page.ts or /_layout.ts endpoint\n\t\t\t\t\tif (ev.request.method === \"GET\") {\n\t\t\t\t\t\treturn handleResponse(await loadView(ev, url, handler, params, template));\n\t\t\t\t\t} else if (ev.request.method === \"POST\") {\n\t\t\t\t\t\t// The server end point comes from the sibling /+page.server.ts, if applicable\n\t\t\t\t\t\tconst serverEndPoint: PageServerEndPoint | undefined =\n\t\t\t\t\t\t\thandler.serverEndPoint && (await handler.serverEndPoint()).default;\n\t\t\t\t\t\treturn handleResponse(\n\t\t\t\t\t\t\tawait runAction(ev, url, handler, serverEndPoint, params, query, template),\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase PAGE_SERVER_ROUTE:\n\t\t\t\tcase LAYOUT_SERVER_ROUTE: {\n\t\t\t\t\t// It's a /+page.server.ts or /_layout.server.ts endpoint\n\t\t\t\t\tif (ev.request.method === \"GET\") {\n\t\t\t\t\t\treturn await loadData(ev, url, handler, \"load\", params);\n\t\t\t\t\t} else if (ev.request.method === \"POST\") {\n\t\t\t\t\t\tconst serverEndPoint: PageServerEndPoint | undefined = (await resolveModule(handler))\n\t\t\t\t\t\t\t.default;\n\t\t\t\t\t\treturn handleResponse(\n\t\t\t\t\t\t\tawait runAction(ev, url, handler, serverEndPoint, params, query, template),\n\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase SERVER_ROUTE: {\n\t\t\t\t\t// It's a /+server.ts endpoint\n\t\t\t\t\tconst functionName = ev.request.method.toLowerCase().replace(\"delete\", \"del\");\n\t\t\t\t\treturn await loadData(ev, url, handler, functionName, params);\n\t\t\t\t}\n\t\t\t\tcase HOOK_ROUTE:\n\t\t\t\tcase HOOK_SERVER_ROUTE: {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase ERROR_ROUTE: {\n\t\t\t\t\treturn await loadView(ev, url, handler, params, template);\n\t\t\t\t}\n\t\t\t}\n\t\t} finally {\n\t\t\twhile (enteredRoute > 0) {\n\t\t\t\tenteredRoute--;\n\t\t\t\tawait routeMiddleware[enteredRoute].exit?.(ev);\n\t\t\t}\n\t\t}\n\n\t\treturn notFound();\n\t};\n\n\treturn async function load(ev: ServerEvent, template?: string): Promise<Response> {\n\t\t// Global middleware, from `site.middleware`: runs for every request\n\t\t// before routing, including ones that won't match a route\n\t\t// (maintenance mode, legacy url redirects, etc)\n\t\tlet entered = 0;\n\t\ttry {\n\t\t\tlet response: Response | undefined = undefined;\n\t\t\tfor (; entered < middleware.length && !response; entered++) {\n\t\t\t\tconst result = await middleware[entered].enter?.(ev);\n\t\t\t\tif (result) {\n\t\t\t\t\tresponse = result;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (response) {\n\t\t\t\treturn response;\n\t\t\t}\n\t\t\treturn await handle(ev, template);\n\t\t} catch (error) {\n\t\t\t// Middleware exits can inspect (and replace, in Server.fetch) the\n\t\t\t// error via `ev.error`\n\t\t\tev.error = error;\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\twhile (entered > 0) {\n\t\t\t\tentered--;\n\t\t\t\tawait middleware[entered].exit?.(ev);\n\t\t\t}\n\t\t}\n\t};\n}\n\n/**\n * Resolves the route's endpoint module, caching it on the handler so warm\n * requests don't pay for the loader promise.\n */\nasync function resolveModule(handler: RouteHandler): Promise<any> {\n\treturn (handler.resolvedModule ??= await (handler.modulePromise ??= handler.endPoint()));\n}\n\nasync function loadServerHooks(handler: RouteHandler): Promise<ServerHook[]> {\n\tif (!handler.serverHooks) return [];\n\t// Resolve each hook module once and cache the result on the handler\n\treturn (handler.resolvedHooks ??= Promise.all(\n\t\thandler.serverHooks.map(async (load) => (await load()).default),\n\t));\n}\n\nasync function handleResponse(response: Response, fromForm = false): Promise<Response> {\n\t$page.status = response.status;\n\n\t// Success codes and redirect codes are acceptable\n\tif (response.status >= 200 && response.status <= 399) {\n\t\treturn response;\n\t}\n\n\t// 4xx error codes are acceptable from form actions\n\tif (fromForm && response.status >= 400 && response.status <= 499) {\n\t\treturn response;\n\t}\n\n\t// It's an error, so redirect to the error page\n\t// We're just pushing the status and message in the URL, but maybe there's a\n\t// more sophisticated way to do this?\n\t// TODO: Should be returning loadView rather than redirecting\n\t// TODO: Should be returning the NEAREST error page to this path, including layouts\n\tlet params = new URLSearchParams();\n\tparams.append(\"status\", $page.status.toString());\n\tlet message = await response.text();\n\tif (response.headers.get(\"Content-Type\")?.includes(\"application/json\")) {\n\t\tconst data = JSON.parse(message);\n\t\tmessage = data.message ?? message;\n\t}\n\tif (message) {\n\t\tif ($page.error) {\n\t\t\t$page.error.message = message;\n\t\t} else {\n\t\t\t$page.error = { message };\n\t\t}\n\t\tparams.append(\"message\", message);\n\t}\n\treturn seeOther(`/_error?${params.toString()}`);\n}\n\nasync function loadData(\n\tev: ServerEvent,\n\turl: URL,\n\thandler: RouteHandler,\n\tfunctionName: string,\n\tparams: Record<string, any>,\n) {\n\t// The endpoint module is cached on the handler, so once warm this is a\n\t// plain property read\n\tconst mod = handler.resolvedModule ?? (await resolveModule(handler));\n\tconst serverEndPoint: ServerEndPoint | undefined = mod?.default;\n\t// `functionName` is computed from the request method, so the handlers are\n\t// accessed through a loose record\n\tconst handlerFn = (\n\t\tserverEndPoint as unknown as Record<string, ServerRequest | undefined> | undefined\n\t)?.[functionName];\n\tif (!serverEndPoint || !handlerFn) {\n\t\treturn notFound();\n\t}\n\n\t// Route params come from the URL, so a failed validation means the\n\t// resource doesn't exist. Only endpoints declaring a params schema pay\n\t// for validation\n\tconst paramsSchema = endpointSchema(serverEndPoint, \"params\");\n\tif (paramsSchema) {\n\t\ttry {\n\t\t\tparams = (await validate(paramsSchema, params)) as Record<string, any>;\n\t\t} catch (error) {\n\t\t\tif (error instanceof ValidationError) return notFound();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\ttry {\n\t\t// If the endpoint declares a schema for this handler, validate its\n\t\t// input up front and reject with 422 if it fails. get/head/load\n\t\t// schemas validate the query string; other schemas validate the json\n\t\t// body. Endpoints without a schema skip straight to the handler\n\t\tconst schema = endpointSchema(serverEndPoint, functionName);\n\t\tconst values = schema\n\t\t\t? functionName === \"get\" || functionName === \"head\" || functionName === \"load\"\n\t\t\t\t? { query: await validate(schema, searchParamsToRecord(url.searchParams)) }\n\t\t\t\t: { json: await validate(schema, await ev.json()) }\n\t\t\t: {};\n\n\t\tconst serverParams = buildServerParams(ev, url, params, values);\n\n\t\t// Hooks are resolved once per handler; routes without hooks don't\n\t\t// await anything here\n\t\tconst hooks = handler.serverHooks ? await loadServerHooks(handler) : [];\n\n\t\tlet entered = 0;\n\t\tlet enterResponse: Response | undefined = undefined;\n\t\ttry {\n\t\t\t// Hooks run from the root down; a hook's enter can return a\n\t\t\t// Response to short-circuit the request\n\t\t\tfor (; entered < hooks.length && !enterResponse; entered++) {\n\t\t\t\tconst hookResult = await hooks[entered].enter?.(serverParams);\n\t\t\t\tif (hookResult) {\n\t\t\t\t\tenterResponse = hookResult;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// A hook's enter response short-circuits the request; otherwise, if\n\t\t\t// there was no response returned from load (such as errors or a\n\t\t\t// redirect), send an ok response\n\t\t\treturn enterResponse || (await handlerFn(serverParams)) || ok();\n\t\t} finally {\n\t\t\t// Run exit hooks in reverse order for hooks that were entered\n\t\t\twhile (entered > 0) {\n\t\t\t\tentered--;\n\t\t\t\tawait hooks[entered].exit?.(serverParams);\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tconst response = validationErrorResponse(error);\n\t\tif (response) return response;\n\t\tthrow error;\n\t}\n}\n\nasync function loadView(\n\tev: ServerEvent,\n\turl: URL,\n\thandler: RouteHandler,\n\tparams: Record<string, any>,\n\ttemplate: string | undefined,\n\tformStatus?: number,\n\tform?: Record<string, string | number>,\n\tfromForm?: boolean,\n) {\n\t// There must be a client endpoint with a component\n\tconst clientEndPoint: PageEndPoint | undefined = (await resolveModule(handler)).default;\n\tif (!clientEndPoint?.component) {\n\t\treturn notFound();\n\t}\n\n\t// Consume the flash message when a page is rendered (but not for API\n\t// requests), so that the following page -- and only that page -- can show\n\t// it. For a form action that re-renders instead of redirecting, the\n\t// message is set and read within this request\n\t$page.flash = ev.flash.get();\n\n\t// The template comes from site.html, which endpoints-only sites don't have\n\tif (!template) {\n\t\tthrow new Error(\n\t\t\t\"Page routes require a src/site.html file, which was not found; add it, or remove page/layout routes to serve endpoints only\",\n\t\t);\n\t}\n\n\t// There may be a server endpoint\n\tconst serverEndPoint: PageServerEndPoint | undefined =\n\t\thandler.serverEndPoint && (await handler.serverEndPoint())?.default;\n\n\t// Validate the route params and the load query against the server\n\t// endpoint's schemas, if it declares any. Params come from the URL, so a\n\t// failed validation means the resource doesn't exist; a failed query goes\n\t// to the error page like any other load failure\n\tlet query: unknown;\n\tif (serverEndPoint) {\n\t\ttry {\n\t\t\tparams = await validateEndpointParams(serverEndPoint, params);\n\t\t} catch (error) {\n\t\t\tif (error instanceof ValidationError) return notFound();\n\t\t\tthrow error;\n\t\t}\n\t\tconst loadSchema = endpointSchema(serverEndPoint, \"load\");\n\t\tif (loadSchema) {\n\t\t\tconst queryRecord = searchParamsToRecord(url.searchParams);\n\t\t\ttry {\n\t\t\t\tquery = await validate(loadSchema, queryRecord);\n\t\t\t} catch (error) {\n\t\t\t\t// A form re-render's url is the POST's, and a form action can\n\t\t\t\t// drop query params that the load schema requires, so failing\n\t\t\t\t// validation here would lose the form errors. Fall back to the\n\t\t\t\t// raw query values instead and let the load make of them what\n\t\t\t\t// it can\n\t\t\t\tif (fromForm) {\n\t\t\t\t\tquery = queryRecord;\n\t\t\t\t} else {\n\t\t\t\t\tconst response = validationErrorResponse(error);\n\t\t\t\t\tif (response) return response;\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Maybe hit the server hooks -- unless they already ran for this request,\n\t// which is the case when the view is re-rendered after a form action\n\tconst serverParams = buildServerParams(ev, url, params, query ? { query } : {});\n\tconst serverHooks = fromForm ? [] : await loadServerHooks(handler);\n\tlet entered = 0;\n\tlet enterResponse: Response | undefined = undefined;\n\ttry {\n\t\t// Hooks run from the root down; a hook's enter can return a Response\n\t\t// to short-circuit the request\n\t\tfor (; entered < serverHooks.length && !enterResponse; entered++) {\n\t\t\tconst hookResult = await serverHooks[entered].enter?.(serverParams);\n\t\t\tif (hookResult) {\n\t\t\t\tenterResponse = hookResult;\n\t\t\t}\n\t\t}\n\t\tif (enterResponse) {\n\t\t\treturn enterResponse;\n\t\t}\n\n\t\t// Pass the data into $props\n\t\t// TODO: Promise.all\n\t\t// NOTE: We're loading data from top to bottom, overriding as we go, and I'm\n\t\t// not sure if this is the best way to go\n\t\tlet data = {};\n\t\tif (handler.layouts) {\n\t\t\tfor (let layout of handler.layouts) {\n\t\t\t\tconst layoutEndPoint: PageEndPoint | undefined = (await layout.endPoint())?.default;\n\t\t\t\tconst layoutServerEndPoint: PageServerEndPoint | undefined =\n\t\t\t\t\tlayout.serverEndPoint && (await layout.serverEndPoint())?.default;\n\t\t\t\tconst layoutResponse = await loadClientAndServerData(\n\t\t\t\t\turl,\n\t\t\t\t\tparams,\n\t\t\t\t\tserverParams,\n\t\t\t\t\tdata,\n\t\t\t\t\tlayoutEndPoint,\n\t\t\t\t\tlayoutServerEndPoint,\n\t\t\t\t);\n\t\t\t\tif (layoutResponse?.ok === false) {\n\t\t\t\t\treturn layoutResponse;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlet endPointResponse = await loadClientAndServerData(\n\t\t\turl,\n\t\t\tparams,\n\t\t\tserverParams,\n\t\t\tdata,\n\t\t\tclientEndPoint,\n\t\t\tserverEndPoint,\n\t\t);\n\t\tif (endPointResponse?.ok === false) {\n\t\t\treturn endPointResponse;\n\t\t}\n\t\tlet $props: Record<string, any> = { data, form };\n\n\t\tlet styles = \"\";\n\n\t\t// If there are layouts, work our way upwards, pushing each component into\n\t\t// the default slot of its parent\n\t\t// TODO: Also handle layout server data\n\t\t// TODO: There's probably a nicer way to do this with reducers or something\n\t\tlet component = clientEndPoint.component as ServerComponent;\n\t\tlet slots: Record<string, ServerSlotRender> | undefined = undefined;\n\t\t// Which slot levels actually ran during the render below, so a layout\n\t\t// that never rendered its <slot /> (silently dropping the page\n\t\t// content) can be reported (see findMissingSlotLayout)\n\t\tconst invokedLevels = new Set<number>();\n\t\tconst trackSlot = (level: number, slot: ServerSlotRender): ServerSlotRender => {\n\t\t\treturn ($slot, $context) => {\n\t\t\t\tinvokedLevels.add(level);\n\t\t\t\treturn slot($slot, $context);\n\t\t\t};\n\t\t};\n\t\tif (handler.layouts) {\n\t\t\tlet slotFunctions: ServerSlotRender[] = [];\n\t\t\t// The last slot function will render the client component\n\t\t\tslotFunctions[handler.layouts.length] = trackSlot(\n\t\t\t\thandler.layouts.length,\n\t\t\t\tasync (_, $context) => {\n\t\t\t\t\tlet { body, head } = await (clientEndPoint.component as ServerComponent)(\n\t\t\t\t\t\t$props,\n\t\t\t\t\t\t$context,\n\t\t\t\t\t);\n\t\t\t\t\tstyles += head;\n\t\t\t\t\treturn body;\n\t\t\t\t},\n\t\t\t);\n\t\t\tfor (let i = handler.layouts.length - 1; i >= 0; i--) {\n\t\t\t\tconst layoutEndPoint: PageEndPoint | undefined = (await handler.layouts[i].endPoint())\n\t\t\t\t\t?.default;\n\t\t\t\tif (layoutEndPoint?.component) {\n\t\t\t\t\tif (i === 0) {\n\t\t\t\t\t\tcomponent = layoutEndPoint.component as ServerComponent;\n\t\t\t\t\t\tslots = { _: slotFunctions[i + 1] };\n\t\t\t\t\t} else {\n\t\t\t\t\t\tslotFunctions[i] = trackSlot(i, async (_, $context) => {\n\t\t\t\t\t\t\tlet { body, head } = await (layoutEndPoint.component as ServerComponent)(\n\t\t\t\t\t\t\t\t$props,\n\t\t\t\t\t\t\t\t$context,\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t_: slotFunctions[i + 1],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tstyles += head;\n\t\t\t\t\t\t\treturn body;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet html;\n\t\ttry {\n\t\t\tlet { body, head } = await component($props, undefined, slots);\n\n\t\t\t// Render the page's (and its layouts') head element data, if the\n\t\t\t// endpoint declared any. Layouts lose to the page (the nearest\n\t\t\t// endpoint wins, as with @head content), and everything loses to\n\t\t\t// the first title in the compiled head -- which mergeHead keeps\n\t\t\tlet headData = \"\";\n\t\t\tconst event = { url, params, data } as PageLoadEvent;\n\t\t\tconst layoutEndPoints = await Promise.all(\n\t\t\t\t(handler.layouts ?? []).map(async (layout) => await layout.endPoint()),\n\t\t\t);\n\t\t\tconst headPoints = [clientEndPoint, ...layoutEndPoints].reverse();\n\t\t\tfor (const endPoint of headPoints) {\n\t\t\t\tconst headElements =\n\t\t\t\t\ttypeof endPoint.head === \"function\" ? await endPoint.head(event) : endPoint.head;\n\t\t\t\tif (headElements) {\n\t\t\t\t\theadData += headElements.map((element: HeadElement) => markupOf(element)).join(\"\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Put the form info in a hidden input so that it can be accessed on the client\n\t\t\tif (form) {\n\t\t\t\tbody += `\\n<input type=\"hidden\" id=\"t-form-data\" value='${JSON.stringify(form).replaceAll(\"'\", \"\\\\'\")}' />`;\n\t\t\t}\n\n\t\t\tstyles += head;\n\t\t\thtml = rewriteBaseInHtml(\n\t\t\t\tmergeHead(template, styles + headData).replace(\"%COMPONENT_BODY%\", body),\n\t\t\t\tgetBasePath(),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\t// TODO: Show a proper Error component\n\t\t\thtml = '<span style=\"color: red\">Script syntax error</span><p>' + error + \"</p>\";\n\t\t\tconsole.log(error);\n\t\t}\n\n\t\t// A layout that never rendered <slot /> silently drops the whole page\n\t\t// content from the output; find and report the outermost one\n\t\tif (handler.layouts) {\n\t\t\tconst missingLayout = findMissingSlotLayout(handler.layouts, invokedLevels);\n\t\t\tif (missingLayout !== undefined) {\n\t\t\t\twarnMissingSlotContent(missingLayout);\n\t\t\t}\n\t\t}\n\n\t\treturn new Response(html, {\n\t\t\tstatus: formStatus ?? 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/html\",\n\t\t\t},\n\t\t});\n\t} finally {\n\t\t// Run exit hooks in reverse order for hooks that were entered\n\t\twhile (entered > 0) {\n\t\t\tentered--;\n\t\t\tawait serverHooks[entered].exit?.(serverParams);\n\t\t}\n\t}\n}\n\nasync function runAction(\n\tev: ServerEvent,\n\turl: URL,\n\thandler: RouteHandler,\n\tserverEndPoint: PageServerEndPoint | undefined,\n\tparams: Record<string, any>,\n\tquery: URLSearchParams,\n\ttemplate: string | undefined,\n) {\n\t// The action name rides in the query, so look for a `?/name` key rather\n\t// than taking the first key -- the url may carry ordinary load query\n\t// params as well (e.g. `?page=3&/like`, or a default action posted to a\n\t// url that already has a query). A key that names a declared action also\n\t// matches (e.g. `?set`), and a form without an action attribute calls the\n\t// `default` action\n\tconst queryKeys = Array.from(query.keys());\n\tconst actionKey =\n\t\tqueryKeys.find((key) => key.startsWith(\"/\")) ??\n\t\tqueryKeys.find((key) => !!serverEndPoint?.actions?.[key.replace(/^\\//, \"\")]);\n\tconst actionName = (actionKey ?? \"default\").replace(/^\\//, \"\");\n\tif (serverEndPoint?.actions) {\n\t\tconst action = serverEndPoint.actions[actionName];\n\t\tif (action) {\n\t\t\tif (actionName === \"load\" || actionName === \"params\") {\n\t\t\t\t// These names are reserved in the endpoint's schema map: `load`\n\t\t\t\t// validates the query string and `params` the route params, so\n\t\t\t\t// an action with one of these names would get the wrong schema\n\t\t\t\t// applied to its form data\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The action name \"${actionName}\" is reserved. ` +\n\t\t\t\t\t\t`Rename the action (and its schema key, if any), e.g. to \"save\".`,\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Route params come from the URL, so a failed validation means the\n\t\t\t// resource doesn't exist\n\t\t\ttry {\n\t\t\t\tparams = await validateEndpointParams(serverEndPoint, params);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof ValidationError) return notFound();\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tlet result: Response | undefined | void;\n\t\t\ttry {\n\t\t\t\t// If the endpoint declares a schema for this action, validate the\n\t\t\t\t// submitted form data up front and reject with 422 if it fails\n\t\t\t\tconst schema = endpointSchema(serverEndPoint, actionName);\n\t\t\t\tconst form = schema\n\t\t\t\t\t? await validate(schema, await formDataToRecord(ev.request))\n\t\t\t\t\t: undefined;\n\n\t\t\t\tconst serverParams = buildServerParams(ev, url, params, form ? { form } : {});\n\n\t\t\t\tconst serverHooks = await loadServerHooks(handler);\n\t\t\t\tlet entered = 0;\n\t\t\t\tlet enterResponse: Response | undefined = undefined;\n\t\t\t\ttry {\n\t\t\t\t\t// Hooks run from the root down; a hook's enter can return a\n\t\t\t\t\t// Response to short-circuit the action\n\t\t\t\t\tfor (; entered < serverHooks.length && !enterResponse; entered++) {\n\t\t\t\t\t\tconst hookResult = await serverHooks[entered].enter?.(serverParams);\n\t\t\t\t\t\tif (hookResult) {\n\t\t\t\t\t\t\tenterResponse = hookResult;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tresult = enterResponse || (await action(serverParams));\n\t\t\t\t} finally {\n\t\t\t\t\t// Run exit hooks in reverse order for hooks that were entered\n\t\t\t\t\twhile (entered > 0) {\n\t\t\t\t\t\tentered--;\n\t\t\t\t\t\tawait serverHooks[entered].exit?.(serverParams);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconst response = validationErrorResponse(error);\n\t\t\t\tif (response) return response;\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tif (ev.request.headers.has(\"X-Torpor-Form-Submit\")) {\n\t\t\t\t// If the form was submitted from javascript, just return the\n\t\t\t\t// response and it will be handled on the client\n\t\t\t\t// TODO: Should we make the user return a response??\n\t\t\t\tresult ??= ok();\n\n\t\t\t\t// If it's a redirect, we need to stop the browser handling it\n\t\t\t\tif (result.status >= 300 && result.status <= 399) {\n\t\t\t\t\tconst location = result.headers.get(\"Location\") ?? \"\";\n\t\t\t\t\tresult = ok();\n\t\t\t\t\tresult.headers.set(\"X-Torpor-Form-Redirect\", \"\");\n\t\t\t\t\tresult.headers.set(\"Location\", location);\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t} else if (\n\t\t\t\t!result ||\n\t\t\t\t(result.status >= 200 && result.status <= 299) ||\n\t\t\t\t(result.status >= 400 && result.status <= 499)\n\t\t\t) {\n\t\t\t\t// If the form was submitted without javascript, and there was\n\t\t\t\t// no result, an ok result, or a 4xx error, re-render the view\n\t\t\t\t// with the form result. The server hook already ran around the\n\t\t\t\t// action, so it is not run again here\n\t\t\t\t// Keep the query string, so that loads validating the query see\n\t\t\t\t// the same values as the original GET. If the form action\n\t\t\t\t// dropped params that the load schema requires, loadView falls\n\t\t\t\t// back to the raw query instead of failing validation\n\t\t\t\tconst newUrl = new URL(url.pathname + url.search, url);\n\t\t\t\tconst formStatus = result?.status;\n\t\t\t\tlet formMessage = await result?.text();\n\t\t\t\tif (formMessage && result?.headers.get(\"Content-Type\")?.includes(\"application/json\")) {\n\t\t\t\t\t$page.form = JSON.parse(formMessage);\n\t\t\t\t\tformMessage = undefined;\n\t\t\t\t} else {\n\t\t\t\t\t$page.form = {};\n\t\t\t\t}\n\t\t\t\t// Set status and message if they haven't already been set,\n\t\t\t\t// which means that you can just return e.g. forbidden() or\n\t\t\t\t// forbidden(\"no!\") and there will be something you can work\n\t\t\t\t// with in your component, or you can set a completely custom\n\t\t\t\t// object with whatever info you need\n\t\t\t\t$page.form!.status ??= formStatus ?? 0;\n\t\t\t\t$page.form!.message ??= formMessage ?? \"\";\n\t\t\t\treturn await loadView(ev, newUrl, handler, params, template, formStatus, $page.form, true);\n\t\t\t} else {\n\t\t\t\t// If the form was submitted without javascript and there was a\n\t\t\t\t// redirect or server error, just return the result to handle it\n\t\t\t\t// as normal\n\t\t\t\treturn result;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn notFound();\n}\n\nasync function loadClientAndServerData(\n\turl: URL,\n\tparams: Record<string, any>,\n\tserverParams: ServerLoadEvent,\n\tdata: Record<string, any>,\n\tclientEndPoint?: PageEndPoint,\n\tserverEndPoint?: PageServerEndPoint,\n) {\n\tif (clientEndPoint?.load) {\n\t\tconst clientParams = buildClientParams(url, params, data);\n\t\tconst clientResponse = await clientEndPoint.load(clientParams);\n\t\tif (clientResponse) {\n\t\t\tif (clientResponse.ok) {\n\t\t\t\tif (clientResponse.headers.get(\"Content-Type\")?.includes(\"application/json\")) {\n\t\t\t\t\tObject.assign(data, await clientResponse.json());\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn clientResponse;\n\t\t\t}\n\t\t}\n\t}\n\tif (serverEndPoint?.load) {\n\t\tconst serverResponse = await serverEndPoint.load(serverParams);\n\t\tif (serverResponse) {\n\t\t\tif (serverResponse.ok) {\n\t\t\t\tif (serverResponse.headers.get(\"Content-Type\")?.includes(\"application/json\")) {\n\t\t\t\t\tObject.assign(data, await serverResponse.json());\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn serverResponse;\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction buildClientParams(url: URL, params: Record<string, any>, data: Record<string, any>) {\n\treturn {\n\t\turl,\n\t\tparams,\n\t\tdata,\n\t};\n}\n\nfunction buildServerParams(\n\tev: ServerEvent,\n\turl: URL,\n\tparams: Record<string, any>,\n\tvalues: { json?: unknown; form?: unknown; query?: unknown } = {},\n): ServerLoadEvent {\n\treturn {\n\t\turl,\n\t\tparams,\n\t\tappData: {},\n\t\trequest: ev.request,\n\t\t// The inputs may have been validated already, in which case the request\n\t\t// body has been consumed and the parsed values are returned instead.\n\t\t// Their types come from the endpoint's schemas, so they are loosely\n\t\t// typed here\n\t\tjson: (): Promise<any> =>\n\t\t\tvalues.json !== undefined ? Promise.resolve(values.json) : ev.json(),\n\t\tform: (): Promise<any> =>\n\t\t\tvalues.form !== undefined ? Promise.resolve(values.form) : formDataToRecord(ev.request),\n\t\tquery: (): Promise<any> =>\n\t\t\tvalues.query !== undefined\n\t\t\t\t? Promise.resolve(values.query)\n\t\t\t\t: Promise.resolve(searchParamsToRecord(url.searchParams)),\n\t\tcookies: ev.cookies,\n\t\theaders: ev.headers,\n\t\tsession: ev.session,\n\t\tflash: ev.flash,\n\t\tadapter: ev.adapter,\n\t};\n}\n\n/**\n * Renders a head element as markup. Attribute values are escaped, since\n * they can come from user data (e.g. a post title passed to `seo()`).\n */\nfunction markupOf(element: HeadElement): string {\n\tif (\"title\" in element) {\n\t\treturn `<title>${escapeHtml(element.title)}</title>`;\n\t}\n\tif (\"name\" in element) {\n\t\treturn `<meta name=\"${escapeHtml(element.name)}\" content=\"${escapeHtml(element.content)}\" />`;\n\t}\n\treturn `<meta property=\"${escapeHtml(element.property)}\" content=\"${escapeHtml(element.content)}\" />`;\n}\n\nfunction escapeHtml(value: string): string {\n\treturn value\n\t\t.replaceAll(\"&\", \"&\")\n\t\t.replaceAll(\"<\", \"<\")\n\t\t.replaceAll(\">\", \">\")\n\t\t.replaceAll('\"', \""\");\n}\n"],"mappings":"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"}
|