@torpor/build 1.0.2 → 1.2.0
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/Jsonify-Dg6gChd3.d.mts.map +1 -1
- package/dist/Router-COdQuVUi.d.mts +59 -0
- package/dist/Router-COdQuVUi.d.mts.map +1 -0
- package/dist/{Server-BnjLJleZ.mjs → Server-Dr6yqVa5.mjs} +2 -2
- package/dist/{Server-BnjLJleZ.mjs.map → Server-Dr6yqVa5.mjs.map} +1 -1
- package/dist/{ServerEvent-Dljn5i7A.mjs → ServerEvent-gmOvC_Yf.mjs} +3 -2
- package/dist/{ServerEvent-Dljn5i7A.mjs.map → ServerEvent-gmOvC_Yf.mjs.map} +1 -1
- package/dist/ServerHook-BlLArueW.d.mts +91 -0
- package/dist/ServerHook-BlLArueW.d.mts.map +1 -0
- package/dist/{Site-CE0_o5Ci.d.mts → Site-CTADVh7d.d.mts} +12 -91
- package/dist/Site-CTADVh7d.d.mts.map +1 -0
- package/dist/bin/index.js +1 -1
- package/dist/clientEntry.mjs +3 -2
- package/dist/clientEntry.mjs.map +1 -1
- package/dist/dev.d.mts +1 -1
- package/dist/dev.mjs +2 -2
- package/dist/index.d.mts +3 -57
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +153 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{load-BntzvmwL.mjs → load-C9RpS_4j.mjs} +32 -26
- package/dist/{load-BntzvmwL.mjs.map → load-C9RpS_4j.mjs.map} +1 -1
- package/dist/nav.d.mts.map +1 -1
- package/dist/nav.mjs +7 -5
- package/dist/nav.mjs.map +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/pathTrie-D4Ax2Mu9.mjs.map +1 -1
- package/dist/{response-Bg4w2S1q.mjs → response-CuNPcxsY.mjs} +2 -2
- package/dist/{response-Bg4w2S1q.mjs.map → response-CuNPcxsY.mjs.map} +1 -1
- package/dist/response.mjs +2 -2
- package/dist/run.d.mts +1 -1
- package/dist/run.mjs +1 -1
- package/dist/{runOpenApi-C8eI2Fh0.mjs → runOpenApi-yIzYasNN.mjs} +15 -15
- package/dist/{runOpenApi-C8eI2Fh0.mjs.map → runOpenApi-yIzYasNN.mjs.map} +1 -1
- package/dist/server/Server.mjs +1 -1
- package/dist/server.mjs +2 -2
- package/dist/serverEntry-CUXFQ07g.mjs +11 -0
- package/dist/serverEntry-CUXFQ07g.mjs.map +1 -0
- package/dist/serverEntry-DVv9YI3I.d.mts +13 -0
- package/dist/serverEntry-DVv9YI3I.d.mts.map +1 -0
- package/dist/serverEntry.d.mts +1 -1
- package/dist/serverEntry.mjs +1 -1
- package/dist/{serverEntry-1qY3wZig.mjs → serverHandlers-fzIlmvX-.mjs} +202 -74
- package/dist/serverHandlers-fzIlmvX-.mjs.map +1 -0
- package/dist/test.d.mts +1 -1
- package/dist/test.d.mts.map +1 -1
- package/dist/test.mjs +7 -242
- package/dist/test.mjs.map +1 -1
- package/dist/{unprocessable-DAZbrDeR.mjs → unprocessable-D6RcYLh6.mjs} +7 -5
- package/dist/{unprocessable-DAZbrDeR.mjs.map → unprocessable-D6RcYLh6.mjs.map} +1 -1
- package/package.json +5 -5
- package/dist/Site-CE0_o5Ci.d.mts.map +0 -1
- package/dist/endpoint-EULRGCKA.mjs +0 -108
- package/dist/endpoint-EULRGCKA.mjs.map +0 -1
- package/dist/serverEntry-1qY3wZig.mjs.map +0 -1
- package/dist/serverEntry-BAO8m03V.d.mts +0 -6
- package/dist/serverEntry-BAO8m03V.d.mts.map +0 -1
package/dist/test.mjs
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { t as Router } from "./Router-C4ADUfhv.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
4
|
-
import { n as ValidationError, t as validate } from "./validate-Ok4krlkX.mjs";
|
|
5
|
-
import { a as searchParamsToRecord, i as validationErrorResponse, n as validateEndpointParams, o as $page, r as validateHandlerInput, s as formDataToRecord, t as endpointSchema } from "./endpoint-EULRGCKA.mjs";
|
|
2
|
+
import { t as ServerEvent } from "./ServerEvent-gmOvC_Yf.mjs";
|
|
3
|
+
import { t as createServerLoad } from "./serverHandlers-fzIlmvX-.mjs";
|
|
6
4
|
import fpath from "node:path";
|
|
7
5
|
//#region src/test/runTest.ts
|
|
8
6
|
/**
|
|
@@ -14,7 +12,10 @@ import fpath from "node:path";
|
|
|
14
12
|
*/
|
|
15
13
|
async function runTest(site, route, ev) {
|
|
16
14
|
if (!route.startsWith("/")) route += "/";
|
|
17
|
-
if (!ev)
|
|
15
|
+
if (!ev) {
|
|
16
|
+
const req = new Request(`http://localhost${route}`);
|
|
17
|
+
ev = new ServerEvent(req);
|
|
18
|
+
}
|
|
18
19
|
const router = new Router();
|
|
19
20
|
router.addPages(site.routes.map((r) => ({
|
|
20
21
|
path: r.path,
|
|
@@ -32,243 +33,7 @@ async function runTest(site, route, ev) {
|
|
|
32
33
|
},
|
|
33
34
|
subFolder: r.subFolder
|
|
34
35
|
})));
|
|
35
|
-
return await
|
|
36
|
-
}
|
|
37
|
-
async function load(router, ev, template) {
|
|
38
|
-
const url = ev.url;
|
|
39
|
-
const path = url.pathname;
|
|
40
|
-
const query = url.searchParams;
|
|
41
|
-
const route = router.match(path, query);
|
|
42
|
-
if (!route) return notFound();
|
|
43
|
-
$page.url = url;
|
|
44
|
-
if (path.endsWith("/_error")) {
|
|
45
|
-
$page.status = parseInt(query.get("status") ?? "404");
|
|
46
|
-
$page.error = { message: query.get("message") ?? "" };
|
|
47
|
-
} else $page.status = 200;
|
|
48
|
-
const handler = route.handler;
|
|
49
|
-
const params = route.params || {};
|
|
50
|
-
switch (handler.type) {
|
|
51
|
-
case 0:
|
|
52
|
-
case 4:
|
|
53
|
-
if (ev.request.method === "GET") return await loadView(ev, url, handler, params, template);
|
|
54
|
-
else if (ev.request.method === "POST") return await runAction(ev, url, handler, handler.serverEndPoint && (await handler.serverEndPoint()).default, params, query);
|
|
55
|
-
break;
|
|
56
|
-
case 1:
|
|
57
|
-
case 5:
|
|
58
|
-
if (ev.request.method === "GET") return await loadData(ev, url, handler, "load", params);
|
|
59
|
-
else if (ev.request.method === "POST") return await runAction(ev, url, handler, handler.endPoint && (await handler.endPoint()).default, params, query);
|
|
60
|
-
break;
|
|
61
|
-
case 3: return await loadData(ev, url, handler, ev.request.method.toLowerCase().replace("delete", "del"), params);
|
|
62
|
-
case 8: return await loadView(ev, url, handler, params, template);
|
|
63
|
-
case 6:
|
|
64
|
-
case 7: break;
|
|
65
|
-
}
|
|
66
|
-
return notFound();
|
|
67
|
-
}
|
|
68
|
-
async function loadData(ev, url, handler, functionName, params) {
|
|
69
|
-
const serverEndPoint = (await handler.endPoint()).default;
|
|
70
|
-
const handlerFn = serverEndPoint?.[functionName];
|
|
71
|
-
if (serverEndPoint && handlerFn) {
|
|
72
|
-
try {
|
|
73
|
-
params = await validateEndpointParams(serverEndPoint, params);
|
|
74
|
-
} catch (error) {
|
|
75
|
-
if (error instanceof ValidationError) return notFound();
|
|
76
|
-
throw error;
|
|
77
|
-
}
|
|
78
|
-
try {
|
|
79
|
-
const values = await validateHandlerInput(endpointSchema(serverEndPoint, functionName), functionName, url, ev);
|
|
80
|
-
const serverParams = buildServerParams(ev, url, params, values);
|
|
81
|
-
const serverHooks = await loadServerHooks(handler);
|
|
82
|
-
let entered = 0;
|
|
83
|
-
let enterResponse = void 0;
|
|
84
|
-
try {
|
|
85
|
-
for (; entered < serverHooks.length && !enterResponse; entered++) {
|
|
86
|
-
const hookResult = await serverHooks[entered].enter?.(serverParams);
|
|
87
|
-
if (hookResult) enterResponse = hookResult;
|
|
88
|
-
}
|
|
89
|
-
return enterResponse || await handlerFn(serverParams) || ok();
|
|
90
|
-
} finally {
|
|
91
|
-
while (entered > 0) {
|
|
92
|
-
entered--;
|
|
93
|
-
await serverHooks[entered].exit?.(serverParams);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
} catch (error) {
|
|
97
|
-
const response = validationErrorResponse(error);
|
|
98
|
-
if (response) return response;
|
|
99
|
-
throw error;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return notFound();
|
|
103
|
-
}
|
|
104
|
-
async function loadView(ev, url, handler, params, template) {
|
|
105
|
-
const clientEndPoint = (await handler.endPoint()).default;
|
|
106
|
-
if (!clientEndPoint?.component) return notFound();
|
|
107
|
-
const serverEndPoint = handler.serverEndPoint && (await handler.serverEndPoint())?.default;
|
|
108
|
-
let query;
|
|
109
|
-
if (serverEndPoint) {
|
|
110
|
-
try {
|
|
111
|
-
params = await validateEndpointParams(serverEndPoint, params);
|
|
112
|
-
} catch (error) {
|
|
113
|
-
if (error instanceof ValidationError) return notFound();
|
|
114
|
-
throw error;
|
|
115
|
-
}
|
|
116
|
-
const loadSchema = endpointSchema(serverEndPoint, "load");
|
|
117
|
-
if (loadSchema) try {
|
|
118
|
-
query = await validate(loadSchema, searchParamsToRecord(url.searchParams));
|
|
119
|
-
} catch (error) {
|
|
120
|
-
const response = validationErrorResponse(error);
|
|
121
|
-
if (response) return response;
|
|
122
|
-
throw error;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
const serverParams = buildServerParams(ev, url, params, query ? { query } : {});
|
|
126
|
-
const serverHooks = await loadServerHooks(handler);
|
|
127
|
-
let entered = 0;
|
|
128
|
-
let enterResponse = void 0;
|
|
129
|
-
try {
|
|
130
|
-
for (; entered < serverHooks.length && !enterResponse; entered++) {
|
|
131
|
-
const hookResult = await serverHooks[entered].enter?.(serverParams);
|
|
132
|
-
if (hookResult) enterResponse = hookResult;
|
|
133
|
-
}
|
|
134
|
-
if (enterResponse) return enterResponse;
|
|
135
|
-
let data = {};
|
|
136
|
-
if (handler.layouts) for (let layout of handler.layouts) {
|
|
137
|
-
const layoutEndPoint = (await layout.endPoint())?.default;
|
|
138
|
-
const layoutServerEndPoint = layout.serverEndPoint && (await layout.serverEndPoint())?.default;
|
|
139
|
-
const layoutResponse = await loadClientAndServerData(url, params, serverParams, data, layoutEndPoint, layoutServerEndPoint);
|
|
140
|
-
if (layoutResponse?.ok === false) return layoutResponse;
|
|
141
|
-
}
|
|
142
|
-
let endPointResponse = await loadClientAndServerData(url, params, serverParams, data, clientEndPoint, serverEndPoint);
|
|
143
|
-
if (endPointResponse?.ok === false) return endPointResponse;
|
|
144
|
-
let $props = { data };
|
|
145
|
-
let styles = "";
|
|
146
|
-
let component = clientEndPoint.component;
|
|
147
|
-
let slots = void 0;
|
|
148
|
-
if (handler.layouts) {
|
|
149
|
-
let slotFunctions = [];
|
|
150
|
-
slotFunctions[handler.layouts.length] = (_, $context) => {
|
|
151
|
-
let { body, head } = clientEndPoint.component($props, $context);
|
|
152
|
-
styles += head;
|
|
153
|
-
return body;
|
|
154
|
-
};
|
|
155
|
-
for (let i = handler.layouts.length - 1; i >= 0; i--) {
|
|
156
|
-
const layoutEndPoint = (await handler.layouts[i].endPoint())?.default;
|
|
157
|
-
if (layoutEndPoint?.component) if (i === 0) {
|
|
158
|
-
component = layoutEndPoint.component;
|
|
159
|
-
slots = { _: slotFunctions[i + 1] };
|
|
160
|
-
} else slotFunctions[i] = (_, $context) => {
|
|
161
|
-
let { body, head } = layoutEndPoint.component($props, $context, { _: slotFunctions[i + 1] });
|
|
162
|
-
styles += head;
|
|
163
|
-
return body;
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
let html;
|
|
168
|
-
try {
|
|
169
|
-
let { body, head } = component($props, void 0, slots);
|
|
170
|
-
styles += head;
|
|
171
|
-
html = template.replace("%COMPONENT_BODY%", body).replace("%COMPONENT_HEAD%", styles);
|
|
172
|
-
} catch (error) {
|
|
173
|
-
html = "<span style=\"color: red\">Script syntax error</span><p>" + error + "</p>";
|
|
174
|
-
console.log(error);
|
|
175
|
-
}
|
|
176
|
-
return new Response(html, {
|
|
177
|
-
status: 200,
|
|
178
|
-
headers: { "Content-Type": "text/html" }
|
|
179
|
-
});
|
|
180
|
-
} finally {
|
|
181
|
-
while (entered > 0) {
|
|
182
|
-
entered--;
|
|
183
|
-
await serverHooks[entered].exit?.(serverParams);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
async function runAction(ev, url, handler, serverEndPoint, params, query) {
|
|
188
|
-
const actionName = (Array.from(query.keys())[0] || "default").replace(/^\//, "");
|
|
189
|
-
if (serverEndPoint?.actions) {
|
|
190
|
-
const action = serverEndPoint.actions[actionName];
|
|
191
|
-
if (action) {
|
|
192
|
-
if (actionName === "load" || actionName === "params") throw new Error(`The action name "${actionName}" is reserved. Rename the action (and its schema key, if any), e.g. to "save".`);
|
|
193
|
-
try {
|
|
194
|
-
params = await validateEndpointParams(serverEndPoint, params);
|
|
195
|
-
} catch (error) {
|
|
196
|
-
if (error instanceof ValidationError) return notFound();
|
|
197
|
-
throw error;
|
|
198
|
-
}
|
|
199
|
-
let result;
|
|
200
|
-
try {
|
|
201
|
-
const schema = endpointSchema(serverEndPoint, actionName);
|
|
202
|
-
const form = schema ? await validate(schema, await formDataToRecord(ev.request)) : void 0;
|
|
203
|
-
const serverParams = buildServerParams(ev, url, params, form ? { form } : {});
|
|
204
|
-
const serverHooks = await loadServerHooks(handler);
|
|
205
|
-
let entered = 0;
|
|
206
|
-
let enterResponse = void 0;
|
|
207
|
-
try {
|
|
208
|
-
for (; entered < serverHooks.length && !enterResponse; entered++) {
|
|
209
|
-
const hookResult = await serverHooks[entered].enter?.(serverParams);
|
|
210
|
-
if (hookResult) enterResponse = hookResult;
|
|
211
|
-
}
|
|
212
|
-
result = enterResponse || await action(serverParams);
|
|
213
|
-
} finally {
|
|
214
|
-
while (entered > 0) {
|
|
215
|
-
entered--;
|
|
216
|
-
await serverHooks[entered].exit?.(serverParams);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
} catch (error) {
|
|
220
|
-
const response = validationErrorResponse(error);
|
|
221
|
-
if (response) return response;
|
|
222
|
-
throw error;
|
|
223
|
-
}
|
|
224
|
-
return result || seeOther(url.pathname);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
return notFound();
|
|
228
|
-
}
|
|
229
|
-
async function loadClientAndServerData(url, params, serverParams, data, clientEndPoint, serverEndPoint) {
|
|
230
|
-
if (clientEndPoint?.load) {
|
|
231
|
-
const clientParams = buildClientParams(url, params, data);
|
|
232
|
-
const clientResponse = await clientEndPoint.load(clientParams);
|
|
233
|
-
if (clientResponse) if (clientResponse.ok) {
|
|
234
|
-
if (clientResponse.headers.get("Content-Type")?.includes("application/json")) Object.assign(data, await clientResponse.json());
|
|
235
|
-
} else return clientResponse;
|
|
236
|
-
}
|
|
237
|
-
if (serverEndPoint?.load) {
|
|
238
|
-
const serverResponse = await serverEndPoint.load(serverParams);
|
|
239
|
-
if (serverResponse) if (serverResponse.ok) {
|
|
240
|
-
if (serverResponse.headers.get("Content-Type")?.includes("application/json")) Object.assign(data, await serverResponse.json());
|
|
241
|
-
} else return serverResponse;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
function buildClientParams(url, params, data) {
|
|
245
|
-
return {
|
|
246
|
-
url,
|
|
247
|
-
params,
|
|
248
|
-
data
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Loads the route's server hooks, from the root down
|
|
253
|
-
*/
|
|
254
|
-
async function loadServerHooks(handler) {
|
|
255
|
-
const hooks = [];
|
|
256
|
-
if (handler.serverHooks) for (let serverHook of handler.serverHooks) hooks.push((await serverHook()).default);
|
|
257
|
-
return hooks;
|
|
258
|
-
}
|
|
259
|
-
function buildServerParams(ev, url, params, values = {}) {
|
|
260
|
-
return {
|
|
261
|
-
url,
|
|
262
|
-
params,
|
|
263
|
-
appData: {},
|
|
264
|
-
request: ev.request,
|
|
265
|
-
json: () => values.json !== void 0 ? Promise.resolve(values.json) : ev.json(),
|
|
266
|
-
form: () => values.form !== void 0 ? Promise.resolve(values.form) : formDataToRecord(ev.request),
|
|
267
|
-
query: () => values.query !== void 0 ? Promise.resolve(values.query) : Promise.resolve(searchParamsToRecord(url.searchParams)),
|
|
268
|
-
cookies: ev.cookies,
|
|
269
|
-
headers: ev.headers,
|
|
270
|
-
adapter: ev.adapter
|
|
271
|
-
};
|
|
36
|
+
return await createServerLoad(router)(ev, "%COMPONENT_BODY%");
|
|
272
37
|
}
|
|
273
38
|
//#endregion
|
|
274
39
|
export { runTest };
|
package/dist/test.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.mjs","names":["path","handlers"],"sources":["../src/test/runTest.ts"],"sourcesContent":["import { type ServerComponent, type ServerSlotRender } from \"@torpor/view/ssr\";\nimport path from \"node:path\";\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 Router from \"../site/Router.ts\";\nimport Site from \"../site/Site\";\nimport $page from \"../state/$serverPage.ts\";\nimport type PageEndPoint from \"../types/PageEndPoint.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\tvalidateHandlerInput,\n\tvalidationErrorResponse,\n} from \"../validation/endpoint.ts\";\n\n/**\n * Runs a site route in test mode\n * @param site The site configuration, with routing configured\n * @param route The route path e.g. `/home`\n * @param ev An optional ServerEvent, which you can use to set test cookies and headers\n * @returns An HTTP response containing the requested data, HTML, or error status\n */\nexport default async function runTest(\n\tsite: Site,\n\troute: string,\n\tev?: ServerEvent,\n): Promise<Response> {\n\tif (!route.startsWith(\"/\")) route += \"/\";\n\tif (!ev) {\n\t\tconst req = new Request(`http://localhost${route}`);\n\t\tev = new ServerEvent(req);\n\t}\n\n\t// Build the router from the Site object created by the user\n\tconst router = new Router();\n\trouter.addPages(\n\t\tsite.routes.map((r) => ({\n\t\t\tpath: r.path,\n\t\t\ttype: r.type,\n\t\t\tendPoint: async () => {\n\t\t\t\tif (r.file) {\n\t\t\t\t\tconst mod = await import(/* @vite-ignore */ path.join(site.root, r.file));\n\t\t\t\t\t// A .torp file's default export is a component, so wrap it as\n\t\t\t\t\t// a PageEndPoint ({ component }) for the entries\n\t\t\t\t\tif (r.file.endsWith(\".torp\")) {\n\t\t\t\t\t\treturn { default: { component: mod.default } };\n\t\t\t\t\t}\n\t\t\t\t\treturn mod;\n\t\t\t\t}\n\t\t\t\t// Inline endpoint (no file) — return directly from memory\n\t\t\t\treturn { default: r.endPoint };\n\t\t\t},\n\t\t\tsubFolder: r.subFolder,\n\t\t})),\n\t);\n\n\treturn await load(router, ev, \"%COMPONENT_BODY%\");\n}\n\n// HACK: This is a copy of serverEntry\n// TODO: Make it shared instead!\nasync function load(router: Router, ev: ServerEvent, template: string): Promise<Response> {\n\t//const url = new URL(`http://${process.env.HOST ?? \"localhost\"}${ev.request.url}`);\n\tconst url = ev.url;\n\tconst path = url.pathname;\n\tconst query = url.searchParams;\n\n\t//console.log(`handling ${ev.request.method} for '${path}'${query.size ? ` with ${query}` : \"\"}`);\n\n\tconst route = router.match(path, query);\n\tif (!route) {\n\t\treturn notFound();\n\t}\n\n\t// Update $page before building the components\n\t// TODO: Find somewhere better to put this\n\t$page.url = url;\n\tif (path.endsWith(\"/_error\")) {\n\t\t$page.status = parseInt(query.get(\"status\") ?? \"404\");\n\t\t$page.error = { message: query.get(\"message\") ?? \"\" };\n\t} else {\n\t\t$page.status = 200;\n\t}\n\n\tconst handler = route.handler;\n\tconst params = route.params || {};\n\n\t// TODO: Hit the server hook out here\n\t// We could maybe set data loading up as middleware on a route??????\n\n\tswitch (handler.type) {\n\t\tcase PAGE_ROUTE:\n\t\tcase LAYOUT_ROUTE: {\n\t\t\t// It's a /+page.ts or /_layout.ts endpoint\n\t\t\tif (ev.request.method === \"GET\") {\n\t\t\t\treturn await loadView(ev, url, handler, params, template);\n\t\t\t} else if (ev.request.method === \"POST\") {\n\t\t\t\tconst serverEndPoint: PageServerEndPoint | undefined =\n\t\t\t\t\thandler.serverEndPoint && (await handler.serverEndPoint()).default;\n\t\t\t\treturn await runAction(ev, url, handler, serverEndPoint, params, query);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase PAGE_SERVER_ROUTE:\n\t\tcase LAYOUT_SERVER_ROUTE: {\n\t\t\t// It's a /+page.server.ts or /_layout.server.ts endpoint\n\t\t\tif (ev.request.method === \"GET\") {\n\t\t\t\treturn await loadData(ev, url, handler, \"load\", params);\n\t\t\t} else if (ev.request.method === \"POST\") {\n\t\t\t\tconst serverEndPoint: PageServerEndPoint | undefined =\n\t\t\t\t\thandler.endPoint && (await handler.endPoint()).default;\n\t\t\t\treturn await runAction(ev, url, handler, serverEndPoint, params, query);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tcase SERVER_ROUTE: {\n\t\t\t// It's a /+server.ts endpoint\n\t\t\tconst functionName = ev.request.method.toLowerCase().replace(\"delete\", \"del\");\n\t\t\treturn await loadData(ev, url, handler, functionName, params);\n\t\t}\n\t\tcase ERROR_ROUTE: {\n\t\t\treturn await loadView(ev, url, handler, params, template);\n\t\t}\n\t\tcase HOOK_ROUTE:\n\t\tcase HOOK_SERVER_ROUTE: {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn notFound();\n}\n\nasync function loadData(\n\tev: ServerEvent,\n\turl: URL,\n\thandler: RouteHandler,\n\tfunctionName: string,\n\tparams: Record<string, any>,\n) {\n\tconst serverEndPoint: ServerEndPoint | undefined = (await handler.endPoint()).default;\n\t// `functionName` is computed from the request method, so the handlers are\n\t// accessed through a loose record\n\tconst handlers = serverEndPoint as unknown as Record<string, ServerRequest | undefined>;\n\tconst handlerFn: ServerRequest | undefined = handlers?.[functionName];\n\tif (serverEndPoint && handlerFn) {\n\t\t// Route params come from the URL, so a failed validation means the\n\t\t// resource doesn't exist\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\n\t\ttry {\n\t\t\t// If the endpoint declares a schema for this handler, validate its\n\t\t\t// input up front and reject with 422 if it fails. get/head schemas\n\t\t\t// validate the query string; other schemas validate the json body\n\t\t\tconst schema = endpointSchema(serverEndPoint, functionName);\n\t\t\tconst values = await validateHandlerInput(schema, functionName, url, ev);\n\n\t\t\tconst serverParams = buildServerParams(ev, url, params, values);\n\n\t\t\tconst serverHooks = await loadServerHooks(handler);\n\t\t\tlet entered = 0;\n\t\t\tlet enterResponse: Response | undefined = undefined;\n\t\t\ttry {\n\t\t\t\t// Hooks run from the root down; a hook's enter can return a\n\t\t\t\t// Response to short-circuit the request\n\t\t\t\tfor (; entered < serverHooks.length && !enterResponse; entered++) {\n\t\t\t\t\tconst hookResult = await serverHooks[entered].enter?.(serverParams);\n\t\t\t\t\tif (hookResult) {\n\t\t\t\t\t\tenterResponse = hookResult;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst result = enterResponse || (await handlerFn(serverParams));\n\n\t\t\t\t// If there was no response returned from load (such as errors or a\n\t\t\t\t// redirect), send an ok response\n\t\t\t\treturn result || ok();\n\t\t\t} finally {\n\t\t\t\t// Run exit hooks in reverse order for hooks that were entered\n\t\t\t\twhile (entered > 0) {\n\t\t\t\t\tentered--;\n\t\t\t\t\tawait serverHooks[entered].exit?.(serverParams);\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst response = validationErrorResponse(error);\n\t\t\tif (response) return response;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\treturn notFound();\n}\n\nasync function loadView(\n\tev: ServerEvent,\n\turl: URL,\n\thandler: RouteHandler,\n\tparams: Record<string, any>,\n\ttemplate: string,\n) {\n\t// There must be a client endpoint with a component\n\tconst clientEndPoint: PageEndPoint | undefined = (await handler.endPoint()).default;\n\tif (!clientEndPoint?.component) {\n\t\treturn notFound();\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\n\t// returns 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\ttry {\n\t\t\t\tquery = await validate(loadSchema, searchParamsToRecord(url.searchParams));\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\t\t}\n\t}\n\n\t// Maybe hit the server hooks\n\tconst serverParams = buildServerParams(ev, url, params, query ? { query } : {});\n\tconst serverHooks = 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 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 };\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\tif (handler.layouts) {\n\t\t\tlet slotFunctions: ServerSlotRender[] = [];\n\t\t\tslotFunctions[handler.layouts.length] = (_, $context) => {\n\t\t\t\tlet { body, head } = (clientEndPoint.component as ServerComponent)($props, $context);\n\t\t\t\tstyles += head;\n\t\t\t\treturn body;\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] = (_, $context) => {\n\t\t\t\t\t\t\tlet { body, head } = (layoutEndPoint.component as ServerComponent)($props, $context, {\n\t\t\t\t\t\t\t\t_: slotFunctions[i + 1],\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 } = component($props, undefined, slots);\n\t\t\tstyles += head;\n\t\t\thtml = template.replace(\"%COMPONENT_BODY%\", body).replace(\"%COMPONENT_HEAD%\", styles);\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\treturn new Response(html, {\n\t\t\tstatus: 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) {\n\tconst actionName = (Array.from(query.keys())[0] || \"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// TODO: form.errors etc\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\t// If there was no response returned from the action (such as errors\n\t\t\t// or a redirect), reload the page by redirecting\n\t\t\treturn result || seeOther(url.pathname);\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\n/**\n * Loads the route's server hooks, from the root down\n */\nasync function loadServerHooks(handler: RouteHandler): Promise<ServerHook[]> {\n\tconst hooks: ServerHook[] = [];\n\tif (handler.serverHooks) {\n\t\tfor (let serverHook of handler.serverHooks) {\n\t\t\thooks.push((await serverHook()).default);\n\t\t}\n\t}\n\treturn hooks;\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\tadapter: ev.adapter,\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"test.mjs","names":["path"],"sources":["../src/test/runTest.ts"],"sourcesContent":["import path from \"node:path\";\nimport ServerEvent from \"../server/ServerEvent.ts\";\nimport Router from \"../site/Router.ts\";\nimport Site from \"../site/Site\";\nimport { createServerLoad } from \"../site/serverHandlers.ts\";\n\n/**\n * Runs a site route in test mode\n * @param site The site configuration, with routing configured\n * @param route The route path e.g. `/home`\n * @param ev An optional ServerEvent, which you can use to set test cookies and headers\n * @returns An HTTP response containing the requested data, HTML, or error status\n */\nexport default async function runTest(\n\tsite: Site,\n\troute: string,\n\tev?: ServerEvent,\n): Promise<Response> {\n\tif (!route.startsWith(\"/\")) route += \"/\";\n\tif (!ev) {\n\t\tconst req = new Request(`http://localhost${route}`);\n\t\tev = new ServerEvent(req);\n\t}\n\n\t// Build the router from the Site object created by the user\n\tconst router = new Router();\n\trouter.addPages(\n\t\tsite.routes.map((r) => ({\n\t\t\tpath: r.path,\n\t\t\ttype: r.type,\n\t\t\tendPoint: async () => {\n\t\t\t\tif (r.file) {\n\t\t\t\t\tconst mod = await import(/* @vite-ignore */ path.join(site.root, r.file));\n\t\t\t\t\t// A .torp file's default export is a component, so wrap it as\n\t\t\t\t\t// a PageEndPoint ({ component }) for the entries\n\t\t\t\t\tif (r.file.endsWith(\".torp\")) {\n\t\t\t\t\t\treturn { default: { component: mod.default } };\n\t\t\t\t\t}\n\t\t\t\t\treturn mod;\n\t\t\t\t}\n\t\t\t\t// Inline endpoint (no file) — return directly from memory\n\t\t\t\treturn { default: r.endPoint };\n\t\t\t},\n\t\t\tsubFolder: r.subFolder,\n\t\t})),\n\t);\n\n\t// Run the request through the same handlers the site server uses, so the\n\t// test harness can never drift from production behavior\n\treturn await createServerLoad(router)(ev, \"%COMPONENT_BODY%\");\n}\n"],"mappings":";;;;;;;;;;;;AAaA,eAA8B,QAC7B,MACA,OACA,IACoB;CACpB,IAAI,CAAC,MAAM,WAAW,GAAG,GAAG,SAAS;CACrC,IAAI,CAAC,IAAI;EACR,MAAM,MAAM,IAAI,QAAQ,mBAAmB,OAAO;EAClD,KAAK,IAAI,YAAY,GAAG;CACzB;CAGA,MAAM,SAAS,IAAI,OAAO;CAC1B,OAAO,SACN,KAAK,OAAO,KAAK,OAAO;EACvB,MAAM,EAAE;EACR,MAAM,EAAE;EACR,UAAU,YAAY;GACrB,IAAI,EAAE,MAAM;IACX,MAAM,MAAM,MAAM;;KAA0BA,MAAK,KAAK,KAAK,MAAM,EAAE,IAAI;;IAGvE,IAAI,EAAE,KAAK,SAAS,OAAO,GAC1B,OAAO,EAAE,SAAS,EAAE,WAAW,IAAI,QAAQ,EAAE;IAE9C,OAAO;GACR;GAEA,OAAO,EAAE,SAAS,EAAE,SAAS;EAC9B;EACA,WAAW,EAAE;CACd,EAAE,CACH;CAIA,OAAO,MAAM,iBAAiB,MAAM,CAAC,CAAC,IAAI,kBAAkB;AAC7D"}
|
|
@@ -8,10 +8,12 @@
|
|
|
8
8
|
*/
|
|
9
9
|
function response(status, body) {
|
|
10
10
|
let headers = void 0;
|
|
11
|
-
if (body)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
if (body) {
|
|
12
|
+
if (typeof body === "object") {
|
|
13
|
+
headers = { "Content-Type": "application/json" };
|
|
14
|
+
body = JSON.stringify(body);
|
|
15
|
+
} else headers = { "Content-Type": "text/plain" };
|
|
16
|
+
}
|
|
15
17
|
return new Response(body, {
|
|
16
18
|
status,
|
|
17
19
|
headers
|
|
@@ -128,4 +130,4 @@ function unprocessable(body) {
|
|
|
128
130
|
//#endregion
|
|
129
131
|
export { transfer as a, notFound as i, seeOther as n, response as o, ok as r, unprocessable as t };
|
|
130
132
|
|
|
131
|
-
//# sourceMappingURL=unprocessable-
|
|
133
|
+
//# sourceMappingURL=unprocessable-D6RcYLh6.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unprocessable-
|
|
1
|
+
{"version":3,"file":"unprocessable-D6RcYLh6.mjs","names":[],"sources":["../src/response/response.ts","../src/response/transfer.ts","../src/response/notFound.ts","../src/response/ok.ts","../src/response/seeOther.ts","../src/response/unprocessable.ts"],"sourcesContent":["/**\n * Creates a response with the supplied status code and optional body.\n *\n * If the body is an object, it will be converted to JSON and the Content-Type\n * header set to \"application/json\". Otherwise, if the body is a string, the\n * Content-Type header will be set to \"text/plain\".\n */\nexport default function response(status: number, body?: object | string): Response {\n\tlet headers: Record<string, string> | undefined = undefined;\n\tif (body) {\n\t\tif (typeof body === \"object\") {\n\t\t\theaders = { \"Content-Type\": \"application/json\" };\n\t\t\tbody = JSON.stringify(body);\n\t\t} else {\n\t\t\theaders = { \"Content-Type\": \"text/plain\" };\n\t\t}\n\t}\n\treturn new Response(body, {\n\t\tstatus,\n\t\theaders,\n\t});\n}\n","/**\n * Creates a redirect response with the supplied status code.\n */\nexport default function transfer(\n\tstatus: 300 | 301 | 302 | 303 | 304 | 307 | 308,\n\tlocation: string,\n): Response {\n\treturn new Response(null, {\n\t\tstatus,\n\t\theaders: {\n\t\t\tlocation,\n\t\t},\n\t});\n}\n","import response from \"./response\";\n\n/**\n * 404 Not Found\n *\n * The HTTP 404 Not Found client error response status code indicates that the\n * server cannot find the requested resource. Links that lead to a 404 page are\n * often called broken or dead links and can be subject to link rot.\n *\n * A 404 status code only indicates that the resource is missing without\n * indicating if this is temporary or permanent. If a resource is permanently\n * removed, servers should send the 410 Gone status instead.\n *\n * 404 errors on a website can lead to a poor user experience for your visitors,\n * so the number of broken links (internal and external) should be minimized to\n * prevent frustration for readers. Common causes of 404 responses are mistyped\n * URLs or pages that are moved or deleted without redirection. For more\n * information, see the Redirections in HTTP guide.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/404\n */\nexport default function notFound(body?: object | string): Response {\n\treturn response(404, body ?? \"Not found\");\n}\n","import type { Jsonify } from \"../types/Jsonify\";\nimport type TypedResponse from \"./TypedResponse\";\nimport response from \"./response\";\n\ntype OkResponse<T extends object | string | undefined> = T extends object\n\t? TypedResponse<Jsonify<T>>\n\t: Response;\n\n/**\n * 200 OK\n *\n * The HTTP 200 OK successful response status code indicates that a request has\n * succeeded. A 200 OK response is cacheable by default.\n *\n * A 200 OK response has a different meaning and format depending on the HTTP\n * request method. Here's how they vary for different methods:\n *\n * - GET: A resource was retrieved by the server and included in the response\n * body.\n * - POST: An action succeeded; the response has a message body describing the\n * result.\n * - HEAD: Identical to GET, except there is no message body.\n * - TRACE: The response has a message body containing the request as received\n * by the server.\n *\n * Although possible, successful PUT or DELETE requests often do not result in\n * a 200 OK response. It is more common to see 201 Created if the resource is\n * uploaded or created for the first time, or 204 No Content upon successful\n * deletion of a resource.\n *\n * An object body is typed: the client sees its JSON form through\n * `makeApi`-created callers.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/200\n */\nexport default function ok<T extends object | string | undefined>(body?: T): OkResponse<T> {\n\treturn response(200, body) as OkResponse<T>;\n}\n","import transfer from \"./transfer\";\n\n/**\n * 303 See Other\n *\n * The HTTP 303 See Other redirection response status code indicates that the\n * browser should redirect to the URL in the Location header instead of\n * rendering the requested resource.\n *\n * This response code is often sent back as a result of PUT or POST methods so\n * the client may retrieve a confirmation, or view a representation of a\n * real-world object (see HTTP range-14). The method to retrieve the redirected\n * resource is always GET.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/303\n */\nexport default function seeOther(location: string): Response {\n\treturn transfer(303, location);\n}\n","import response from \"./response\";\nimport type { Jsonify } from \"../types/Jsonify\";\nimport type TypedResponse from \"./TypedResponse\";\n\ntype UnprocessableResponse<T extends object | string | undefined> = T extends object\n\t? TypedResponse<Jsonify<T>>\n\t: Response;\n\n/**\n * 422 Unprocessable Content\n *\n * The HTTP 422 Unprocessable Content client error response status code\n * indicates that the server understood the content type of the request content,\n * and the syntax of the request content was correct, but it was unable to\n * process the contained instructions.\n *\n * Clients that receive a 422 response should expect that repeating the request\n * without modification will fail with the same error.\n *\n * An object body is typed: it becomes the page's `$props.form` (with its JSON\n * form) after a form submit, so validation errors can be surfaced with their\n * field types via `PageForm`.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/422\n */\nexport default function unprocessable<T extends object | string | undefined>(\n\tbody?: T,\n): UnprocessableResponse<T> {\n\treturn response(422, body ?? \"Unprocessable\") as UnprocessableResponse<T>;\n}\n"],"mappings":";;;;;;;;AAOA,SAAwB,SAAS,QAAgB,MAAkC;CAClF,IAAI,UAA8C,KAAA;CAClD,IAAI,MAAM;EACT,IAAI,OAAO,SAAS,UAAU;GAC7B,UAAU,EAAE,gBAAgB,mBAAmB;GAC/C,OAAO,KAAK,UAAU,IAAI;EAC3B,OACC,UAAU,EAAE,gBAAgB,aAAa;CAE3C;CACA,OAAO,IAAI,SAAS,MAAM;EACzB;EACA;CACD,CAAC;AACF;;;;;;AClBA,SAAwB,SACvB,QACA,UACW;CACX,OAAO,IAAI,SAAS,MAAM;EACzB;EACA,SAAS,EACR,SACD;CACD,CAAC;AACF;;;;;;;;;;;;;;;;;;;;;;ACQA,SAAwB,SAAS,MAAkC;CAClE,OAAO,SAAS,KAAK,QAAQ,WAAW;AACzC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACYA,SAAwB,GAA0C,MAAyB;CAC1F,OAAO,SAAS,KAAK,IAAI;AAC1B;;;;;;;;;;;;;;;;;ACrBA,SAAwB,SAAS,UAA4B;CAC5D,OAAO,SAAS,KAAK,QAAQ;AAC9B;;;;;;;;;;;;;;;;;;;;ACOA,SAAwB,cACvB,MAC2B;CAC3B,OAAO,SAAS,KAAK,QAAQ,eAAe;AAC7C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@torpor/build",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A framework for building sites and apps with Torpor",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -69,10 +69,10 @@
|
|
|
69
69
|
"dependencies": {
|
|
70
70
|
"cookie": "^2.0.1",
|
|
71
71
|
"dotenv": "^17.4.2",
|
|
72
|
-
"vite": "npm:@voidzero-dev/vite-plus-core@0.
|
|
73
|
-
"vite-plus": "0.
|
|
74
|
-
"@torpor/unplugin": "^1.0.
|
|
75
|
-
"@torpor/view": "^1.0
|
|
72
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@0.3.0",
|
|
73
|
+
"vite-plus": "0.3.0",
|
|
74
|
+
"@torpor/unplugin": "^1.0.4",
|
|
75
|
+
"@torpor/view": "^1.1.0"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Site-CE0_o5Ci.d.mts","names":[],"sources":["../src/types/ServerLoadEvent.ts","../src/types/ServerHook.ts","../src/types/Adapter.ts","../src/types/SitePlugin.ts","../src/types/PageLoadEvent.ts","../src/types/PageLoadReturn.ts","../src/types/PageEndPoint.ts","../src/types/PageServerAction.ts","../src/types/PageServerLoad.ts","../src/types/PageServerEndPoint.ts","../src/types/ServerRequest.ts","../src/types/ServerEndPoint.ts","../src/types/RouteType.ts","../src/types/Route.ts","../src/site/Site.ts"],"mappings":"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"}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { t as unprocessable } from "./unprocessable-DAZbrDeR.mjs";
|
|
2
|
-
import { n as ValidationError, t as validate } from "./validate-Ok4krlkX.mjs";
|
|
3
|
-
import { $watch } from "@torpor/view/ssr";
|
|
4
|
-
//#region src/form/formDataToRecord.ts
|
|
5
|
-
/**
|
|
6
|
-
* Converts the submitted fields of a form request into a plain record: one
|
|
7
|
-
* value per field, or an array when a field was submitted with multiple
|
|
8
|
-
* values (e.g. a multi select). File inputs pass through as `File` values;
|
|
9
|
-
* coercing them is left to the schema or the action.
|
|
10
|
-
*
|
|
11
|
-
* @param request The request (or FormData directly)
|
|
12
|
-
* @returns The field values
|
|
13
|
-
*/
|
|
14
|
-
async function formDataToRecord(request) {
|
|
15
|
-
const formData = request instanceof FormData ? request : await request.formData();
|
|
16
|
-
const result = {};
|
|
17
|
-
for (const key of formData.keys()) {
|
|
18
|
-
if (key in result) continue;
|
|
19
|
-
const values = formData.getAll(key);
|
|
20
|
-
result[key] = values.length > 1 ? values : values[0];
|
|
21
|
-
}
|
|
22
|
-
return result;
|
|
23
|
-
}
|
|
24
|
-
//#endregion
|
|
25
|
-
//#region src/state/$serverPage.ts
|
|
26
|
-
const PAGE_SYMBOL = Symbol.for("torp.Page");
|
|
27
|
-
const $page = globalThis[PAGE_SYMBOL] ??= $watch({
|
|
28
|
-
status: 404,
|
|
29
|
-
url: new URL("http://localhost"),
|
|
30
|
-
form: void 0,
|
|
31
|
-
error: { message: "" }
|
|
32
|
-
});
|
|
33
|
-
//#endregion
|
|
34
|
-
//#region src/utils/searchParamsToRecord.ts
|
|
35
|
-
/**
|
|
36
|
-
* Converts a URL's query string into a plain record: one string per param,
|
|
37
|
-
* or an array when a param was repeated.
|
|
38
|
-
*
|
|
39
|
-
* @param searchParams The URL's search params
|
|
40
|
-
* @returns The param values
|
|
41
|
-
*/
|
|
42
|
-
function searchParamsToRecord(searchParams) {
|
|
43
|
-
const result = {};
|
|
44
|
-
for (const key of searchParams.keys()) {
|
|
45
|
-
if (key in result) continue;
|
|
46
|
-
const values = searchParams.getAll(key);
|
|
47
|
-
result[key] = values.length > 1 ? values : values[0];
|
|
48
|
-
}
|
|
49
|
-
return result;
|
|
50
|
-
}
|
|
51
|
-
//#endregion
|
|
52
|
-
//#region src/validation/endpoint.ts
|
|
53
|
-
/**
|
|
54
|
-
* Gets the standard schema declared for a handler or action, if any. The
|
|
55
|
-
* schemas map is keyed by name; the runtime treats it as a loose record.
|
|
56
|
-
*/
|
|
57
|
-
function endpointSchema(endPoint, name) {
|
|
58
|
-
return endPoint.schema?.[name];
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Validates the route params against the endpoint's `params` schema, if it
|
|
62
|
-
* declares one, returning the coerced params. Throws a ValidationError when
|
|
63
|
-
* they don't match, which callers turn into a 404 (params come from the URL,
|
|
64
|
-
* so a failed validation means the resource doesn't exist).
|
|
65
|
-
*
|
|
66
|
-
* @param endPoint The endpoint declaring the (optional) `params` schema
|
|
67
|
-
* @param params The route params from the matched route
|
|
68
|
-
* @returns The validated params
|
|
69
|
-
*/
|
|
70
|
-
async function validateEndpointParams(endPoint, params) {
|
|
71
|
-
const schema = endpointSchema(endPoint, "params");
|
|
72
|
-
return schema ? await validate(schema, params) : params;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Validates a handler's input against its schema: get/head handlers and load
|
|
76
|
-
* functions validate the URL's query string, other handlers validate the JSON
|
|
77
|
-
* request body. Returns the validated values (an empty object when no schema
|
|
78
|
-
* is declared), which callers pass through to the handler's event.
|
|
79
|
-
*
|
|
80
|
-
* @param schema The handler's (optional) schema
|
|
81
|
-
* @param functionName The handler name (`get`, `post`, `load`, etc)
|
|
82
|
-
* @param url The request URL, for the query string
|
|
83
|
-
* @param ev The server event, for the request body
|
|
84
|
-
* @returns The validated values
|
|
85
|
-
*/
|
|
86
|
-
async function validateHandlerInput(schema, functionName, url, ev) {
|
|
87
|
-
if (!schema) return {};
|
|
88
|
-
if (functionName === "get" || functionName === "head" || functionName === "load") return { query: await validate(schema, searchParamsToRecord(url.searchParams)) };
|
|
89
|
-
return { json: await validate(schema, await ev.json()) };
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Turns a ValidationError thrown during endpoint validation into a 422
|
|
93
|
-
* response with the schema's issues. Returns undefined for any other error,
|
|
94
|
-
* which callers should rethrow.
|
|
95
|
-
*
|
|
96
|
-
* @param error The error thrown by a handler or validation
|
|
97
|
-
* @returns A 422 response, or undefined when the error isn't a validation failure
|
|
98
|
-
*/
|
|
99
|
-
function validationErrorResponse(error) {
|
|
100
|
-
if (error instanceof ValidationError) return unprocessable({
|
|
101
|
-
message: error.message,
|
|
102
|
-
issues: error.issues
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
//#endregion
|
|
106
|
-
export { searchParamsToRecord as a, validationErrorResponse as i, validateEndpointParams as n, $page as o, validateHandlerInput as r, formDataToRecord as s, endpointSchema as t };
|
|
107
|
-
|
|
108
|
-
//# sourceMappingURL=endpoint-EULRGCKA.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"endpoint-EULRGCKA.mjs","names":[],"sources":["../src/form/formDataToRecord.ts","../src/state/$serverPage.ts","../src/utils/searchParamsToRecord.ts","../src/validation/endpoint.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\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"],"mappings":";;;;;;;;;;;;;AAWA,eAA8B,iBAC7B,SAC0B;CAC1B,MAAM,WAAW,mBAAmB,WAAW,UAAU,MAAM,QAAQ,SAAS;CAChF,MAAM,SAAyB,CAAC;CAChC,KAAK,MAAM,OAAO,SAAS,KAAK,GAAG;EAClC,IAAI,OAAO,QAAQ;EACnB,MAAM,SAAS,SAAS,OAAO,GAAG;EAClC,OAAO,OAAO,OAAO,SAAS,IAAI,SAAS,OAAO;CACnD;CACA,OAAO;AACR;;;ACnBA,MAAM,cAA6B,OAAO,IAAI,WAAW;AAOzD,MAAM,QAEJ,WAAW,iBAAiB,OAAO;CACnC,QAAQ;CACR,KAAK,IAAI,IAAI,kBAAkB;CAC/B,MAAM,KAAA;CACN,OAAO,EACN,SAAS,GACV;AACD,CAAC;;;;;;;;;;ACVF,SAAwB,qBAAqB,cAA4C;CACxF,MAAM,SAAsB,CAAC;CAC7B,KAAK,MAAM,OAAO,aAAa,KAAK,GAAG;EACtC,IAAI,OAAO,QAAQ;EACnB,MAAM,SAAS,aAAa,OAAO,GAAG;EACtC,OAAO,OAAO,OAAO,SAAS,IAAI,SAAS,OAAO;CACnD;CACA,OAAO;AACR;;;;;;;ACKA,SAAgB,eAAe,UAAoB,MAA4C;CAC9F,OAAQ,SAAS,SAAiC;AACnD;;;;;;;;;;;AAYA,eAAsB,uBACrB,UACA,QAC+B;CAC/B,MAAM,SAAS,eAAe,UAAU,QAAQ;CAChD,OAAO,SAAW,MAAM,SAAS,QAAQ,MAAM,IAA6B;AAC7E;;;;;;;;;;;;;AAcA,eAAsB,qBACrB,QACA,cACA,KACA,IAC+D;CAC/D,IAAI,CAAC,QAAQ,OAAO,CAAC;CACrB,IAAI,iBAAiB,SAAS,iBAAiB,UAAU,iBAAiB,QACzE,OAAO,EAAE,OAAO,MAAM,SAAS,QAAQ,qBAAqB,IAAI,YAAY,CAAC,EAAE;CAEhF,OAAO,EAAE,MAAM,MAAM,SAAS,QAAQ,MAAM,GAAG,KAAK,CAAC,EAAE;AACxD;;;;;;;;;AAUA,SAAgB,wBAAwB,OAAsC;CAC7E,IAAI,iBAAiB,iBACpB,OAAO,cAAc;EAAE,SAAS,MAAM;EAAS,QAAQ,MAAM;CAAO,CAAC;AAGvE"}
|