bosia 1.2.5 → 1.2.7
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 +5 -6
- package/package.json +2 -1
- package/src/core/backend.ts +87 -3
- package/src/core/basePath.ts +30 -0
- package/src/core/cache.ts +378 -30
- package/src/core/client/App.svelte +19 -11
- package/src/core/client/hydrate.ts +17 -9
- package/src/core/client/navigation.ts +1 -1
- package/src/core/client/prefetch.ts +66 -41
- package/src/core/client/router.svelte.ts +41 -22
- package/src/core/cors.ts +17 -1
- package/src/core/csrf.ts +32 -19
- package/src/core/dedup.ts +51 -7
- package/src/core/dev.ts +11 -1
- package/src/core/devWsProxy.ts +144 -0
- package/src/core/env.ts +7 -0
- package/src/core/errors.ts +23 -6
- package/src/core/hooks.ts +1 -1
- package/src/core/html.ts +13 -1
- package/src/core/plugins/access-log.ts +128 -0
- package/src/core/prerender.ts +143 -6
- package/src/core/proxy.ts +48 -0
- package/src/core/renderer.ts +70 -29
- package/src/core/routeTypes.ts +16 -1
- package/src/core/server.bun.ts +6 -1
- package/src/core/server.ts +198 -77
- package/src/core/server.workers.ts +3 -2
- package/src/core/types/plugin.ts +2 -1
- package/src/core/websocket.ts +232 -0
- package/src/core/workersGuard.ts +18 -3
- package/src/lib/index.ts +1 -0
- package/templates/default/.env.example +20 -5
- package/templates/default/tsconfig.json +1 -1
- package/templates/demo/.env.example +20 -5
- package/templates/demo/src/hooks.server.ts +3 -12
- package/templates/demo/tsconfig.json +1 -1
- package/templates/shop/src/app.d.ts +0 -1
- package/templates/shop/src/hooks.server.ts +3 -11
- package/templates/shop/src/routes/+layout.server.ts +0 -1
- package/templates/shop/tsconfig.json +1 -1
- package/templates/store/src/app.d.ts +0 -1
- package/templates/store/src/hooks.server.ts +3 -11
- package/templates/store/src/routes/+layout.server.ts +0 -1
- package/templates/store/tsconfig.json +1 -1
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
// ─── WebSockets (Bun only) ────────────────────────────────
|
|
2
|
+
// A `+server.ts` exports `websocket = { upgrade?, open, message, close, … }`.
|
|
3
|
+
// resolve() runs `upgrade()` after the hooks, then hands the request to Bun's
|
|
4
|
+
// `server.upgrade()`. Bun.serve takes one websocket handler for the whole
|
|
5
|
+
// server, so the upgrade carries the route's handlers in an envelope; open()
|
|
6
|
+
// keeps them per socket and sets `ws.data` to what upgrade() returned.
|
|
7
|
+
//
|
|
8
|
+
// Subprotocols are not selectable yet: `upgrade()` returns only data. To add
|
|
9
|
+
// it, let the export declare `protocols: string[]` and send the first one the
|
|
10
|
+
// client offers as `Sec-WebSocket-Protocol` in server.upgrade's headers. The
|
|
11
|
+
// dev proxy already passes it through.
|
|
12
|
+
|
|
13
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
14
|
+
|
|
15
|
+
import type { Server, ServerWebSocket, WebSocketHandler as BunWebSocketHandler } from "bun";
|
|
16
|
+
|
|
17
|
+
import type { RequestEvent } from "./hooks.ts";
|
|
18
|
+
|
|
19
|
+
/** What a `+server.ts` exports as `websocket`. `ws` is Bun's ServerWebSocket. */
|
|
20
|
+
export interface WebSocketHandler<T extends object = {}, E = RequestEvent> {
|
|
21
|
+
/**
|
|
22
|
+
* Runs after `hooks.server.ts`, so `event.locals` is set. Return the
|
|
23
|
+
* connection's `ws.data` (a fresh object per connection), or a Response to
|
|
24
|
+
* refuse. A thrown `error()` / `redirect()` answers like an API handler.
|
|
25
|
+
*/
|
|
26
|
+
upgrade?(event: E): T | Response | void | Promise<T | Response | void>;
|
|
27
|
+
open?(ws: ServerWebSocket<T>): unknown;
|
|
28
|
+
/** `string` for text frames, `Buffer` for binary frames. */
|
|
29
|
+
message?(ws: ServerWebSocket<T>, message: string | Buffer): unknown;
|
|
30
|
+
/** The socket can take more data again after `send()` returned -1. */
|
|
31
|
+
drain?(ws: ServerWebSocket<T>): unknown;
|
|
32
|
+
close?(ws: ServerWebSocket<T>, code: number, reason: string): unknown;
|
|
33
|
+
ping?(ws: ServerWebSocket<T>, data: Buffer): unknown;
|
|
34
|
+
pong?(ws: ServerWebSocket<T>, data: Buffer): unknown;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface WebSocketOptions {
|
|
38
|
+
maxPayloadLength: number;
|
|
39
|
+
idleTimeout: number;
|
|
40
|
+
backpressureLimit: number;
|
|
41
|
+
perMessageDeflate: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
type Socket = ServerWebSocket<any>;
|
|
45
|
+
|
|
46
|
+
/** What server.upgrade() carries until open() unwraps it. */
|
|
47
|
+
class Envelope {
|
|
48
|
+
constructor(
|
|
49
|
+
readonly handler: WebSocketHandler<any, any>,
|
|
50
|
+
readonly data: object,
|
|
51
|
+
) {}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Per socket, not on ws.data: one object returned by two routes (a cached
|
|
55
|
+
// session user, say) must not carry either route's handlers.
|
|
56
|
+
const routeOf = new WeakMap<Socket, WebSocketHandler<any, any>>();
|
|
57
|
+
|
|
58
|
+
// Sec-WebSocket-Key too: a stray Upgrade header on a plain GET (a proxy, a
|
|
59
|
+
// scanner) must reach the GET handler, not run upgrade() and then 400.
|
|
60
|
+
export function isUpgradeRequest(request: Request): boolean {
|
|
61
|
+
return (
|
|
62
|
+
request.method === "GET" &&
|
|
63
|
+
request.headers.get("upgrade")?.toLowerCase() === "websocket" &&
|
|
64
|
+
request.headers.has("sec-websocket-key")
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// One per upgrade request, set by BosiaApp.fetch. It holds the Request Bun gave
|
|
69
|
+
// (server.upgrade() needs that one, and a hook may pass resolve() a new one)
|
|
70
|
+
// and whether the upgrade happened — a per-request flag, so a hook that
|
|
71
|
+
// rebuilds or mutates the returned Response can't hide or leak it.
|
|
72
|
+
interface UpgradeContext {
|
|
73
|
+
request?: Request;
|
|
74
|
+
server?: Server<any>;
|
|
75
|
+
upgraded: boolean;
|
|
76
|
+
/** Set by open(), which Bun runs inside server.upgrade(). */
|
|
77
|
+
socket?: Socket;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const upgrades = new AsyncLocalStorage<UpgradeContext>();
|
|
81
|
+
|
|
82
|
+
export async function runUpgrade<T>(
|
|
83
|
+
request: Request,
|
|
84
|
+
server: Server<any>,
|
|
85
|
+
fn: () => Promise<T>,
|
|
86
|
+
): Promise<T> {
|
|
87
|
+
const ctx: UpgradeContext = { request, server, upgraded: false };
|
|
88
|
+
try {
|
|
89
|
+
return await upgrades.run(ctx, fn);
|
|
90
|
+
} finally {
|
|
91
|
+
// A timer or pool started during this request keeps the context: it must
|
|
92
|
+
// not hold the Request, nor see isUpgraded() in its own later fetches.
|
|
93
|
+
ctx.request = ctx.server = ctx.socket = undefined;
|
|
94
|
+
ctx.upgraded = false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** True once this request has been upgraded: Bun already sent the 101. */
|
|
99
|
+
export function isUpgraded(): boolean {
|
|
100
|
+
return upgrades.getStore()?.upgraded === true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** A hook threw after the 101: close the socket, as a handler error would. */
|
|
104
|
+
export function closeUpgraded(): void {
|
|
105
|
+
const ws = upgrades.getStore()?.socket;
|
|
106
|
+
if (ws) closeEach([ws], 1011, "Internal error");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let closing = false;
|
|
110
|
+
|
|
111
|
+
// Bun answers without a protocol, so a browser that asked for one fails the
|
|
112
|
+
// handshake with no error on the server. Warn once per route, not per connect.
|
|
113
|
+
const warnedProtocol = new WeakSet<WebSocketHandler<any, any>>();
|
|
114
|
+
|
|
115
|
+
function warnProtocol(handler: WebSocketHandler<any, any>, request: Request): void {
|
|
116
|
+
const asked = request.headers.get("sec-websocket-protocol");
|
|
117
|
+
if (!asked || warnedProtocol.has(handler)) return;
|
|
118
|
+
warnedProtocol.add(handler);
|
|
119
|
+
console.warn(
|
|
120
|
+
`[WebSocket] ${new URL(request.url).pathname}: the client asked for Sec-WebSocket-Protocol ` +
|
|
121
|
+
`"${asked}", but Bosia can't pick one yet. Browsers fail this handshake; drop the ` +
|
|
122
|
+
`protocols argument from new WebSocket().`,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Upgrade the current request with `data` as `ws.data`. Returns a placeholder
|
|
128
|
+
* Response (Bun ignores it; isUpgraded() is the signal), or the Response to
|
|
129
|
+
* send instead (bad handshake, a runtime without WebSockets).
|
|
130
|
+
*/
|
|
131
|
+
export function upgradeRequest(
|
|
132
|
+
handler: WebSocketHandler<any, any>,
|
|
133
|
+
data: object,
|
|
134
|
+
headers: Headers,
|
|
135
|
+
): Response {
|
|
136
|
+
const ctx = upgrades.getStore();
|
|
137
|
+
if (!ctx?.request || !ctx.server) {
|
|
138
|
+
return new Response("WebSockets are not supported here", { status: 501 });
|
|
139
|
+
}
|
|
140
|
+
warnProtocol(handler, ctx.request);
|
|
141
|
+
if (!ctx.server.upgrade(ctx.request, { data: new Envelope(handler, data) as any, headers })) {
|
|
142
|
+
return new Response("Bad WebSocket handshake", { status: 400 });
|
|
143
|
+
}
|
|
144
|
+
ctx.upgraded = true;
|
|
145
|
+
return new Response(null, { status: 200 });
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ─── Shared Bun handlers ─────────────────────────────────
|
|
149
|
+
|
|
150
|
+
const sockets = new Set<Socket>();
|
|
151
|
+
|
|
152
|
+
function fail(ws: Socket, err: unknown): void {
|
|
153
|
+
console.error("WebSocket handler error:", err);
|
|
154
|
+
closeEach([ws], 1011, "Internal error");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// A user handler's throw or rejection closes that socket with 1011; it must
|
|
158
|
+
// never reach the prod `uncaughtException` handler, which exits the process.
|
|
159
|
+
//
|
|
160
|
+
// Bun runs open() inside server.upgrade(), so in the upgrade request's async
|
|
161
|
+
// context; exit() it, so a timer or callback started in open() doesn't hold
|
|
162
|
+
// that request or see isUpgraded() in its own in-process fetches. (Other
|
|
163
|
+
// events run outside it; exit() is then a no-op.)
|
|
164
|
+
function run(ws: Socket, name: Exclude<keyof WebSocketHandler, "upgrade">, args: unknown[]): void {
|
|
165
|
+
upgrades.exit(() => call(ws, name, args));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function call(ws: Socket, name: Exclude<keyof WebSocketHandler, "upgrade">, args: unknown[]): void {
|
|
169
|
+
const handler = routeOf.get(ws);
|
|
170
|
+
const fn = handler?.[name] as ((...a: unknown[]) => unknown) | undefined;
|
|
171
|
+
if (!fn) return;
|
|
172
|
+
try {
|
|
173
|
+
const out = fn.call(handler, ws, ...args);
|
|
174
|
+
if (out instanceof Promise) out.catch((err) => fail(ws, err));
|
|
175
|
+
} catch (err) {
|
|
176
|
+
fail(ws, err);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export const websocketHandlers: BunWebSocketHandler<any> = {
|
|
181
|
+
open(ws) {
|
|
182
|
+
// The very object upgrade() returned becomes ws.data (an app may keep it
|
|
183
|
+
// in a registry).
|
|
184
|
+
const envelope = ws.data as Envelope;
|
|
185
|
+
routeOf.set(ws, envelope.handler);
|
|
186
|
+
ws.data = envelope.data;
|
|
187
|
+
sockets.add(ws);
|
|
188
|
+
const ctx = upgrades.getStore();
|
|
189
|
+
if (ctx) ctx.socket = ws;
|
|
190
|
+
run(ws, "open", []);
|
|
191
|
+
// An upgrade still in its async upgrade() during the shutdown sweep opens
|
|
192
|
+
// after it: the app has seen open() and gets close(), so it can clean up.
|
|
193
|
+
if (closing) ws.close(1001, "Server shutting down");
|
|
194
|
+
},
|
|
195
|
+
message(ws, message) {
|
|
196
|
+
run(ws, "message", [message]);
|
|
197
|
+
},
|
|
198
|
+
drain(ws) {
|
|
199
|
+
run(ws, "drain", []);
|
|
200
|
+
},
|
|
201
|
+
close(ws, code, reason) {
|
|
202
|
+
sockets.delete(ws);
|
|
203
|
+
run(ws, "close", [code, reason]);
|
|
204
|
+
},
|
|
205
|
+
ping(ws, data) {
|
|
206
|
+
run(ws, "ping", [data]);
|
|
207
|
+
},
|
|
208
|
+
pong(ws, data) {
|
|
209
|
+
run(ws, "pong", [data]);
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/** Shutdown: close every open socket with 1001 (clients reconnect elsewhere),
|
|
214
|
+
* and any that opens from here on. */
|
|
215
|
+
export function closeAllSockets(): void {
|
|
216
|
+
closing = true;
|
|
217
|
+
closeEach(sockets, 1001, "Server shutting down");
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function closeEach(
|
|
221
|
+
list: Iterable<ServerWebSocket<any>>,
|
|
222
|
+
code: number,
|
|
223
|
+
reason: string,
|
|
224
|
+
): void {
|
|
225
|
+
for (const ws of [...list]) {
|
|
226
|
+
try {
|
|
227
|
+
ws.close(code, reason);
|
|
228
|
+
} catch {
|
|
229
|
+
/* already closed */
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
package/src/core/workersGuard.ts
CHANGED
|
@@ -19,6 +19,7 @@ export interface WorkersGuardHit {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
const SERVER_FILE = /(^|\/)(hooks\.server\.(ts|js)|\+server\.(ts|js)|\+[^/]*\.server\.(ts|js))$/;
|
|
22
|
+
const API_FILE = /(^|\/)\+server\.(ts|js)$/;
|
|
22
23
|
const LIB_SERVER = /^lib\/server\/.*\.(ts|js)$/;
|
|
23
24
|
const FS_MODULES = new Set(["fs", "node:fs", "fs/promises", "node:fs/promises"]);
|
|
24
25
|
|
|
@@ -54,13 +55,27 @@ export function findWorkersIncompatible(srcDir = "./src"): WorkersGuardHit[] {
|
|
|
54
55
|
const lines = source.split("\n");
|
|
55
56
|
|
|
56
57
|
let imports: { path: string }[] = [];
|
|
58
|
+
let exports: string[] = [];
|
|
57
59
|
try {
|
|
58
|
-
imports = new Bun.Transpiler({
|
|
59
|
-
|
|
60
|
-
).
|
|
60
|
+
({ imports, exports } = new Bun.Transpiler({
|
|
61
|
+
loader: rel.endsWith(".js") ? "js" : "ts",
|
|
62
|
+
}).scan(source));
|
|
61
63
|
} catch {
|
|
62
64
|
continue; // syntax error — the real build reports it better
|
|
63
65
|
}
|
|
66
|
+
// Any export form (`const`, `let`, `export { websocket }`) shows up here.
|
|
67
|
+
if (API_FILE.test(rel) && exports.includes("websocket")) {
|
|
68
|
+
const i = Math.max(
|
|
69
|
+
0,
|
|
70
|
+
lines.findIndex((l) => /\bwebsocket\b/.test(l) && /\bexport\b/.test(l)),
|
|
71
|
+
);
|
|
72
|
+
hits.push({
|
|
73
|
+
file,
|
|
74
|
+
line: i + 1,
|
|
75
|
+
col: 1,
|
|
76
|
+
message: "exports `websocket` — WebSockets are Bun-only for now",
|
|
77
|
+
});
|
|
78
|
+
}
|
|
64
79
|
for (const { path } of imports) {
|
|
65
80
|
const message = badImport(path);
|
|
66
81
|
if (!message) continue;
|
package/src/lib/index.ts
CHANGED
|
@@ -34,6 +34,7 @@ export type {
|
|
|
34
34
|
PlatformEnv,
|
|
35
35
|
} from "../core/hooks.ts";
|
|
36
36
|
export type { CsrfConfig } from "../core/csrf.ts";
|
|
37
|
+
export type { WebSocketHandler } from "../core/websocket.ts";
|
|
37
38
|
export type { CorsConfig } from "../core/cors.ts";
|
|
38
39
|
export { defineConfig } from "../core/types/plugin.ts";
|
|
39
40
|
export type {
|
|
@@ -48,6 +48,20 @@ PUBLIC_STATIC_APP_NAME=My Bosia App
|
|
|
48
48
|
#
|
|
49
49
|
# Max cache entries (LRU). Set to 0 to disable the cache entirely. Defaults to 500.
|
|
50
50
|
# CACHE_MAX_ENTRIES=500
|
|
51
|
+
# Memory for all cached responses together, in bytes (0 = entry count only).
|
|
52
|
+
# CACHE_MAX_BYTES=104857600
|
|
53
|
+
# Query params left out of the page cache key: a link with ?utm_source=… or
|
|
54
|
+
# ?fbclid=… gets the cached page of the same URL without them, instead of a new
|
|
55
|
+
# render per ad click. Comma-separated; `name*` matches a prefix; `none` turns
|
|
56
|
+
# it off. Without that cached page, or when load()/metadata() reads one of
|
|
57
|
+
# these params, the full URL is cached on its own, as before.
|
|
58
|
+
# Defaults to the list below. Setting it replaces the list.
|
|
59
|
+
# CACHE_IGNORE_PARAMS=utm_*,fbclid,gclid,gbraid,wbraid,dclid,msclkid,twclid,ttclid,li_fat_id,igshid,yclid,mc_cid,mc_eid,_ga,_gl
|
|
60
|
+
# How long a request waits for another one building the same cached response
|
|
61
|
+
# before building it itself, in ms, so one that hangs can't block its URL.
|
|
62
|
+
# 0 or Infinity = wait for it. Defaults to 60000 (60s), or METADATA_TIMEOUT +
|
|
63
|
+
# LOAD_TIMEOUT + 10s when that is longer.
|
|
64
|
+
# CACHE_WAIT_TIMEOUT=60000
|
|
51
65
|
|
|
52
66
|
# Static files and prerendered pages are kept in memory after their first
|
|
53
67
|
# request (Bun only; ignored on Cloudflare Workers). Total budget in bytes,
|
|
@@ -56,13 +70,14 @@ PUBLIC_STATIC_APP_NAME=My Bosia App
|
|
|
56
70
|
# Largest file kept in memory, in bytes. Defaults to 1048576 (1MB).
|
|
57
71
|
# ASSET_CACHE_MAX_FILE_BYTES=1048576
|
|
58
72
|
|
|
59
|
-
# Timeout for load() functions (layout + page) in milliseconds. Defaults to
|
|
60
|
-
#
|
|
61
|
-
#
|
|
73
|
+
# Timeout for load() functions (layout + page) in milliseconds. Defaults to 30000 (30s).
|
|
74
|
+
# A page's time includes its `await parent()`. Bun drops a silent connection after
|
|
75
|
+
# IDLE_TIMEOUT (10s): raise it too for slower loaders. Set to 0 or Infinity to disable.
|
|
76
|
+
# LOAD_TIMEOUT=30000
|
|
62
77
|
|
|
63
|
-
# Timeout for metadata() functions in milliseconds. Defaults to
|
|
78
|
+
# Timeout for metadata() functions in milliseconds. Defaults to 10000 (10s).
|
|
64
79
|
# Set to 0 or Infinity to disable.
|
|
65
|
-
# METADATA_TIMEOUT=
|
|
80
|
+
# METADATA_TIMEOUT=10000
|
|
66
81
|
|
|
67
82
|
# Timeout for prerender fetches during build in milliseconds. Defaults to 5000 (5s).
|
|
68
83
|
# Set to 0 or Infinity to disable.
|
|
@@ -15,6 +15,20 @@ BODY_SIZE_LIMIT=512K
|
|
|
15
15
|
# Per-user pages stay isolated. Disable per-route with `export const cache = false`.
|
|
16
16
|
# CACHE_KEYS=session,sid,auth,token,jwt,Authorization
|
|
17
17
|
# CACHE_MAX_ENTRIES=500
|
|
18
|
+
# Memory for all cached responses together, in bytes (0 = entry count only).
|
|
19
|
+
# CACHE_MAX_BYTES=104857600
|
|
20
|
+
# Query params left out of the page cache key: a link with ?utm_source=… or
|
|
21
|
+
# ?fbclid=… gets the cached page of the same URL without them, instead of a new
|
|
22
|
+
# render per ad click. Comma-separated; `name*` matches a prefix; `none` turns
|
|
23
|
+
# it off. Without that cached page, or when load()/metadata() reads one of
|
|
24
|
+
# these params, the full URL is cached on its own, as before.
|
|
25
|
+
# Defaults to the list below. Setting it replaces the list.
|
|
26
|
+
# CACHE_IGNORE_PARAMS=utm_*,fbclid,gclid,gbraid,wbraid,dclid,msclkid,twclid,ttclid,li_fat_id,igshid,yclid,mc_cid,mc_eid,_ga,_gl
|
|
27
|
+
# How long a request waits for another one building the same cached response
|
|
28
|
+
# before building it itself, in ms, so one that hangs can't block its URL.
|
|
29
|
+
# 0 or Infinity = wait for it. Defaults to 60000 (60s), or METADATA_TIMEOUT +
|
|
30
|
+
# LOAD_TIMEOUT + 10s when that is longer.
|
|
31
|
+
# CACHE_WAIT_TIMEOUT=60000
|
|
18
32
|
|
|
19
33
|
# Static files and prerendered pages are kept in memory after their first
|
|
20
34
|
# request (Bun only; ignored on Cloudflare Workers). Total budget in bytes,
|
|
@@ -59,13 +73,14 @@ CORS_ALLOWED_ORIGINS=
|
|
|
59
73
|
# Default: 86400 (24 hours)
|
|
60
74
|
# CORS_MAX_AGE=86400
|
|
61
75
|
|
|
62
|
-
# Timeout for load() functions (layout + page) in milliseconds. Defaults to
|
|
63
|
-
#
|
|
64
|
-
#
|
|
76
|
+
# Timeout for load() functions (layout + page) in milliseconds. Defaults to 30000 (30s).
|
|
77
|
+
# A page's time includes its `await parent()`. Bun drops a silent connection after
|
|
78
|
+
# IDLE_TIMEOUT (10s): raise it too for slower loaders. Set to 0 or Infinity to disable.
|
|
79
|
+
# LOAD_TIMEOUT=30000
|
|
65
80
|
|
|
66
|
-
# Timeout for metadata() functions in milliseconds. Defaults to
|
|
81
|
+
# Timeout for metadata() functions in milliseconds. Defaults to 10000 (10s).
|
|
67
82
|
# Set to 0 or Infinity to disable.
|
|
68
|
-
# METADATA_TIMEOUT=
|
|
83
|
+
# METADATA_TIMEOUT=10000
|
|
69
84
|
|
|
70
85
|
# Timeout for prerender fetches during build in milliseconds. Defaults to 5000 (5s).
|
|
71
86
|
# Set to 0 or Infinity to disable.
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { sequence } from "bosia";
|
|
2
1
|
import type { Handle } from "bosia";
|
|
3
2
|
|
|
4
3
|
// Sets locals that every loader and API handler can read
|
|
@@ -8,14 +7,6 @@ const authHandle: Handle = async ({ event, resolve }) => {
|
|
|
8
7
|
return resolve(event);
|
|
9
8
|
};
|
|
10
9
|
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const res = await resolve(event);
|
|
15
|
-
const ms = Date.now() - start;
|
|
16
|
-
console.log(`[${event.request.method}] ${event.url.pathname} ${res.status} (${ms}ms)`);
|
|
17
|
-
res.headers.set("X-Response-Time", `${ms}ms`);
|
|
18
|
-
return res;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const handle = sequence(authHandle, loggingHandle);
|
|
10
|
+
// Need an access log? Let nginx/Caddy keep it, or add `accessLog()` from
|
|
11
|
+
// "bosia/plugins/access-log" to bosia.config.ts.
|
|
12
|
+
export const handle = authHandle;
|
|
@@ -18,14 +18,6 @@ const guardHandle: Handle = async ({ event, resolve }) => {
|
|
|
18
18
|
return resolve(event);
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const res = await resolve(event);
|
|
25
|
-
const ms = Date.now() - start;
|
|
26
|
-
console.log(`[${event.request.method}] ${event.url.pathname} ${res.status} (${ms}ms)`);
|
|
27
|
-
res.headers.set("X-Response-Time", `${ms}ms`);
|
|
28
|
-
return res;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export const handle = sequence(dbHandle, authHandle, guardHandle, loggingHandle);
|
|
21
|
+
// Need an access log? Let nginx/Caddy keep it, or add `accessLog()` from
|
|
22
|
+
// "bosia/plugins/access-log" to bosia.config.ts.
|
|
23
|
+
export const handle = sequence(dbHandle, authHandle, guardHandle);
|
|
@@ -18,14 +18,6 @@ const guardHandle: Handle = async ({ event, resolve }) => {
|
|
|
18
18
|
return resolve(event);
|
|
19
19
|
};
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const res = await resolve(event);
|
|
25
|
-
const ms = Date.now() - start;
|
|
26
|
-
console.log(`[${event.request.method}] ${event.url.pathname} ${res.status} (${ms}ms)`);
|
|
27
|
-
res.headers.set("X-Response-Time", `${ms}ms`);
|
|
28
|
-
return res;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export const handle = sequence(dbHandle, authHandle, guardHandle, loggingHandle);
|
|
21
|
+
// Need an access log? Let nginx/Caddy keep it, or add `accessLog()` from
|
|
22
|
+
// "bosia/plugins/access-log" to bosia.config.ts.
|
|
23
|
+
export const handle = sequence(dbHandle, authHandle, guardHandle);
|