@qwik.dev/router 2.0.0-beta.39 → 2.0.0-beta.40

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.
Files changed (40) hide show
  1. package/lib/adapters/azure-swa/vite/index.mjs +45 -54
  2. package/lib/adapters/bun-server/vite/index.mjs +16 -22
  3. package/lib/adapters/cloud-run/vite/index.mjs +15 -19
  4. package/lib/adapters/cloudflare-pages/vite/index.mjs +46 -67
  5. package/lib/adapters/deno-server/vite/index.mjs +25 -39
  6. package/lib/adapters/netlify-edge/vite/index.mjs +50 -76
  7. package/lib/adapters/node-server/vite/index.mjs +16 -22
  8. package/lib/adapters/shared/vite/index.mjs +271 -360
  9. package/lib/adapters/ssg/vite/index.mjs +11 -15
  10. package/lib/adapters/vercel-edge/vite/index.mjs +74 -95
  11. package/lib/chunks/dev-preloaded-route-loader.mjs +2 -3
  12. package/lib/chunks/format.mjs +16 -23
  13. package/lib/chunks/fs.mjs +93 -106
  14. package/lib/chunks/head.qwik.mjs +1174 -1382
  15. package/lib/chunks/http-error.qwik.mjs +20 -28
  16. package/lib/chunks/pathname.mjs +50 -69
  17. package/lib/chunks/request-body-limit.mjs +25 -35
  18. package/lib/chunks/request-path.mjs +44 -55
  19. package/lib/chunks/routes.mjs +20 -41
  20. package/lib/chunks/server-error.mjs +15 -18
  21. package/lib/chunks/system.mjs +258 -326
  22. package/lib/chunks/url.mjs +56 -58
  23. package/lib/chunks/user-response.mjs +1616 -1804
  24. package/lib/chunks/worker-thread.mjs +254 -307
  25. package/lib/index.qwik.mjs +1637 -1918
  26. package/lib/middleware/aws-lambda/index.mjs +44 -52
  27. package/lib/middleware/azure-swa/index.mjs +85 -94
  28. package/lib/middleware/bun/index.mjs +118 -138
  29. package/lib/middleware/cloudflare-pages/index.mjs +83 -96
  30. package/lib/middleware/deno/index.mjs +104 -125
  31. package/lib/middleware/firebase/index.mjs +21 -25
  32. package/lib/middleware/netlify-edge/index.mjs +63 -71
  33. package/lib/middleware/node/index.mjs +297 -357
  34. package/lib/middleware/request-handler/index.mjs +110 -133
  35. package/lib/middleware/vercel-edge/index.mjs +82 -98
  36. package/lib/service-worker/index.mjs +12 -3
  37. package/lib/ssg/index.mjs +249 -289
  38. package/lib/vite/index.mjs +2344 -3030
  39. package/package.json +5 -5
  40. package/lib/chunks/use-functions.qwik.mjs +0 -23
