@torpor/build 1.4.5 → 1.5.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/README.md +3 -2
- package/dist/{Site-CQ29Opvm.d.mts → Site-Blz32JRD.d.mts} +4 -3
- package/dist/{Site-CQ29Opvm.d.mts.map → Site-Blz32JRD.d.mts.map} +1 -1
- package/dist/bin/index.js +1 -1
- package/dist/clientEntry.mjs +4 -4
- package/dist/clientEntry.mjs.map +1 -1
- package/dist/dataRequest-JosDB_ig.mjs +50 -0
- package/dist/dataRequest-JosDB_ig.mjs.map +1 -0
- package/dist/dev.mjs +1 -1
- package/dist/devPlugin-V689J6l6.mjs +144 -0
- package/dist/devPlugin-V689J6l6.mjs.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +3 -2
- package/dist/index.mjs.map +1 -1
- package/dist/load-LWQoFWh-.mjs +349 -0
- package/dist/load-LWQoFWh-.mjs.map +1 -0
- package/dist/nav.mjs +1 -1
- package/dist/nodeDev.d.mts +16 -0
- package/dist/nodeDev.d.mts.map +1 -0
- package/dist/nodeDev.mjs +2 -0
- package/dist/openapi.d.mts +1 -1
- package/dist/{response-CuNPcxsY.mjs → response-sth6FQsj.mjs} +33 -3
- package/dist/response-sth6FQsj.mjs.map +1 -0
- package/dist/response.mjs +2 -2
- package/dist/run.d.mts +1 -1
- package/dist/run.mjs +1 -1
- package/dist/{runOpenApi-CbbrPi4E.mjs → runOpenApi-tnflDjZV.mjs} +10 -143
- package/dist/runOpenApi-tnflDjZV.mjs.map +1 -0
- package/dist/serverEntry-fj0XfTs4.d.mts.map +1 -1
- package/dist/{serverEntry-D3uwudkX.mjs → serverEntry-o6kk_-Wo.mjs} +2 -2
- package/dist/{serverEntry-D3uwudkX.mjs.map → serverEntry-o6kk_-Wo.mjs.map} +1 -1
- package/dist/serverEntry.mjs +1 -1
- package/dist/{serverHandlers-C8qzOSX-.mjs → serverHandlers-F1gJ1lrj.mjs} +194 -30
- package/dist/serverHandlers-F1gJ1lrj.mjs.map +1 -0
- package/dist/test.d.mts +1 -1
- package/dist/test.mjs +1 -1
- package/dist/{unprocessable-D6RcYLh6.mjs → unprocessable-CoMN2zFa.mjs} +2 -32
- package/dist/unprocessable-CoMN2zFa.mjs.map +1 -0
- package/package.json +8 -3
- package/dist/load-Uyj9I60p.mjs +0 -246
- package/dist/load-Uyj9I60p.mjs.map +0 -1
- package/dist/response-CuNPcxsY.mjs.map +0 -1
- package/dist/runOpenApi-CbbrPi4E.mjs.map +0 -1
- package/dist/serverHandlers-C8qzOSX-.mjs.map +0 -1
- package/dist/unprocessable-D6RcYLh6.mjs.map +0 -1
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import { n as getBasePath, s as stripBaseFromUrl } from "./basePath-DQnbHc7o.mjs";
|
|
2
|
+
import { t as $page } from "./_page-CW6SLuT4.mjs";
|
|
3
|
+
import { n as DATA_REUSE_HEADER, r as findErrorRoute, t as DATA_REQUEST_HEADER } from "./dataRequest-JosDB_ig.mjs";
|
|
4
|
+
import { clearLayoutSlot, fillLayoutSlot, hydrate, mount, unmount } from "@torpor/view";
|
|
5
|
+
//#region src/state/client.ts
|
|
6
|
+
const CLIENT_SYMBOL = Symbol.for("torp.Client");
|
|
7
|
+
const client = globalThis[CLIENT_SYMBOL] ??= {
|
|
8
|
+
router: null,
|
|
9
|
+
layoutStack: [],
|
|
10
|
+
prefetchedData: {},
|
|
11
|
+
viewTransitions: false
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region src/nav/reload.ts
|
|
15
|
+
/**
|
|
16
|
+
* Reloads data for the currently loaded page and rerenders it.
|
|
17
|
+
*/
|
|
18
|
+
async function reload() {
|
|
19
|
+
return await navigate(new URL(document.location.href));
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/nav/formSubmit.ts
|
|
23
|
+
async function formSubmit(e) {
|
|
24
|
+
e.preventDefault();
|
|
25
|
+
$page.form = void 0;
|
|
26
|
+
const form = e.target;
|
|
27
|
+
const button = e.submitter;
|
|
28
|
+
let action = form.action || document.URL;
|
|
29
|
+
if (button && button.formAction && button.formAction !== document.URL) action = button.formAction;
|
|
30
|
+
const options = {
|
|
31
|
+
body: new FormData(form),
|
|
32
|
+
method: "POST",
|
|
33
|
+
mode: "cors",
|
|
34
|
+
credentials: "same-origin",
|
|
35
|
+
headers: { "X-Torpor-Form-Submit": "" }
|
|
36
|
+
};
|
|
37
|
+
const response = await fetch(action, options);
|
|
38
|
+
if (response.status === 200 && response.headers.has("Content-Disposition") && /attachment;\s*filename="(.+?)"/.test(response.headers.get("Content-Disposition"))) {
|
|
39
|
+
const downloadFileName = response.headers.get("Content-Disposition")?.match(/attachment;\s*filename="(.+?)"/)[1] ?? "file";
|
|
40
|
+
const downloadLink = document.createElement("a");
|
|
41
|
+
downloadLink.href = window.URL.createObjectURL(await response.blob());
|
|
42
|
+
downloadLink.download = downloadFileName;
|
|
43
|
+
downloadLink.click();
|
|
44
|
+
} else if (response.status === 200 && response.headers.has("X-Torpor-Form-Redirect")) {
|
|
45
|
+
const redirect = response.headers.get("Location");
|
|
46
|
+
await load(redirect);
|
|
47
|
+
window.location.href = redirect;
|
|
48
|
+
} else if (response.status >= 200 && response.status <= 299 || response.status >= 400 && response.status <= 499) {
|
|
49
|
+
if (response.headers.get("Content-Type") === "application/json") $page.form = await response.json();
|
|
50
|
+
await reload();
|
|
51
|
+
} else if (response.status >= 500) {
|
|
52
|
+
if (response.headers.get("Content-Type")?.includes("text/html")) {
|
|
53
|
+
const html = await response.text();
|
|
54
|
+
document.open();
|
|
55
|
+
document.write(html);
|
|
56
|
+
document.close();
|
|
57
|
+
} else window.location.reload();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/nav/loadData.ts
|
|
62
|
+
/**
|
|
63
|
+
* Loads a route's data for a client-side navigation.
|
|
64
|
+
*
|
|
65
|
+
* One request (`GET <page url>/~server` with the data header) returns the
|
|
66
|
+
* server data for the page and all of its layouts, with hooks running once
|
|
67
|
+
* against the page url. The client then runs its own load functions (layout
|
|
68
|
+
* by layout, then the page), merging each route's fresh server data in the
|
|
69
|
+
* same order the server render does.
|
|
70
|
+
*/
|
|
71
|
+
async function loadData(handler, params, path, query, newLayoutStack, clientEndPoint, prefetch = false) {
|
|
72
|
+
let data = {};
|
|
73
|
+
const layoutStack = client.layoutStack;
|
|
74
|
+
const layouts = (handler.layouts ?? []).map((layout, index) => {
|
|
75
|
+
let layoutPath = layout.path;
|
|
76
|
+
for (let key in params) layoutPath = layoutPath.replace(`[${key}]`, params[key]);
|
|
77
|
+
const previous = layoutStack.at(index);
|
|
78
|
+
const reuse = !prefetch && previous?.path === layoutPath;
|
|
79
|
+
return {
|
|
80
|
+
layout,
|
|
81
|
+
index,
|
|
82
|
+
layoutPath,
|
|
83
|
+
previous,
|
|
84
|
+
reuse
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
const server = await loadServerData(handler, path, query, layouts.filter((l) => l.reuse).map((l) => l.layoutPath));
|
|
88
|
+
if (server === void 0) return;
|
|
89
|
+
if ("error" in server) return {
|
|
90
|
+
data,
|
|
91
|
+
error: server.error
|
|
92
|
+
};
|
|
93
|
+
for (const { layout, index, layoutPath, previous, reuse } of layouts) {
|
|
94
|
+
const stackLayout = {
|
|
95
|
+
path: layoutPath,
|
|
96
|
+
data: {},
|
|
97
|
+
reuse,
|
|
98
|
+
slotRegion: null
|
|
99
|
+
};
|
|
100
|
+
if (reuse && previous) {
|
|
101
|
+
stackLayout.slotRegion = previous.slotRegion;
|
|
102
|
+
Object.assign(stackLayout.data, previous.data);
|
|
103
|
+
} else {
|
|
104
|
+
const layoutEndPoint = (await layout.endPoint())?.default;
|
|
105
|
+
const response = await runClientLoad(layoutEndPoint, clientLocation(layoutPath), query, params, stackLayout.data);
|
|
106
|
+
if (response) {
|
|
107
|
+
if (isRedirect(response)) return;
|
|
108
|
+
return {
|
|
109
|
+
data,
|
|
110
|
+
error: await errorOf(response)
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const serverData = server.loads?.[index];
|
|
114
|
+
if (serverData) Object.assign(stackLayout.data, serverData);
|
|
115
|
+
}
|
|
116
|
+
Object.assign(data, stackLayout.data);
|
|
117
|
+
newLayoutStack.push(stackLayout);
|
|
118
|
+
}
|
|
119
|
+
const response = await runClientLoad(clientEndPoint, clientLocation(path), query, params, data);
|
|
120
|
+
if (response) {
|
|
121
|
+
if (isRedirect(response)) return;
|
|
122
|
+
return {
|
|
123
|
+
data,
|
|
124
|
+
error: await errorOf(response)
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const pageServerData = server.loads?.[handler.layouts?.length ?? 0];
|
|
128
|
+
if (pageServerData) Object.assign(data, pageServerData);
|
|
129
|
+
return { data };
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Fetches the page's combined server data. Returns `undefined` when a load
|
|
133
|
+
* redirected, or an `error` result when a load failed.
|
|
134
|
+
*/
|
|
135
|
+
async function loadServerData(handler, path, query, reusedLayouts) {
|
|
136
|
+
if (!hasServerData(handler)) return {};
|
|
137
|
+
const url = new URL(document.location.origin + getBasePath() + path.replace(/\/$/, "") + "/~server");
|
|
138
|
+
for (let [name, value] of query) url.searchParams.append(name, value);
|
|
139
|
+
const headers = { [DATA_REQUEST_HEADER]: "1" };
|
|
140
|
+
if (reusedLayouts.length > 0) headers[DATA_REUSE_HEADER] = JSON.stringify(reusedLayouts);
|
|
141
|
+
const response = await fetch(url, {
|
|
142
|
+
redirect: "manual",
|
|
143
|
+
headers
|
|
144
|
+
});
|
|
145
|
+
if (isRedirect(response)) return;
|
|
146
|
+
if (!response.ok) return { error: await errorOf(response) };
|
|
147
|
+
if (!response.headers.get("Content-Type")?.includes("application/json")) return {};
|
|
148
|
+
return await response.json();
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Whether the route has any server-side code to run (a page or layout server
|
|
152
|
+
* load, or a folder hook). Without any, there's no data request to make.
|
|
153
|
+
*/
|
|
154
|
+
function hasServerData(handler) {
|
|
155
|
+
if (handler.serverHooks && handler.serverHooks.length > 0) return true;
|
|
156
|
+
if (handler.serverEndPoint) return true;
|
|
157
|
+
return (handler.layouts ?? []).some((layout) => !!layout.serverEndPoint);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Runs a route's client-side load, merging its json data into `data`. Returns
|
|
161
|
+
* a non-ok Response for the caller to turn into an error page.
|
|
162
|
+
*/
|
|
163
|
+
async function runClientLoad(endPoint, location, query, params, data) {
|
|
164
|
+
if (!endPoint?.load) return;
|
|
165
|
+
const clientKey = location + (query.size > 0 ? `?${query}` : "");
|
|
166
|
+
const prefetchedData = client.prefetchedData;
|
|
167
|
+
if (prefetchedData[clientKey]) {
|
|
168
|
+
Object.assign(data, prefetchedData[clientKey]);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const clientUrl = new URL(document.location.href);
|
|
172
|
+
for (let [name, value] of query) clientUrl.searchParams.append(name, value);
|
|
173
|
+
const clientResponse = await endPoint.load({
|
|
174
|
+
url: clientUrl,
|
|
175
|
+
params,
|
|
176
|
+
data
|
|
177
|
+
});
|
|
178
|
+
if (clientResponse) {
|
|
179
|
+
if (clientResponse.ok) {
|
|
180
|
+
if (clientResponse.headers.get("Content-Type")?.includes("application/json")) {
|
|
181
|
+
const clientData = await clientResponse.json();
|
|
182
|
+
Object.assign(data, clientData);
|
|
183
|
+
prefetchedData[clientKey] = clientData;
|
|
184
|
+
}
|
|
185
|
+
} else return clientResponse;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function clientLocation(path) {
|
|
189
|
+
return document.location.origin + getBasePath() + path;
|
|
190
|
+
}
|
|
191
|
+
function isRedirect(response) {
|
|
192
|
+
return response.status >= 300 && response.status < 400 || response.type === "opaqueredirect";
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* The status and message of a failed load response. The body only becomes
|
|
196
|
+
* the message when it's a `message`-carrying json body or plain text -- an
|
|
197
|
+
* html body is a whole page (e.g. a static host's 404), not a message.
|
|
198
|
+
*/
|
|
199
|
+
async function errorOf(response) {
|
|
200
|
+
let message = "";
|
|
201
|
+
const type = response.headers.get("Content-Type");
|
|
202
|
+
if (type?.includes("application/json")) try {
|
|
203
|
+
const data = await response.json();
|
|
204
|
+
if (typeof data.message === "string") message = data.message;
|
|
205
|
+
} catch {}
|
|
206
|
+
else if (type?.includes("text/plain")) message = await response.text();
|
|
207
|
+
return {
|
|
208
|
+
status: response.status,
|
|
209
|
+
message: message || response.statusText
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
//#endregion
|
|
213
|
+
//#region src/nav/navigate.ts
|
|
214
|
+
async function navigate(rawUrl, withHydration = false) {
|
|
215
|
+
let parent = document.getElementById("app");
|
|
216
|
+
if (!parent) {
|
|
217
|
+
console.log("500");
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
const url = stripBaseFromUrl(rawUrl, getBasePath()) ?? rawUrl;
|
|
221
|
+
const path = url.pathname;
|
|
222
|
+
const query = url.searchParams;
|
|
223
|
+
let route = client.router.match(path, query);
|
|
224
|
+
$page.url = url;
|
|
225
|
+
if (route) {
|
|
226
|
+
if (path.endsWith("/_error")) {
|
|
227
|
+
$page.status = parseInt(query.get("status") ?? "404");
|
|
228
|
+
$page.error = { message: query.get("message") ?? "" };
|
|
229
|
+
window.history.replaceState({}, "", rawUrl.toString().split("?")[0]);
|
|
230
|
+
} else {
|
|
231
|
+
$page.status = 200;
|
|
232
|
+
$page.error = { message: "" };
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
const errorPath = findErrorRoute(client.router, path);
|
|
236
|
+
const errorRoute = errorPath && client.router.match(errorPath, query);
|
|
237
|
+
if (!errorRoute) return false;
|
|
238
|
+
route = errorRoute;
|
|
239
|
+
$page.status = 404;
|
|
240
|
+
$page.error = { message: "Not found" };
|
|
241
|
+
}
|
|
242
|
+
let handler = route.handler;
|
|
243
|
+
let params = route.params || {};
|
|
244
|
+
let clientEndPoint = handler.endPoint ? (await handler.endPoint())?.default : void 0;
|
|
245
|
+
if (!clientEndPoint?.component) return false;
|
|
246
|
+
let newLayoutStack = [];
|
|
247
|
+
const result = await loadData(handler, params, path, query, newLayoutStack, clientEndPoint);
|
|
248
|
+
if (result === void 0) return false;
|
|
249
|
+
let data = result.data;
|
|
250
|
+
if (result.error) {
|
|
251
|
+
if (withHydration) return false;
|
|
252
|
+
const errorPath = findErrorRoute(client.router, path);
|
|
253
|
+
const errorRoute = errorPath && client.router.match(errorPath, query);
|
|
254
|
+
if (!errorRoute) return false;
|
|
255
|
+
route = errorRoute;
|
|
256
|
+
handler = errorRoute.handler;
|
|
257
|
+
params = errorRoute.params || {};
|
|
258
|
+
clientEndPoint = handler.endPoint ? (await handler.endPoint())?.default : void 0;
|
|
259
|
+
if (!clientEndPoint?.component) return false;
|
|
260
|
+
$page.status = result.error.status;
|
|
261
|
+
$page.error = { message: result.error.message };
|
|
262
|
+
newLayoutStack.length = 0;
|
|
263
|
+
const errorResult = await loadData(handler, params, path, query, newLayoutStack, clientEndPoint);
|
|
264
|
+
if (errorResult === void 0 || errorResult.error) return false;
|
|
265
|
+
data = errorResult.data;
|
|
266
|
+
}
|
|
267
|
+
let formInput = document.getElementById("t-form-data");
|
|
268
|
+
let form;
|
|
269
|
+
if (formInput) {
|
|
270
|
+
form = JSON.parse(formInput.value);
|
|
271
|
+
$page.form = form;
|
|
272
|
+
formInput.remove();
|
|
273
|
+
}
|
|
274
|
+
let $props = { data };
|
|
275
|
+
$props.form = $page.form;
|
|
276
|
+
const $context = { TorporBuildContext: { onformsubmit: formSubmit } };
|
|
277
|
+
client.layoutStack.push({
|
|
278
|
+
path: route.handler.path,
|
|
279
|
+
data: {},
|
|
280
|
+
reuse: false,
|
|
281
|
+
slotRegion: null
|
|
282
|
+
});
|
|
283
|
+
client.layoutStack = newLayoutStack;
|
|
284
|
+
let layoutStack = client.layoutStack;
|
|
285
|
+
let component = clientEndPoint.component;
|
|
286
|
+
let slots = void 0;
|
|
287
|
+
let reused = false;
|
|
288
|
+
let reusedIndex = -1;
|
|
289
|
+
if (handler.layouts) {
|
|
290
|
+
let slotFunctions = [];
|
|
291
|
+
slotFunctions[handler.layouts.length] = function clientComponent(parent, anchor) {
|
|
292
|
+
let i = layoutStack.length - 1;
|
|
293
|
+
layoutStack[i].slotRegion = fillLayoutSlot(clientEndPoint.component, slotFunctions[i + 1], parent, anchor, $props, $context);
|
|
294
|
+
};
|
|
295
|
+
for (let i = handler.layouts.length - 1; i >= 0; i--) {
|
|
296
|
+
const layoutEndPoint = (await handler.layouts[i].endPoint())?.default;
|
|
297
|
+
if (layoutEndPoint?.component) {
|
|
298
|
+
if (layoutStack[i].reuse) {
|
|
299
|
+
component = slotFunctions[i + 1];
|
|
300
|
+
reusedIndex = i;
|
|
301
|
+
reused = true;
|
|
302
|
+
break;
|
|
303
|
+
} else if (i === 0) {
|
|
304
|
+
component = layoutEndPoint.component;
|
|
305
|
+
slots = { _: slotFunctions[i + 1] };
|
|
306
|
+
} else slotFunctions[i] = function layoutComponent(parent, anchor, _, $context) {
|
|
307
|
+
layoutStack[i - 1].slotRegion = fillLayoutSlot(layoutEndPoint.component, slotFunctions[i + 1], parent, anchor, $props, $context);
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
let app = parent;
|
|
313
|
+
const render = () => {
|
|
314
|
+
try {
|
|
315
|
+
if (reused) {
|
|
316
|
+
const slotRegion = layoutStack[reusedIndex].slotRegion;
|
|
317
|
+
app = slotRegion.startNode.parentNode;
|
|
318
|
+
clearLayoutSlot(slotRegion);
|
|
319
|
+
component(app, null);
|
|
320
|
+
} else if (withHydration) hydrate(app, component, $props, slots);
|
|
321
|
+
else {
|
|
322
|
+
unmount(app);
|
|
323
|
+
mount(app, component, $props, slots);
|
|
324
|
+
}
|
|
325
|
+
} catch (error) {
|
|
326
|
+
app.innerHTML = "<span style=\"color: red\">Script syntax error</span><p>" + error + "</p>";
|
|
327
|
+
console.log(error);
|
|
328
|
+
}
|
|
329
|
+
if (!withHydration) {
|
|
330
|
+
if (stripBaseFromUrl(new URL(document.location.href), getBasePath())?.pathname !== path) window.scrollTo(0, 0);
|
|
331
|
+
}
|
|
332
|
+
};
|
|
333
|
+
if (!withHydration && client.viewTransitions && typeof document.startViewTransition === "function") document.startViewTransition(render);
|
|
334
|
+
else render();
|
|
335
|
+
client.prefetchedData = {};
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
//#endregion
|
|
339
|
+
//#region src/nav/load.ts
|
|
340
|
+
/**
|
|
341
|
+
* Loads and renders the page at the supplied path.
|
|
342
|
+
*/
|
|
343
|
+
async function load(path) {
|
|
344
|
+
return await navigate(new URL(path, document.location.href));
|
|
345
|
+
}
|
|
346
|
+
//#endregion
|
|
347
|
+
export { client as a, reload as i, navigate as n, loadData as r, load as t };
|
|
348
|
+
|
|
349
|
+
//# sourceMappingURL=load-LWQoFWh-.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load-LWQoFWh-.mjs","names":[],"sources":["../src/state/client.ts","../src/nav/reload.ts","../src/nav/formSubmit.ts","../src/nav/loadData.ts","../src/nav/navigate.ts","../src/nav/load.ts"],"sourcesContent":["import type ClientState from \"../types/ClientState\";\n\nconst CLIENT_SYMBOL: unique symbol = Symbol.for(\"torp.Client\");\n\nconst client: ClientState =\n\t// @ts-ignore\n\t(globalThis[CLIENT_SYMBOL] ??= {\n\t\t// @ts-ignore This will definitely, 100% get set\n\t\trouter: null,\n\t\tlayoutStack: [],\n\t\t// TODO: Probably expire after 30 seconds or something?\n\t\tprefetchedData: {},\n\t\tviewTransitions: false,\n\t});\n\nexport default client;\n","import navigate from \"./navigate\";\n\n/**\n * Reloads data for the currently loaded page and rerenders it.\n */\nexport default async function reload(): Promise<boolean> {\n\tconst url = new URL(document.location.href);\n\treturn await navigate(url);\n}\n","import $page from \"../state/$page\";\nimport load from \"./load\";\nimport reload from \"./reload\";\n\nexport default async function formSubmit(e: SubmitEvent): Promise<void> {\n\t// We'll take it from here\n\te.preventDefault();\n\n\t// Reset $page on submit and link navigation\n\t// TODO: Should we put data in $page.data??\n\t$page.form = undefined;\n\n\t// Perform a POST fetch to the form's action location\n\tconst form = e.target as HTMLFormElement;\n\tconst button = e.submitter as HTMLButtonElement;\n\t// HACK: submit buttons have their formAction set to the current page if not\n\t// set, so we can't just check whether it's empty and fallback to form action\n\t//const action = button?.formAction ?? form.action;\n\tlet action = form.action || document.URL;\n\tif (button && button.formAction && button.formAction !== document.URL) {\n\t\taction = button.formAction;\n\t}\n\tconst options = {\n\t\tbody: new FormData(form),\n\t\tmethod: \"POST\",\n\t\tmode: \"cors\",\n\t\tcredentials: \"same-origin\",\n\t\t// Add a special header which tells the server that we want the raw\n\t\t// error response (if applicable) rather than the reloaded page that you\n\t\t// would get if submitting a page without javascript\n\t\theaders: {\n\t\t\t\"X-Torpor-Form-Submit\": \"\",\n\t\t},\n\t};\n\tconst response = await fetch(\n\t\taction,\n\t\t// @ts-ignore -- don't know what it's complaining about here\n\t\toptions,\n\t);\n\n\tif (\n\t\tresponse.status === 200 &&\n\t\tresponse.headers.has(\"Content-Disposition\") &&\n\t\t/attachment;\\s*filename=\"(.+?)\"/.test(response.headers.get(\"Content-Disposition\")!)\n\t) {\n\t\t// TODO: Is this enough to check to see if we have a file that should download?\n\t\t// Download the file by creating a dummy <a> and clicking it\n\t\tconst downloadFileName =\n\t\t\tresponse.headers.get(\"Content-Disposition\")?.match(/attachment;\\s*filename=\"(.+?)\"/)![1] ??\n\t\t\t\"file\";\n\t\tconst downloadLink = document.createElement(\"a\");\n\t\tdownloadLink.href = window.URL.createObjectURL(await response.blob());\n\t\tdownloadLink.download = downloadFileName;\n\t\tdownloadLink.click();\n\t} else if (response.status === 200 && response.headers.has(\"X-Torpor-Form-Redirect\")) {\n\t\t// TODO: Should do the correct type of redirect e.g. seeOther etc\n\t\tconst redirect = response.headers.get(\"Location\")!;\n\t\tawait load(redirect);\n\t\twindow.location.href = redirect;\n\t} else if (\n\t\t(response.status >= 200 && response.status <= 299) ||\n\t\t(response.status >= 400 && response.status <= 499)\n\t) {\n\t\t// Put the response into `$page.form`, and it will be put into `$props` in reload\n\t\tif (response.headers.get(\"Content-Type\") === \"application/json\") {\n\t\t\t$page.form = await response.json();\n\t\t}\n\t\tawait reload();\n\t} else if (response.status >= 500) {\n\t\t// A server error: like a no-javascript submit, the response is the\n\t\t// error page rendered at this url with the error status. Swap the\n\t\t// document for it -- the url stays, so a transient failure can be\n\t\t// retried with a refresh. Without an error page, reload, which will\n\t\t// show the raw error response instead\n\t\tif (response.headers.get(\"Content-Type\")?.includes(\"text/html\")) {\n\t\t\tconst html = await response.text();\n\t\t\tdocument.open();\n\t\t\tdocument.write(html);\n\t\t\tdocument.close();\n\t\t} else {\n\t\t\twindow.location.reload();\n\t\t}\n\t}\n}\n","import { DATA_REUSE_HEADER, DATA_REQUEST_HEADER } from \"../dataRequest.ts\";\nimport { getBasePath } from \"../site/basePath\";\nimport type LayoutPath from \"../types/LayoutPath\";\nimport type PageEndPoint from \"../types/PageEndPoint\";\nimport type RouteHandler from \"../types/RouteHandler\";\nimport client from \"../state/client\";\n\n/**\n * The result of loading a route's data. `error` is set when a load function\n * returned an error response (redirects excluded) -- the caller renders the\n * error page instead of the route.\n */\nexport type LoadDataResult = {\n\tdata: Record<string, any>;\n\terror?: {\n\t\tstatus: number;\n\t\tmessage: string;\n\t};\n};\n\n/**\n * Loads a route's data for a client-side navigation.\n *\n * One request (`GET <page url>/~server` with the data header) returns the\n * server data for the page and all of its layouts, with hooks running once\n * against the page url. The client then runs its own load functions (layout\n * by layout, then the page), merging each route's fresh server data in the\n * same order the server render does.\n */\nexport default async function loadData(\n\thandler: RouteHandler,\n\tparams: Record<string, string>,\n\tpath: string,\n\tquery: URLSearchParams,\n\tnewLayoutStack: LayoutPath[],\n\tclientEndPoint: PageEndPoint | undefined,\n\tprefetch = false,\n): Promise<LoadDataResult | void> {\n\tlet data = {};\n\n\t// Work out up front which layouts are already rendered (their data and UI\n\t// are reused), so the data request can skip loading them\n\tconst layoutStack = client.layoutStack;\n\tconst layouts = (handler.layouts ?? []).map((layout, index) => {\n\t\tlet layoutPath = layout.path;\n\t\tfor (let key in params) {\n\t\t\tlayoutPath = layoutPath.replace(`[${key}]`, params[key]);\n\t\t}\n\t\tconst previous = layoutStack.at(index);\n\t\tconst reuse = !prefetch && previous?.path === layoutPath;\n\t\treturn { layout, index, layoutPath, previous, reuse };\n\t});\n\n\t// One request for all the (non-reused) server data\n\tconst server = await loadServerData(\n\t\thandler,\n\t\tpath,\n\t\tquery,\n\t\tlayouts.filter((l) => l.reuse).map((l) => l.layoutPath),\n\t);\n\tif (server === undefined) {\n\t\t// A load redirected: the client can't follow it through fetch, so the\n\t\t// caller falls back to a full page load\n\t\treturn;\n\t}\n\tif (\"error\" in server) {\n\t\treturn { data, error: server.error };\n\t}\n\n\tfor (const { layout, index, layoutPath, previous, reuse } of layouts) {\n\t\tconst stackLayout: LayoutPath = {\n\t\t\tpath: layoutPath,\n\t\t\tdata: {},\n\t\t\treuse,\n\t\t\tslotRegion: null,\n\t\t};\n\n\t\tif (reuse && previous) {\n\t\t\t// The layout is already rendered: keep its data and slot region\n\t\t\tstackLayout.slotRegion = previous.slotRegion;\n\t\t\tObject.assign(stackLayout.data, previous.data);\n\t\t} else {\n\t\t\t// A new layout: run its client load (its server data already\n\t\t\t// arrived in the single request)\n\t\t\tconst layoutEndPoint: PageEndPoint | undefined = (await layout.endPoint())?.default;\n\t\t\tconst response = await runClientLoad(\n\t\t\t\tlayoutEndPoint,\n\t\t\t\tclientLocation(layoutPath),\n\t\t\t\tquery,\n\t\t\t\tparams,\n\t\t\t\tstackLayout.data,\n\t\t\t);\n\t\t\tif (response) {\n\t\t\t\tif (isRedirect(response)) return;\n\t\t\t\treturn { data, error: await errorOf(response) };\n\t\t\t}\n\t\t\tconst serverData = server.loads?.[index];\n\t\t\tif (serverData) Object.assign(stackLayout.data, serverData);\n\t\t}\n\n\t\tObject.assign(data, stackLayout.data);\n\t\tnewLayoutStack.push(stackLayout);\n\t}\n\n\t// The page's client load, then its server data\n\tconst response = await runClientLoad(clientEndPoint, clientLocation(path), query, params, data);\n\tif (response) {\n\t\tif (isRedirect(response)) return;\n\t\treturn { data, error: await errorOf(response) };\n\t}\n\tconst pageServerData = server.loads?.[handler.layouts?.length ?? 0];\n\tif (pageServerData) Object.assign(data, pageServerData);\n\n\treturn { data };\n}\n\ntype ServerData = {\n\tloads?: (Record<string, any> | null)[];\n};\n\n/**\n * Fetches the page's combined server data. Returns `undefined` when a load\n * redirected, or an `error` result when a load failed.\n */\nasync function loadServerData(\n\thandler: RouteHandler,\n\tpath: string,\n\tquery: URLSearchParams,\n\treusedLayouts: string[],\n): Promise<ServerData | { error: { status: number; message: string } } | undefined> {\n\tif (!hasServerData(handler)) {\n\t\treturn {};\n\t}\n\n\tconst url = new URL(\n\t\tdocument.location.origin + getBasePath() + path.replace(/\\/$/, \"\") + \"/~server\",\n\t);\n\tfor (let [name, value] of query) {\n\t\turl.searchParams.append(name, value);\n\t}\n\n\tconst headers: Record<string, string> = { [DATA_REQUEST_HEADER]: \"1\" };\n\tif (reusedLayouts.length > 0) {\n\t\theaders[DATA_REUSE_HEADER] = JSON.stringify(reusedLayouts);\n\t}\n\n\tconst response = await fetch(url, {\n\t\tredirect: \"manual\",\n\t\theaders,\n\t});\n\tif (isRedirect(response)) {\n\t\treturn undefined;\n\t}\n\tif (!response.ok) {\n\t\treturn { error: await errorOf(response) };\n\t}\n\t// A site without a server (e.g. a static host) responds with the page's\n\t// html rather than json; there's nothing to merge\n\tif (!response.headers.get(\"Content-Type\")?.includes(\"application/json\")) {\n\t\treturn {};\n\t}\n\treturn (await response.json()) as ServerData;\n}\n\n/**\n * Whether the route has any server-side code to run (a page or layout server\n * load, or a folder hook). Without any, there's no data request to make.\n */\nfunction hasServerData(handler: RouteHandler): boolean {\n\tif (handler.serverHooks && handler.serverHooks.length > 0) return true;\n\tif (handler.serverEndPoint) return true;\n\treturn (handler.layouts ?? []).some((layout) => !!layout.serverEndPoint);\n}\n\n/**\n * Runs a route's client-side load, merging its json data into `data`. Returns\n * a non-ok Response for the caller to turn into an error page.\n */\nasync function runClientLoad(\n\tendPoint: PageEndPoint | undefined,\n\tlocation: string,\n\tquery: URLSearchParams,\n\tparams: Record<string, string>,\n\tdata: Record<string, any>,\n): Promise<Response | undefined> {\n\tif (!endPoint?.load) return;\n\n\tconst clientKey = location + (query.size > 0 ? `?${query}` : \"\");\n\tconst prefetchedData = client.prefetchedData;\n\tif (prefetchedData[clientKey]) {\n\t\tObject.assign(data, prefetchedData[clientKey]);\n\t\treturn;\n\t}\n\n\tconst clientUrl = new URL(document.location.href);\n\tfor (let [name, value] of query) {\n\t\tclientUrl.searchParams.append(name, value);\n\t}\n\tconst clientResponse = await endPoint.load({ url: clientUrl, params, data });\n\tif (clientResponse) {\n\t\tif (clientResponse.ok) {\n\t\t\tif (clientResponse.headers.get(\"Content-Type\")?.includes(\"application/json\")) {\n\t\t\t\tconst clientData = await clientResponse.json();\n\t\t\t\tObject.assign(data, clientData);\n\t\t\t\tprefetchedData[clientKey] = clientData;\n\t\t\t}\n\t\t} else {\n\t\t\treturn clientResponse;\n\t\t}\n\t}\n}\n\nfunction clientLocation(path: string): string {\n\treturn document.location.origin + getBasePath() + path;\n}\n\nfunction isRedirect(response: Response): boolean {\n\t// A `redirect: \"manual\"` fetch surfaces a cross-navigation redirect as an\n\t// opaque (\"opaqueredirect\") response in browsers, with status 0\n\treturn (response.status >= 300 && response.status < 400) || response.type === \"opaqueredirect\";\n}\n\n/**\n * The status and message of a failed load response. The body only becomes\n * the message when it's a `message`-carrying json body or plain text -- an\n * html body is a whole page (e.g. a static host's 404), not a message.\n */\nasync function errorOf(response: Response): Promise<{ status: number; message: string }> {\n\tlet message = \"\";\n\tconst type = response.headers.get(\"Content-Type\");\n\tif (type?.includes(\"application/json\")) {\n\t\ttry {\n\t\t\tconst data = await response.json();\n\t\t\tif (typeof data.message === \"string\") {\n\t\t\t\tmessage = data.message;\n\t\t\t}\n\t\t} catch {\n\t\t\t// Not actually json\n\t\t}\n\t} else if (type?.includes(\"text/plain\")) {\n\t\tmessage = await response.text();\n\t}\n\treturn { status: response.status, message: message || response.statusText };\n}\n","import { clearLayoutSlot, fillLayoutSlot, hydrate } from \"@torpor/view\";\nimport { type Component, type SlotRender } from \"@torpor/view\";\nimport { mount, unmount } from \"@torpor/view\";\nimport $page from \"../state/$page\";\nimport client from \"../state/client\";\nimport { getBasePath, stripBaseFromUrl } from \"../site/basePath\";\nimport findErrorRoute from \"../site/findErrorRoute\";\nimport type LayoutPath from \"../types/LayoutPath\";\nimport type PageEndPoint from \"../types/PageEndPoint\";\nimport formSubmit from \"./formSubmit\";\nimport loadData from \"./loadData\";\n\n// @ts-ignore\nexport default async function navigate(rawUrl: URL, withHydration = false): Promise<boolean> {\n\tlet parent = document.getElementById(\"app\");\n\tif (!parent) {\n\t\t// TODO: 500\n\t\tconsole.log(\"500\");\n\t\treturn false;\n\t}\n\n\t// The base path is stripped before matching (routes are base-free), but\n\t// kept in browser state: the caller pushes the original URL. When the\n\t// url doesn't carry the base there will be no matching route anyway\n\tconst url = stripBaseFromUrl(rawUrl, getBasePath()) ?? rawUrl;\n\tconst path = url.pathname;\n\tconst query = url.searchParams;\n\n\t//console.log(`navigating to '${path}'${query.size ? ` with ${query}` : \"\"}`);\n\n\tlet route = client.router.match(path, query);\n\n\t// Update $page before building the components\n\t$page.url = url;\n\tif (route) {\n\t\tif (path.endsWith(\"/_error\")) {\n\t\t\t// A direct visit to the error page (e.g. a bookmark of the url it\n\t\t\t// used to be redirected to). Make it look a bit classier by\n\t\t\t// stripping the query, which carries the status and message\n\t\t\t$page.status = parseInt(query.get(\"status\") ?? \"404\");\n\t\t\t$page.error = { message: query.get(\"message\") ?? \"\" };\n\t\t\twindow.history.replaceState({}, \"\", rawUrl.toString().split(\"?\")[0]);\n\t\t} else {\n\t\t\t$page.status = 200;\n\t\t\t$page.error = { message: \"\" };\n\t\t}\n\t} else {\n\t\t// There's no page at this url -- render the nearest error page at it,\n\t\t// so the address bar keeps the url the user asked for: a transient\n\t\t// failure can be refreshed, and a typo can be seen and fixed\n\t\tconst errorPath = findErrorRoute(client.router, path);\n\t\tconst errorRoute = errorPath && client.router.match(errorPath, query);\n\t\tif (!errorRoute) {\n\t\t\t// Leave the current page alone; the caller falls back to a full\n\t\t\t// page load, and the server renders the error page (or passes the\n\t\t\t// raw response through, when it has no error page)\n\t\t\treturn false;\n\t\t}\n\t\troute = errorRoute;\n\t\t$page.status = 404;\n\t\t$page.error = { message: \"Not found\" };\n\t}\n\tlet handler = route.handler;\n\tlet params = route.params || {};\n\n\t// There must be a client endpoint with a component. Routes with no client\n\t// component (a pure `+server` route like `/logout`) can't be rendered\n\t// client-side, so return false and let the caller do a full page load\n\tlet clientEndPoint: PageEndPoint | undefined = handler.endPoint\n\t\t? (await handler.endPoint())?.default\n\t\t: undefined;\n\tif (!clientEndPoint?.component) {\n\t\treturn false;\n\t}\n\n\tlet newLayoutStack: LayoutPath[] = [];\n\n\t// Pass the data into $props\n\t// TODO: Don't load if this is the first time -- it should have been passed\n\t// to us, somehow...\n\tconst result = await loadData(handler, params, path, query, newLayoutStack, clientEndPoint);\n\tif (result === undefined) {\n\t\t// A load redirected, or (on a prerendered site with no server) the\n\t\t// ~server request couldn't be made. Leave the current page alone;\n\t\t// the caller (e.g. the client entry) falls back to a full page load,\n\t\t// which follows the redirect\n\t\treturn false;\n\t}\n\tlet data = result.data;\n\tif (result.error) {\n\t\tif (withHydration) {\n\t\t\t// The server rendered this page fine moments ago -- keep its\n\t\t\t// markup rather than hydrating an error page over it\n\t\t\treturn false;\n\t\t}\n\t\t// The load failed -- render the nearest error page at this url, so\n\t\t// the address bar keeps the url the user asked for: a transient\n\t\t// failure (a random db hiccup, say) can be retried with a refresh\n\t\tconst errorPath = findErrorRoute(client.router, path);\n\t\tconst errorRoute = errorPath && client.router.match(errorPath, query);\n\t\tif (!errorRoute) {\n\t\t\t// No error page -- the caller falls back to a full page load,\n\t\t\t// where the server passes the error response through\n\t\t\treturn false;\n\t\t}\n\t\troute = errorRoute;\n\t\thandler = errorRoute.handler;\n\t\tparams = errorRoute.params || {};\n\t\tclientEndPoint = handler.endPoint ? (await handler.endPoint())?.default : undefined;\n\t\tif (!clientEndPoint?.component) {\n\t\t\treturn false;\n\t\t}\n\n\t\t$page.status = result.error.status;\n\t\t$page.error = { message: result.error.message };\n\n\t\t// The error page starts fresh: drop the layouts collected for the\n\t\t// route that failed (the error route's own layouts are loaded into\n\t\t// the empty stack, reusing whatever the current page shares)\n\t\tnewLayoutStack.length = 0;\n\t\tconst errorResult = await loadData(\n\t\t\thandler,\n\t\t\tparams,\n\t\t\tpath,\n\t\t\tquery,\n\t\t\tnewLayoutStack,\n\t\t\tclientEndPoint,\n\t\t);\n\t\tif (errorResult === undefined || errorResult.error) {\n\t\t\t// The error page's own load failed too -- fall back to a full\n\t\t\t// page load\n\t\t\treturn false;\n\t\t}\n\t\tdata = errorResult.data;\n\t}\n\t// We may have form data in a hidden input -- not sure if this is the best\n\t// way to do it\n\tlet formInput = document.getElementById(\"t-form-data\") as HTMLInputElement;\n\tlet form: Record<string, string> | undefined;\n\tif (formInput) {\n\t\tform = JSON.parse(formInput.value);\n\t\t$page.form = form;\n\t\tformInput.remove();\n\t}\n\tlet $props: Record<string, any> = { data };\n\n\t// We may have form data in $page.form, either from the hidden input\n\t// (above), or added via onformsubmit (below)\n\t$props.form = $page.form;\n\n\t// Add some special context for submitting Forms client-side\n\tconst $context = {\n\t\tTorporBuildContext: { onformsubmit: formSubmit },\n\t};\n\n\tclient.layoutStack.push({ path: route.handler.path, data: {}, reuse: false, slotRegion: null });\n\tclient.layoutStack = newLayoutStack;\n\tlet layoutStack = client.layoutStack;\n\n\t// If there are layouts, work our way upwards, pushing each component into\n\t// the default slot of its parent\n\t// TODO: There's probably a nicer way to do this with reducers or something\n\tlet component = clientEndPoint.component as Component;\n\tlet slots: Record<string, SlotRender> | undefined = undefined;\n\tlet reused = false;\n\t// The index of the innermost reused layout. Its slotRegion is the region\n\t// that must be cleared and refilled (it contains the next layout's or the\n\t// page's content). This is usually the last entry of the stack, but not\n\t// when an outer layout is reused while an inner one is new — e.g.\n\t// navigating between sections that share the root layout.\n\tlet reusedIndex = -1;\n\tif (handler.layouts) {\n\t\tlet slotFunctions: SlotRender[] = [];\n\t\t// The last slot function will render the client component\n\t\tslotFunctions[handler.layouts.length] = function clientComponent(parent, anchor) {\n\t\t\tlet i = layoutStack.length - 1;\n\t\t\tlayoutStack[i].slotRegion = fillLayoutSlot(\n\t\t\t\tclientEndPoint.component!,\n\t\t\t\tslotFunctions[i + 1],\n\t\t\t\tparent,\n\t\t\t\tanchor,\n\t\t\t\t$props,\n\t\t\t\t$context,\n\t\t\t);\n\t\t};\n\n\t\t// Each earlier slot function will render a layout\n\t\tfor (let i = handler.layouts.length - 1; i >= 0; i--) {\n\t\t\tconst layoutEndPoint: PageEndPoint | undefined = (await handler.layouts[i].endPoint())\n\t\t\t\t?.default;\n\t\t\tif (layoutEndPoint?.component) {\n\t\t\t\tif (layoutStack[i].reuse) {\n\t\t\t\t\t// Reuse this layout — clear and refill its slot (done in\n\t\t\t\t\t// the try block below so a failure doesn't leave the slot\n\t\t\t\t\t// half-cleared)\n\t\t\t\t\tcomponent = slotFunctions[i + 1] as Component;\n\t\t\t\t\treusedIndex = i;\n\t\t\t\t\treused = true;\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (i === 0) {\n\t\t\t\t\tcomponent = layoutEndPoint.component as Component;\n\t\t\t\t\tslots = { _: slotFunctions[i + 1] };\n\t\t\t\t} else {\n\t\t\t\t\tslotFunctions[i] = function layoutComponent(parent, anchor, _, $context) {\n\t\t\t\t\t\tlayoutStack[i - 1].slotRegion = fillLayoutSlot(\n\t\t\t\t\t\t\tlayoutEndPoint.component!,\n\t\t\t\t\t\t\tslotFunctions[i + 1],\n\t\t\t\t\t\t\tparent,\n\t\t\t\t\t\t\tanchor,\n\t\t\t\t\t\t\t$props,\n\t\t\t\t\t\t\t$context,\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\t}\n\n\t// A definite alias, so that the render closure's type checks hold\n\tlet app: HTMLElement = parent;\n\t// The DOM update, wrapped by the view transitions API when navigating\n\t// (but not on the initial hydration)\n\tconst render = () => {\n\t\ttry {\n\t\t\tif (reused) {\n\t\t\t\t// The layout is being reused — clear the old slot content, then\n\t\t\t\t// call the slot function directly to fill it with the new page.\n\t\t\t\t// We must not go through `mount` here: the slot's container still\n\t\t\t\t// holds the layout's own children (e.g. a header), which `mount`\n\t\t\t\t// refuses to mount into. Both the clear and the fill are inside\n\t\t\t\t// the try so that a failure doesn't leave the slot half-cleared.\n\t\t\t\tconst slotRegion = layoutStack[reusedIndex].slotRegion;\n\t\t\t\tapp = slotRegion.startNode!.parentNode as HTMLElement;\n\t\t\t\tclearLayoutSlot(slotRegion);\n\t\t\t\tcomponent(app, null);\n\t\t\t} else if (withHydration) {\n\t\t\t\thydrate(app, component, $props, slots);\n\t\t\t} else {\n\t\t\t\t// The layout chain changed (or there was no previous layout to\n\t\t\t\t// reuse): tear down the previous UI entirely — disposing its\n\t\t\t\t// region tree and clearing `#app` — so `mount` starts fresh.\n\t\t\t\t// Without this, `mount` throws because `#app` still holds the\n\t\t\t\t// previous render's children, and it would reuse a stale root\n\t\t\t\t// region.\n\t\t\t\tunmount(app);\n\t\t\t\tmount(app, component, $props, slots);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// TODO: Show a proper Error component\n\t\t\tapp.innerHTML = '<span style=\"color: red\">Script syntax error</span><p>' + error + \"</p>\";\n\t\t\tconsole.log(error);\n\t\t}\n\n\t\tif (!withHydration) {\n\t\t\t// Scroll back to the top when moving to a different page; keep the\n\t\t\t// scroll position for same-page navigations (query changes,\n\t\t\t// re-renders after form actions)\n\t\t\tconst current = stripBaseFromUrl(new URL(document.location.href), getBasePath())?.pathname;\n\t\t\tif (current !== path) {\n\t\t\t\twindow.scrollTo(0, 0);\n\t\t\t}\n\t\t}\n\t};\n\n\tif (\n\t\t!withHydration &&\n\t\tclient.viewTransitions &&\n\t\ttypeof document.startViewTransition === \"function\"\n\t) {\n\t\tdocument.startViewTransition(render);\n\t} else {\n\t\trender();\n\t}\n\n\t// Reset prefetched data on each navigation\n\tclient.prefetchedData = {};\n\n\treturn true;\n}\n","import navigate from \"./navigate\";\n\n/**\n * Loads and renders the page at the supplied path.\n */\nexport default async function load(path: string): Promise<boolean> {\n\tconst url = new URL(path, document.location.href);\n\treturn await navigate(url);\n}\n"],"mappings":"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"}
|
package/dist/nav.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as getBasePath, t as addBaseToPath } from "./basePath-DQnbHc7o.mjs";
|
|
2
|
-
import { i as reload, t as load } from "./load-
|
|
2
|
+
import { i as reload, t as load } from "./load-LWQoFWh-.mjs";
|
|
3
3
|
//#region src/nav/route.ts
|
|
4
4
|
/**
|
|
5
5
|
* Builds a route path in a type-safe manner, filling in dynamic segments, e.g.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { t as Site } from "./Site-Blz32JRD.mjs";
|
|
2
|
+
import { Plugin } from "vite";
|
|
3
|
+
//#region src/run/devPlugin.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The default Node-runtime dev plugin. Reads `src/site.html`, sets up a torpor
|
|
6
|
+
* `Server` whose catch-all route renders via `vite.ssrLoadModule`, and registers
|
|
7
|
+
* a Connect middleware (after Vite's own middlewares) that bridges Node
|
|
8
|
+
* req/res to the torpor Server's fetch handler.
|
|
9
|
+
*
|
|
10
|
+
* Adapters that need a different runtime (e.g. workerd) provide their own
|
|
11
|
+
* `dev()` plugin instead.
|
|
12
|
+
*/
|
|
13
|
+
declare function devPlugin(site: Site, sourceMode?: boolean): Plugin;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { devPlugin as nodeDev };
|
|
16
|
+
//# sourceMappingURL=nodeDev.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodeDev.d.mts","names":[],"sources":["../src/run/devPlugin.ts"],"mappings":";;;;;;;;;;;;iBAuBwB,UAAU,MAAM,MAAM,uBAAqB"}
|
package/dist/nodeDev.mjs
ADDED
package/dist/openapi.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as StandardSchemaV1 } from "./StandardSchema-D28L8_zZ.mjs";
|
|
2
|
-
import { h as SitePlugin } from "./Site-
|
|
2
|
+
import { h as SitePlugin } from "./Site-Blz32JRD.mjs";
|
|
3
3
|
//#region src/openapi/types.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* A JSON Schema object, as produced by a schema library's converter (e.g.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as response } from "./unprocessable-CoMN2zFa.mjs";
|
|
2
2
|
//#region src/response/badRequest.ts
|
|
3
3
|
/**
|
|
4
4
|
* 400 Bad Request
|
|
@@ -66,6 +66,17 @@ function forbidden(body) {
|
|
|
66
66
|
return response(403, body ?? "Forbidden");
|
|
67
67
|
}
|
|
68
68
|
//#endregion
|
|
69
|
+
//#region src/response/transfer.ts
|
|
70
|
+
/**
|
|
71
|
+
* Creates a redirect response with the supplied status code.
|
|
72
|
+
*/
|
|
73
|
+
function transfer(status, location) {
|
|
74
|
+
return new Response(null, {
|
|
75
|
+
status,
|
|
76
|
+
headers: { location }
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
69
80
|
//#region src/response/found.ts
|
|
70
81
|
/**
|
|
71
82
|
* 302 Found
|
|
@@ -203,6 +214,25 @@ function permanentRedirect(location) {
|
|
|
203
214
|
return transfer(308, location);
|
|
204
215
|
}
|
|
205
216
|
//#endregion
|
|
217
|
+
//#region src/response/seeOther.ts
|
|
218
|
+
/**
|
|
219
|
+
* 303 See Other
|
|
220
|
+
*
|
|
221
|
+
* The HTTP 303 See Other redirection response status code indicates that the
|
|
222
|
+
* browser should redirect to the URL in the Location header instead of
|
|
223
|
+
* rendering the requested resource.
|
|
224
|
+
*
|
|
225
|
+
* This response code is often sent back as a result of PUT or POST methods so
|
|
226
|
+
* the client may retrieve a confirmation, or view a representation of a
|
|
227
|
+
* real-world object (see HTTP range-14). The method to retrieve the redirected
|
|
228
|
+
* resource is always GET.
|
|
229
|
+
*
|
|
230
|
+
* See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/303
|
|
231
|
+
*/
|
|
232
|
+
function seeOther(location) {
|
|
233
|
+
return transfer(303, location);
|
|
234
|
+
}
|
|
235
|
+
//#endregion
|
|
206
236
|
//#region src/response/serverError.ts
|
|
207
237
|
/**
|
|
208
238
|
* 500 Server Error
|
|
@@ -279,6 +309,6 @@ function unauthorized(body) {
|
|
|
279
309
|
return response(401, body ?? "Unauthorized");
|
|
280
310
|
}
|
|
281
311
|
//#endregion
|
|
282
|
-
export {
|
|
312
|
+
export { permanentRedirect as a, methodNotAllowed as c, forbidden as d, created as f, seeOther as i, found as l, temporaryRedirect as n, notModified as o, badRequest as p, serverError as r, movedPermanently as s, unauthorized as t, transfer as u };
|
|
283
313
|
|
|
284
|
-
//# sourceMappingURL=response-
|
|
314
|
+
//# sourceMappingURL=response-sth6FQsj.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-sth6FQsj.mjs","names":[],"sources":["../src/response/badRequest.ts","../src/response/created.ts","../src/response/forbidden.ts","../src/response/transfer.ts","../src/response/found.ts","../src/response/methodNotAllowed.ts","../src/response/movedPermanently.ts","../src/response/notModified.ts","../src/response/permanentRedirect.ts","../src/response/seeOther.ts","../src/response/serverError.ts","../src/response/temporaryRedirect.ts","../src/response/unauthorized.ts"],"sourcesContent":["import response from \"./response\";\nimport type { Jsonify } from \"../types/Jsonify\";\nimport type TypedResponse from \"./TypedResponse\";\n\ntype BadRequestResponse<T extends object | string | undefined> = T extends object\n\t? TypedResponse<Jsonify<T>>\n\t: Response;\n\n/**\n * 400 Bad Request\n *\n * The HTTP 400 Bad Request client error response status code indicates that the\n * server would not process the request due to something the server considered\n * to be a client error. The reason for a 400 response is typically due to\n * malformed request syntax, invalid request message framing, or deceptive\n * request routing.\n *\n * Clients that receive a 400 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/400\n */\nexport default function badRequest<T extends object | string | undefined>(\n\tbody?: T,\n): BadRequestResponse<T> {\n\treturn response(400, body ?? \"Bad request\") as BadRequestResponse<T>;\n}\n","import type { Jsonify } from \"../types/Jsonify\";\nimport type TypedResponse from \"./TypedResponse\";\nimport response from \"./response\";\n\ntype CreatedResponse<T extends object | string | undefined> = T extends object\n\t? TypedResponse<Jsonify<T>>\n\t: Response;\n\n/**\n * 201 Created\n *\n * The HTTP 201 Created successful response status code indicates that the HTTP\n * request has led to the creation of a resource. This status code is commonly\n * sent as the result of a POST request.\n *\n * The new resource, or a description and link to the new resource, is created\n * before the response is returned. The newly-created items can be returned in\n * the body of the response message, but must be locatable by the URL of the\n * initiating request or by the URL in the value of the Location header provided\n * with the response.\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/201\n */\nexport default function created<T extends object | string | undefined>(\n\tbody?: T,\n): CreatedResponse<T> {\n\treturn response(201, body) as CreatedResponse<T>;\n}\n","import response from \"./response\";\n\n/**\n * 403 Forbidden\n *\n * The HTTP 403 Forbidden client error response status code indicates that the\n * server understood the request but refused to process it. This status is\n * similar to 401, except that for 403 Forbidden responses, authenticating or\n * re-authenticating makes no difference. The request failure is tied to\n * application logic, such as insufficient permissions to a resource or action.\n *\n * Clients that receive a 403 response should expect that repeating the request\n * without modification will fail with the same error. Server owners may decide\n * to send a 404 response instead of a 403 if acknowledging the existence of a\n * resource to clients with insufficient privileges is not desired.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/403\n */\nexport default function forbidden(body?: object | string): Response {\n\treturn response(403, body ?? \"Forbidden\");\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 transfer from \"./transfer\";\n\n/**\n * 302 Found\n *\n * The HTTP 302 Found redirection response status code indicates that the\n * requested resource has been temporarily moved to the URL in the Location\n * header.\n *\n * A browser receiving this status will automatically request the resource at\n * the URL in the Location header, redirecting the user to the new page. Search\n * engines receiving this response will not attribute links to the original URL\n * to the new resource, meaning no SEO value is transferred to the new URL.\n *\n * > Note: In the Fetch Standard, when a user agent receives a 302 in response\n * > to a POST request, it uses the GET method in the subsequent redirection\n * > request, as permitted by the HTTP specification. To avoid user agents\n * > modifying the request, use 307 Temporary Redirect instead, as altering the\n * > method after a 307 response is prohibited.\n *\n * > In cases where you want any request method to be changed to GET, use 303\n * > See Other. This is useful when you want to give a response to a PUT method\n * > that is not the uploaded resource but a confirmation message such as: \"you\n * > successfully uploaded XYZ\".\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/302\n */\nexport default function found(location: string): Response {\n\treturn transfer(302, location);\n}\n","import response from \"./response\";\n\n/**\n * 405 Method Not Allowed\n *\n * The HTTP 405 Method Not Allowed client error response status code indicates\n * that the server knows the request method, but the target resource doesn't\n * support this method. The server must generate an Allow header in a 405\n * response with a list of methods that the target resource currently supports.\n *\n * Improper server-side permissions set on files or directories may cause a 405\n * response when the request would otherwise be expected to succeed.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/405\n */\nexport default function methodNotAllowed(body?: object | string): Response {\n\treturn response(405, body ?? \"Method not allowed\");\n}\n","import transfer from \"./transfer\";\n\n/**\n * 301 Moved Permanently\n *\n * The HTTP 301 Moved Permanently redirection response status code indicates\n * that the requested resource has been permanently moved to the URL in the\n * Location header.\n *\n * A browser receiving this status will automatically request the resource at\n * the URL in the Location header, redirecting the user to the new page. Search\n * engines receiving this response will attribute links to the original URL to\n * the redirected resource, passing the SEO ranking to the new URL.\n *\n * > Note: In the Fetch Standard, when a user agent receives a 301 in response\n * > to a POST request, it uses the GET method in the subsequent redirection\n * > request, as permitted by the HTTP specification. To avoid user agents\n * > modifying the request, use 308 Permanent Redirect instead, as altering the\n * > method after a 308 response is prohibited.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/301\n */\nexport default function movedPermanently(location: string): Response {\n\treturn transfer(301, location);\n}\n","import transfer from \"./transfer\";\n\n/**\n * 304 Not Modified\n *\n * The HTTP 304 Not Modified redirection response status code indicates that\n * there is no need to retransmit the requested resources.\n *\n * This response code is sent when the request is a conditional GET or HEAD\n * request with an If-None-Match or an If-Modified-Since header and the\n * condition evaluates to 'false'. It confirms that the resource cached by the\n * client is still valid and that the server would have sent a 200 OK response\n * with the resource if the condition evaluated to 'true'. See HTTP caching for\n * more information.\n *\n * The response must not contain a body and must include the headers that would\n * have been sent in an equivalent 200 response, such as:\n *\n * - Cache-Control\n * - Content-Location\n * - Date\n * - ETag\n * - Expires\n * - Vary\n *\n * > Note: Many developer tools' network panels of browsers create extraneous\n * > requests leading to 304 responses, so that access to the local cache is\n * > visible to developers.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/304\n */\nexport default function notModified(): Response {\n\treturn transfer(304, \"\");\n}\n","import transfer from \"./transfer\";\n\n/**\n * 308 Permanent Redirect\n *\n * The HTTP 308 Permanent Redirect redirection response status code indicates\n * that the requested resource has been permanently moved to the URL given by\n * the Location header.\n *\n * A browser receiving this status will automatically request the resource at\n * the URL in the Location header, redirecting the user to the new page. Search\n * engines receiving this response will attribute links to the original URL to\n * the redirected resource, passing the SEO ranking to the new URL.\n *\n * The request method and the body will not be modified by the client in the\n * redirected request. A 301 Moved Permanently requires the request method and\n * the body to remain unchanged when redirection is performed, but this is\n * incorrectly handled by older clients to use the GET method instead.\n *\n * > Note: Some Web applications may use the 308 Permanent Redirect in a\n * > non-standard way and for different purposes. For example, Google Drive uses\n * > a 308 Resume Incomplete response to indicate to the client when an\n * > unfinished upload has stalled. See Perform a resumable download on the\n * > Google Drive documentation for more information.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/308\n */\nexport default function permanentRedirect(location: string): Response {\n\treturn transfer(308, location);\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\";\n\n/**\n * 500 Server Error\n *\n * The HTTP 500 Internal Server Error server error response status code\n * indicates that the server encountered an unexpected condition that prevented\n * it from fulfilling the request. This error is a generic \"catch-all\" response\n * to server issues, indicating that the server cannot find a more appropriate\n * 5XX error to respond with.\n *\n * If you're a visitor seeing 500 errors on a web page, these issues require\n * investigation by server owners or administrators. There are many possible\n * causes of 500 errors, including: improper server configuration, out-of-memory\n * (OOM) issues, unhandled exceptions, improper file permissions, or other\n * complex factors. Server administrators may proactively log occurrences of\n * server error responses, like the 500 status code, with details about the\n * initiating requests to improve the stability of a service in the future.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/500\n */\nexport default function serverError(body?: object | string): Response {\n\treturn response(500, body ?? \"Server error\");\n}\n","import transfer from \"./transfer\";\n\n/**\n * 307 Temporary Redirect\n *\n * The HTTP 307 Temporary Redirect redirection response status code indicates\n * that the resource requested has been temporarily moved to the URL in the\n * Location header.\n *\n * A browser receiving this status will automatically request the resource at\n * the URL in the Location header, redirecting the user to the new page. Search\n * engines receiving this response will not attribute links to the original URL\n * to the new resource, meaning no SEO value is transferred to the new URL.\n *\n * The method and the body of the original request are reused to perform the\n * redirected request. In the cases where you want the request method to be\n * changed to GET, use 303 See Other instead. This is useful when you want to\n * give an answer to a successful PUT request that is not the uploaded resource,\n * but a status monitor or confirmation message like \"You have successfully\n * uploaded XYZ\".\n *\n * The difference between 307 and 302 is that 307 guarantees that the client\n * will not change the request method and body when the redirected request is\n * made. With 302, older clients incorrectly changed the method to GET. 307 and\n * 302 responses are identical when the request method is GET.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/307\n */\nexport default function temporaryRedirect(location: string): Response {\n\treturn transfer(307, location);\n}\n","import response from \"./response\";\n\n/**\n * 401 Unauthorized\n *\n * The HTTP 401 Unauthorized client error response status code indicates that a\n * request was not successful because it lacks valid authentication credentials\n * for the requested resource. This status code is sent with an HTTP\n * WWW-Authenticate response header that contains information on the\n * authentication scheme the server expects the client to include to make the\n * request successfully.\n *\n * A 401 Unauthorized is similar to the 403 Forbidden response, except that a\n * 403 is returned when a request contains valid credentials, but the client\n * does not have permissions to perform a certain action.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/401\n */\nexport default function unauthorized(body?: object | string): Response {\n\treturn response(401, body ?? \"Unauthorized\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA0BA,SAAwB,WACvB,MACwB;CACxB,OAAO,SAAS,KAAK,QAAQ,aAAa;AAC3C;;;;;;;;;;;;;;;;;;;;;ACJA,SAAwB,QACvB,MACqB;CACrB,OAAO,SAAS,KAAK,IAAI;AAC1B;;;;;;;;;;;;;;;;;;;ACZA,SAAwB,UAAU,MAAkC;CACnE,OAAO,SAAS,KAAK,QAAQ,WAAW;AACzC;;;;;;ACjBA,SAAwB,SACvB,QACA,UACW;CACX,OAAO,IAAI,SAAS,MAAM;EACzB;EACA,SAAS,EACR,SACD;CACD,CAAC;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACcA,SAAwB,MAAM,UAA4B;CACzD,OAAO,SAAS,KAAK,QAAQ;AAC9B;;;;;;;;;;;;;;;;ACdA,SAAwB,iBAAiB,MAAkC;CAC1E,OAAO,SAAS,KAAK,QAAQ,oBAAoB;AAClD;;;;;;;;;;;;;;;;;;;;;;;ACKA,SAAwB,iBAAiB,UAA4B;CACpE,OAAO,SAAS,KAAK,QAAQ;AAC9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACOA,SAAwB,cAAwB;CAC/C,OAAO,SAAS,KAAK,EAAE;AACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACNA,SAAwB,kBAAkB,UAA4B;CACrE,OAAO,SAAS,KAAK,QAAQ;AAC9B;;;;;;;;;;;;;;;;;ACbA,SAAwB,SAAS,UAA4B;CAC5D,OAAO,SAAS,KAAK,QAAQ;AAC9B;;;;;;;;;;;;;;;;;;;;;;ACGA,SAAwB,YAAY,MAAkC;CACrE,OAAO,SAAS,KAAK,QAAQ,cAAc;AAC5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACKA,SAAwB,kBAAkB,UAA4B;CACrE,OAAO,SAAS,KAAK,QAAQ;AAC9B;;;;;;;;;;;;;;;;;;;ACZA,SAAwB,aAAa,MAAkC;CACtE,OAAO,SAAS,KAAK,QAAQ,cAAc;AAC5C"}
|
package/dist/response.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as
|
|
1
|
+
import { i as response, n as ok, r as notFound, t as unprocessable } from "./unprocessable-CoMN2zFa.mjs";
|
|
2
|
+
import { a as permanentRedirect, c as methodNotAllowed, d as forbidden, f as created, i as seeOther, l as found, n as temporaryRedirect, o as notModified, p as badRequest, r as serverError, s as movedPermanently, t as unauthorized, u as transfer } from "./response-sth6FQsj.mjs";
|
|
3
3
|
export { badRequest, created, forbidden, found, methodNotAllowed, movedPermanently, notFound, notModified, ok, permanentRedirect, response, seeOther, serverError, temporaryRedirect, transfer, unauthorized, unprocessable };
|
package/dist/run.d.mts
CHANGED
package/dist/run.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as runDev, i as runPreview, o as runBuild, r as run, t as runOpenApi } from "./runOpenApi-
|
|
1
|
+
import { a as runDev, i as runPreview, o as runBuild, r as run, t as runOpenApi } from "./runOpenApi-tnflDjZV.mjs";
|
|
2
2
|
export { run, runBuild, runDev, runOpenApi, runPreview };
|