@@ -1,373 +1,313 @@
1
- import { isDev } from '@qwik.dev/core';
2
- import { setServerPlatform } from '@qwik.dev/core/server';
3
- import { isStaticPath, requestHandler } from '@qwik.dev/router/middleware/request-handler';
4
- import { createReadStream } from 'node:fs';
5
- import { join, basename, extname } from 'node:path';
6
- import { fileURLToPath } from 'node:url';
7
- import { n as normalizeRequestUrl, M as MIME_TYPES } from '../../chunks/url.mjs';
8
- import { d as devPreloadedRouteLoaders } from '../../chunks/dev-preloaded-route-loader.mjs';
9
- import { Http2ServerRequest } from 'node:http2';
10
- import { D as DEFAULT_REQUEST_BODY_LIMIT, v as validateRequestBodyLimit, R as RequestBodyLimitError } from '../../chunks/request-body-limit.mjs';
11
-
1
+ import { n as MIME_TYPES, t as normalizeRequestUrl } from "../../chunks/url.mjs";
2
+ import { i as validateRequestBodyLimit, n as RequestBodyLimitError, t as DEFAULT_REQUEST_BODY_LIMIT } from "../../chunks/request-body-limit.mjs";
3
+ import { t as devPreloadedRouteLoaders } from "../../chunks/dev-preloaded-route-loader.mjs";
4
+ import { isDev } from "@qwik.dev/core";
5
+ import { setServerPlatform } from "@qwik.dev/core/server";
6
+ import { createReadStream } from "node:fs";
7
+ import { basename, extname, join } from "node:path";
8
+ import { isStaticPath, requestHandler } from "@qwik.dev/router/middleware/request-handler";
9
+ import { fileURLToPath } from "node:url";
10
+ import { Http2ServerRequest } from "node:http2";
12
11
  function fallbackOrigin(req) {
13
- const { PROTOCOL_HEADER, HOST_HEADER } = process.env;
14
- const headers = req.headers;
15
- const protocol = PROTOCOL_HEADER && headers[PROTOCOL_HEADER] || (req.socket.encrypted || req.connection.encrypted ? "https" : "http");
16
- const hostHeader = HOST_HEADER ?? (req instanceof Http2ServerRequest ? ":authority" : "host");
17
- const host = headers[hostHeader];
18
- return `${protocol}://${host}`;
12
+ const { PROTOCOL_HEADER, HOST_HEADER } = process.env;
13
+ const headers = req.headers;
14
+ return `${PROTOCOL_HEADER && headers[PROTOCOL_HEADER] || (req.socket.encrypted || req.connection.encrypted ? "https" : "http")}://${headers[HOST_HEADER ?? (req instanceof Http2ServerRequest ? ":authority" : "host")]}`;
19
15
  }
20
16
  function computeOrigin(req, opts) {
21
- return opts?.getOrigin?.(req) ?? opts?.origin ?? process.env.ORIGIN ?? fallbackOrigin(req);
17
+ return opts?.getOrigin?.(req) ?? opts?.origin ?? process.env.ORIGIN ?? fallbackOrigin(req);
22
18
  }
23
19
  function isClientAbortWriteError(error) {
24
- if (!(error instanceof Error)) {
25
- return false;
26
- }
27
- const code = error.code;
28
- if (code === "EPIPE" || code === "ECONNRESET" || code === "ERR_STREAM_DESTROYED" || code === "ERR_STREAM_WRITE_AFTER_END") {
29
- return true;
30
- }
31
- return false;
20
+ if (!(error instanceof Error)) return false;
21
+ const code = error.code;
22
+ if (code === "EPIPE" || code === "ECONNRESET" || code === "ERR_STREAM_DESTROYED" || code === "ERR_STREAM_WRITE_AFTER_END") return true;
23
+ return false;
32
24
  }
33
- const invalidHeadersPattern = /^:(method|scheme|authority|path)$/i;
25
+ var invalidHeadersPattern = /^:(method|scheme|authority|path)$/i;
34
26
  function normalizeUrl(url, base) {
35
- return normalizeRequestUrl(url, base);
27
+ return normalizeRequestUrl(url, base);
36
28
  }
37
29
  function getUrl(req, origin) {
38
- return normalizeUrl(req.originalUrl || req.url || "/", origin);
30
+ return normalizeUrl(req.originalUrl || req.url || "/", origin);
39
31
  }
40
32
  function createNodeResponseSink(res) {
41
- let closed = res.closed || res.destroyed;
42
- let responseError;
43
- let resolveClosed;
44
- const closedPromise = closed ? Promise.resolve() : new Promise((resolve) => {
45
- resolveClosed = resolve;
46
- res.once("close", () => {
47
- closed = true;
48
- resolve();
49
- });
50
- });
51
- res.on("error", (error) => {
52
- if (responseError === void 0) {
53
- responseError = error;
54
- }
55
- if (!closed) {
56
- closed = true;
57
- resolveClosed();
58
- }
59
- });
60
- const shouldPropagateResponseError = () => responseError !== void 0 && !isClientAbortWriteError(responseError);
61
- const write = (chunk) => {
62
- if (closed || res.closed || res.destroyed) {
63
- if (shouldPropagateResponseError()) {
64
- return Promise.reject(responseError);
65
- }
66
- return;
67
- }
68
- return new Promise((resolve, reject) => {
69
- let settled = false;
70
- let onDrain;
71
- const cleanupDrain = () => {
72
- if (onDrain) {
73
- res.off("drain", onDrain);
74
- onDrain = void 0;
75
- }
76
- };
77
- const finish = () => {
78
- if (settled) {
79
- return;
80
- }
81
- settled = true;
82
- cleanupDrain();
83
- setImmediate(resolve);
84
- };
85
- const finishClosed = () => {
86
- closed = true;
87
- finish();
88
- };
89
- const fail = (error) => {
90
- if (settled) {
91
- return;
92
- }
93
- settled = true;
94
- closed = true;
95
- cleanupDrain();
96
- reject(error);
97
- };
98
- closedPromise.then(() => {
99
- if (shouldPropagateResponseError()) {
100
- fail(responseError);
101
- return;
102
- }
103
- finish();
104
- });
105
- let ok;
106
- try {
107
- ok = res.write(chunk, (error) => {
108
- if (error) {
109
- if (isClientAbortWriteError(error)) {
110
- finishClosed();
111
- return;
112
- }
113
- fail(error);
114
- return;
115
- }
116
- finish();
117
- });
118
- } catch (error) {
119
- if (isClientAbortWriteError(error)) {
120
- finishClosed();
121
- return;
122
- }
123
- fail(error);
124
- return;
125
- }
126
- if (settled) {
127
- return;
128
- }
129
- if (ok) {
130
- finish();
131
- } else {
132
- onDrain = () => {
133
- onDrain = void 0;
134
- finish();
135
- };
136
- res.once("drain", onDrain);
137
- }
138
- });
139
- };
140
- const close = () => {
141
- if (closed || res.closed || res.destroyed) {
142
- if (shouldPropagateResponseError()) {
143
- return Promise.reject(responseError);
144
- }
145
- return;
146
- }
147
- return new Promise((resolve, reject) => {
148
- let settled = false;
149
- const finish = () => {
150
- if (settled) {
151
- return;
152
- }
153
- settled = true;
154
- closed = true;
155
- resolve();
156
- };
157
- const fail = (error) => {
158
- if (settled) {
159
- return;
160
- }
161
- settled = true;
162
- closed = true;
163
- reject(error);
164
- };
165
- closedPromise.then(() => {
166
- if (shouldPropagateResponseError()) {
167
- fail(responseError);
168
- return;
169
- }
170
- finish();
171
- });
172
- res.once("finish", finish);
173
- try {
174
- res.end();
175
- } catch (error) {
176
- if (isClientAbortWriteError(error)) {
177
- finish();
178
- return;
179
- }
180
- fail(error);
181
- }
182
- });
183
- };
184
- return {
185
- write,
186
- close
187
- };
33
+ let closed = res.closed || res.destroyed;
34
+ let responseError;
35
+ let resolveClosed;
36
+ const closedPromise = closed ? Promise.resolve() : new Promise((resolve) => {
37
+ resolveClosed = resolve;
38
+ res.once("close", () => {
39
+ closed = true;
40
+ resolve();
41
+ });
42
+ });
43
+ res.on("error", (error) => {
44
+ if (responseError === void 0) responseError = error;
45
+ if (!closed) {
46
+ closed = true;
47
+ resolveClosed();
48
+ }
49
+ });
50
+ const shouldPropagateResponseError = () => responseError !== void 0 && !isClientAbortWriteError(responseError);
51
+ const write = (chunk) => {
52
+ if (closed || res.closed || res.destroyed) {
53
+ if (shouldPropagateResponseError()) return Promise.reject(responseError);
54
+ return;
55
+ }
56
+ return new Promise((resolve, reject) => {
57
+ let settled = false;
58
+ let onDrain;
59
+ const cleanupDrain = () => {
60
+ if (onDrain) {
61
+ res.off("drain", onDrain);
62
+ onDrain = void 0;
63
+ }
64
+ };
65
+ const finish = () => {
66
+ if (settled) return;
67
+ settled = true;
68
+ cleanupDrain();
69
+ setImmediate(resolve);
70
+ };
71
+ const finishClosed = () => {
72
+ closed = true;
73
+ finish();
74
+ };
75
+ const fail = (error) => {
76
+ if (settled) return;
77
+ settled = true;
78
+ closed = true;
79
+ cleanupDrain();
80
+ reject(error);
81
+ };
82
+ closedPromise.then(() => {
83
+ if (shouldPropagateResponseError()) {
84
+ fail(responseError);
85
+ return;
86
+ }
87
+ finish();
88
+ });
89
+ let ok;
90
+ try {
91
+ ok = res.write(chunk, (error) => {
92
+ if (error) {
93
+ if (isClientAbortWriteError(error)) {
94
+ finishClosed();
95
+ return;
96
+ }
97
+ fail(error);
98
+ return;
99
+ }
100
+ finish();
101
+ });
102
+ } catch (error) {
103
+ if (isClientAbortWriteError(error)) {
104
+ finishClosed();
105
+ return;
106
+ }
107
+ fail(error);
108
+ return;
109
+ }
110
+ if (settled) return;
111
+ if (ok) finish();
112
+ else {
113
+ onDrain = () => {
114
+ onDrain = void 0;
115
+ finish();
116
+ };
117
+ res.once("drain", onDrain);
118
+ }
119
+ });
120
+ };
121
+ const close = () => {
122
+ if (closed || res.closed || res.destroyed) {
123
+ if (shouldPropagateResponseError()) return Promise.reject(responseError);
124
+ return;
125
+ }
126
+ return new Promise((resolve, reject) => {
127
+ let settled = false;
128
+ const finish = () => {
129
+ if (settled) return;
130
+ settled = true;
131
+ closed = true;
132
+ resolve();
133
+ };
134
+ const fail = (error) => {
135
+ if (settled) return;
136
+ settled = true;
137
+ closed = true;
138
+ reject(error);
139
+ };
140
+ closedPromise.then(() => {
141
+ if (shouldPropagateResponseError()) {
142
+ fail(responseError);
143
+ return;
144
+ }
145
+ finish();
146
+ });
147
+ res.once("finish", finish);
148
+ try {
149
+ res.end();
150
+ } catch (error) {
151
+ if (isClientAbortWriteError(error)) {
152
+ finish();
153
+ return;
154
+ }
155
+ fail(error);
156
+ }
157
+ });
158
+ };
159
+ return {
160
+ write,
161
+ close
162
+ };
188
163
  }
189
164
  async function fromNodeHttp(url, req, res, mode, getClientConn, requestBodyLimit = DEFAULT_REQUEST_BODY_LIMIT) {
190
- validateRequestBodyLimit(requestBodyLimit);
191
- const requestHeaders = new Headers();
192
- const nodeRequestHeaders = req.headers;
193
- try {
194
- for (const [key, value] of Object.entries(nodeRequestHeaders)) {
195
- if (invalidHeadersPattern.test(key)) {
196
- continue;
197
- }
198
- if (typeof value === "string") {
199
- requestHeaders.set(key, value);
200
- } else if (Array.isArray(value)) {
201
- for (const v of value) {
202
- requestHeaders.append(key, v);
203
- }
204
- }
205
- }
206
- } catch (err) {
207
- console.error(err);
208
- }
209
- const getRequestBody = async function* () {
210
- let received = 0;
211
- for await (const chunk of req) {
212
- const byteLength = typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.byteLength;
213
- if (byteLength > requestBodyLimit - received) {
214
- req.resume();
215
- throw new RequestBodyLimitError(requestBodyLimit);
216
- }
217
- received += byteLength;
218
- yield chunk;
219
- }
220
- };
221
- const body = req.method === "HEAD" || req.method === "GET" ? void 0 : getRequestBody();
222
- const controller = new AbortController();
223
- const abort = () => {
224
- controller.abort();
225
- };
226
- const options = {
227
- method: req.method,
228
- headers: requestHeaders,
229
- body,
230
- signal: controller.signal,
231
- duplex: "half"
232
- };
233
- req.on("aborted", abort);
234
- req.on("error", abort);
235
- res.on("close", abort);
236
- res.on("error", abort);
237
- const serverRequestEv = {
238
- mode,
239
- url,
240
- request: new Request(url.href, options),
241
- env: {
242
- get(key) {
243
- return process.env[key];
244
- }
245
- },
246
- getWritableStream: (status, headers, cookies, resolve) => {
247
- res.statusCode = status;
248
- const sink = createNodeResponseSink(res);
249
- try {
250
- for (const [key, value] of headers) {
251
- if (invalidHeadersPattern.test(key)) {
252
- continue;
253
- }
254
- res.setHeader(key, value);
255
- }
256
- const cookieHeaders = cookies.headers();
257
- if (cookieHeaders.length > 0) {
258
- res.setHeader("Set-Cookie", cookieHeaders);
259
- }
260
- } catch (err) {
261
- console.error(err);
262
- }
263
- resolve(true);
264
- return new WritableStream({
265
- write(chunk) {
266
- return sink.write(chunk);
267
- },
268
- close() {
269
- return sink.close();
270
- }
271
- });
272
- },
273
- getClientConn: () => {
274
- return getClientConn ? getClientConn(req) : {
275
- ip: req.socket.remoteAddress
276
- };
277
- },
278
- platform: {
279
- ssr: true,
280
- incomingMessage: req,
281
- node: process.versions.node
282
- },
283
- locale: void 0
284
- };
285
- return serverRequestEv;
165
+ validateRequestBodyLimit(requestBodyLimit);
166
+ const requestHeaders = new Headers();
167
+ const nodeRequestHeaders = req.headers;
168
+ try {
169
+ for (const [key, value] of Object.entries(nodeRequestHeaders)) {
170
+ if (invalidHeadersPattern.test(key)) continue;
171
+ if (typeof value === "string") requestHeaders.set(key, value);
172
+ else if (Array.isArray(value)) for (const v of value) requestHeaders.append(key, v);
173
+ }
174
+ } catch (err) {
175
+ console.error(err);
176
+ }
177
+ const getRequestBody = async function* () {
178
+ let received = 0;
179
+ for await (const chunk of req) {
180
+ const byteLength = typeof chunk === "string" ? Buffer.byteLength(chunk) : chunk.byteLength;
181
+ if (byteLength > requestBodyLimit - received) {
182
+ req.resume();
183
+ throw new RequestBodyLimitError(requestBodyLimit);
184
+ }
185
+ received += byteLength;
186
+ yield chunk;
187
+ }
188
+ };
189
+ const body = req.method === "HEAD" || req.method === "GET" ? void 0 : getRequestBody();
190
+ const controller = new AbortController();
191
+ const abort = () => {
192
+ controller.abort();
193
+ };
194
+ const options = {
195
+ method: req.method,
196
+ headers: requestHeaders,
197
+ body,
198
+ signal: controller.signal,
199
+ duplex: "half"
200
+ };
201
+ req.on("aborted", abort);
202
+ req.on("error", abort);
203
+ res.on("close", abort);
204
+ res.on("error", abort);
205
+ return {
206
+ mode,
207
+ url,
208
+ request: new Request(url.href, options),
209
+ env: { get(key) {
210
+ return process.env[key];
211
+ } },
212
+ getWritableStream: (status, headers, cookies, resolve) => {
213
+ res.statusCode = status;
214
+ const sink = createNodeResponseSink(res);
215
+ try {
216
+ for (const [key, value] of headers) {
217
+ if (invalidHeadersPattern.test(key)) continue;
218
+ res.setHeader(key, value);
219
+ }
220
+ const cookieHeaders = cookies.headers();
221
+ if (cookieHeaders.length > 0) res.setHeader("Set-Cookie", cookieHeaders);
222
+ } catch (err) {
223
+ console.error(err);
224
+ }
225
+ resolve(true);
226
+ return new WritableStream({
227
+ write(chunk) {
228
+ return sink.write(chunk);
229
+ },
230
+ close() {
231
+ return sink.close();
232
+ }
233
+ });
234
+ },
235
+ getClientConn: () => {
236
+ return getClientConn ? getClientConn(req) : { ip: req.socket.remoteAddress };
237
+ },
238
+ platform: {
239
+ ssr: true,
240
+ incomingMessage: req,
241
+ node: process.versions.node
242
+ },
243
+ locale: void 0
244
+ };
286
245
  }
287
-
288
- function createQwikRouter(opts) {
289
- if (opts.manifest) {
290
- setServerPlatform(opts.manifest);
291
- }
292
- const staticFolder = opts.static?.root ?? join(fileURLToPath(import.meta.url), "..", "..", "dist");
293
- const router = async (req, res, next, limits = {}) => {
294
- try {
295
- const origin = computeOrigin(req, opts);
296
- let requestBodyLimit = opts.requestBodyLimit;
297
- if (limits?.bodyLimit !== void 0) {
298
- if (requestBodyLimit === void 0) {
299
- requestBodyLimit = limits.bodyLimit;
300
- } else {
301
- requestBodyLimit = Math.min(requestBodyLimit, limits.bodyLimit);
302
- }
303
- }
304
- const serverRequestEv = await fromNodeHttp(getUrl(req, origin), req, res, "server", opts.getClientConn, requestBodyLimit);
305
- if (isDev && opts.platform) {
306
- Object.assign(serverRequestEv.platform, opts.platform);
307
- }
308
- if (isDev) {
309
- const loader = devPreloadedRouteLoaders.get(req);
310
- if (loader) {
311
- devPreloadedRouteLoaders.set(serverRequestEv.request, loader);
312
- devPreloadedRouteLoaders.delete(req);
313
- }
314
- }
315
- const handled = await requestHandler(serverRequestEv, opts);
316
- if (handled) {
317
- const err = await handled.completion;
318
- if (handled.requestEv.headersSent) {
319
- return;
320
- }
321
- if (err) {
322
- throw err;
323
- }
324
- }
325
- next();
326
- } catch (e) {
327
- console.error(e);
328
- next(e);
329
- }
330
- };
331
- const notFound = async (_req, _res, next) => next();
332
- const staticFile = async (req, res, next) => {
333
- try {
334
- const origin = computeOrigin(req, opts);
335
- const url = getUrl(req, origin);
336
- if (isStaticPath(req.method || "GET", url)) {
337
- const pathname = url.pathname;
338
- let filePath;
339
- if (basename(pathname).includes(".")) {
340
- filePath = join(staticFolder, pathname);
341
- } else if (!globalThis.__NO_TRAILING_SLASH__) {
342
- filePath = join(staticFolder, pathname + "index.html");
343
- } else {
344
- filePath = join(staticFolder, pathname, "index.html");
345
- }
346
- const ext = extname(filePath).replace(/^\./, "");
347
- const stream = createReadStream(filePath);
348
- stream.on("error", next);
349
- const contentType = MIME_TYPES[ext];
350
- if (contentType) {
351
- res.setHeader("Content-Type", contentType);
352
- }
353
- if (opts.static?.cacheControl) {
354
- res.setHeader("Cache-Control", opts.static.cacheControl);
355
- }
356
- stream.pipe(res);
357
- return;
358
- }
359
- return next();
360
- } catch (e) {
361
- console.error(e);
362
- next(e);
363
- }
364
- };
365
- return {
366
- router,
367
- notFound,
368
- staticFile
369
- };
246
+ /** @public */ function createQwikRouter(opts) {
247
+ if (opts.manifest) setServerPlatform(opts.manifest);
248
+ const staticFolder = opts.static?.root ?? join(fileURLToPath(import.meta.url), "..", "..", "dist");
249
+ const router = async (req, res, next, limits = {}) => {
250
+ try {
251
+ const origin = computeOrigin(req, opts);
252
+ let requestBodyLimit = opts.requestBodyLimit;
253
+ if (limits?.bodyLimit !== void 0) {
254
+ if (requestBodyLimit === void 0) requestBodyLimit = limits.bodyLimit;
255
+ else requestBodyLimit = Math.min(requestBodyLimit, limits.bodyLimit);
256
+ }
257
+ const serverRequestEv = await fromNodeHttp(getUrl(req, origin), req, res, "server", opts.getClientConn, requestBodyLimit);
258
+ if (isDev && opts.platform) Object.assign(serverRequestEv.platform, opts.platform);
259
+ if (isDev) {
260
+ const loader = devPreloadedRouteLoaders.get(req);
261
+ if (loader) {
262
+ devPreloadedRouteLoaders.set(serverRequestEv.request, loader);
263
+ devPreloadedRouteLoaders.delete(req);
264
+ }
265
+ }
266
+ const handled = await requestHandler(serverRequestEv, opts);
267
+ if (handled) {
268
+ const err = await handled.completion;
269
+ if (handled.requestEv.headersSent) return;
270
+ if (err) throw err;
271
+ }
272
+ next();
273
+ } catch (e) {
274
+ console.error(e);
275
+ next(e);
276
+ }
277
+ };
278
+ /** @deprecated `router` handles 404 responses. Will be removed in V3. */ const notFound = async (_req, _res, next) => next();
279
+ const staticFile = async (req, res, next) => {
280
+ try {
281
+ const url = getUrl(req, computeOrigin(req, opts));
282
+ if (isStaticPath(req.method || "GET", url)) {
283
+ const pathname = url.pathname;
284
+ let filePath;
285
+ if (basename(pathname).includes(".")) filePath = join(staticFolder, pathname);
286
+ else if (!globalThis.__NO_TRAILING_SLASH__) filePath = join(staticFolder, pathname + "index.html");
287
+ else filePath = join(staticFolder, pathname, "index.html");
288
+ const ext = extname(filePath).replace(/^\./, "");
289
+ const stream = createReadStream(filePath);
290
+ stream.on("error", next);
291
+ const contentType = MIME_TYPES[ext];
292
+ if (contentType) res.setHeader("Content-Type", contentType);
293
+ if (opts.static?.cacheControl) res.setHeader("Cache-Control", opts.static.cacheControl);
294
+ stream.pipe(res);
295
+ return;
296
+ }
297
+ return next();
298
+ } catch (e) {
299
+ console.error(e);
300
+ next(e);
301
+ }
302
+ };
303
+ return {
304
+ router,
305
+ notFound,
306
+ staticFile
307
+ };
370
308
  }
371
- const createQwikCity = createQwikRouter;
372
-
309
+ /**
310
+ * @deprecated Use `createQwikRouter` instead. Will be removed in V3
311
+ * @public
312
+ */ var createQwikCity = createQwikRouter;
373
313
  export { createQwikCity, createQwikRouter };