@qwik.dev/router 2.0.0-beta.35 → 2.0.0-beta.37
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/lib/adapters/cloudflare-pages/vite/index.mjs +2 -4
- package/lib/adapters/shared/vite/index.mjs +26 -23
- package/lib/chunks/action-handler.mjs +782 -0
- package/lib/chunks/deepFreeze.qwik.mjs +591 -1
- package/lib/chunks/format.mjs +31 -0
- package/lib/chunks/fs.mjs +4 -6
- package/lib/chunks/{routing.qwik.mjs → head.qwik.mjs} +299 -416
- package/lib/chunks/http-error.qwik.mjs +2 -2
- package/lib/chunks/not-found-wrapper.qwik.mjs +2 -2
- package/lib/chunks/pathname.mjs +3 -32
- package/lib/chunks/request-path.mjs +60 -0
- package/lib/chunks/system.mjs +6 -7
- package/lib/chunks/use-functions.qwik.mjs +3 -15
- package/lib/chunks/worker-thread.qwik.mjs +436 -425
- package/lib/index.d.ts +180 -13
- package/lib/index.qwik.mjs +640 -447
- package/lib/middleware/aws-lambda/index.mjs +2 -1
- package/lib/middleware/request-handler/index.d.ts +56 -16
- package/lib/middleware/request-handler/index.mjs +198 -754
- package/lib/ssg/index.d.ts +3 -3
- package/lib/ssg/index.mjs +4 -3
- package/lib/vite/index.d.ts +15 -0
- package/lib/vite/index.mjs +145 -23
- package/package.json +3 -3
- package/lib/chunks/redirect-handler.mjs +0 -6
|
@@ -1,12 +1,50 @@
|
|
|
1
|
+
import { e as ensureSlash } from './pathname.mjs';
|
|
2
|
+
import { isDev, _deserialize, _verifySerializable, _serialize, _getAsyncLocalStorage } from '@qwik.dev/core/internal';
|
|
1
3
|
import { parentPort } from 'node:worker_threads';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
4
|
+
import { v as deepFreeze, o as getRouteLoaderValues, p as loadRouteLoader, n as getRouteLoaderCtx, q as setRouteLoaders, A as AbortMessage$1, w as getRouteLoaders } from './deepFreeze.qwik.mjs';
|
|
5
|
+
import { Q as QLoaderId$1, I as IsQLoader$1 } from './request-path.mjs';
|
|
6
|
+
import { withLocale, isDev as isDev$1, inlinedQrl } from '@qwik.dev/core';
|
|
7
|
+
import { j as jsonRequestWrapper, l as loaderHandler, f as actionHandler, h as hash, n as normalizeETag, p as performETagMatch, s as setETagHeader } from './action-handler.mjs';
|
|
5
8
|
import { isServer } from '@qwik.dev/core/build';
|
|
6
|
-
|
|
9
|
+
|
|
10
|
+
const IsQLoader = "@isQLoader";
|
|
11
|
+
const IsQAction = "@isQAction";
|
|
12
|
+
const QLoaderId = "@loaderId";
|
|
13
|
+
const QActionId = "@actionId";
|
|
14
|
+
const LOADER_REGEX = /\/(q-loader-([^.]+)\.([^.]+)\.json)$/;
|
|
15
|
+
function recognizeRequest(pathname) {
|
|
16
|
+
if (pathname.length < 10) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const loaderMatch = pathname.match(LOADER_REGEX);
|
|
20
|
+
if (loaderMatch) {
|
|
21
|
+
return {
|
|
22
|
+
type: IsQLoader,
|
|
23
|
+
trimLength: loaderMatch[1].length + 1,
|
|
24
|
+
data: {
|
|
25
|
+
loaderId: loaderMatch[2],
|
|
26
|
+
manifestHash: loaderMatch[3]
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
function trimRecognizedInternalPathname(pathname, recognized) {
|
|
33
|
+
let trimmed = pathname.slice(0, pathname.length - recognized.trimLength) || "/";
|
|
34
|
+
if (!globalThis.__NO_TRAILING_SLASH__ && !trimmed.endsWith("/")) {
|
|
35
|
+
trimmed = ensureSlash(trimmed);
|
|
36
|
+
}
|
|
37
|
+
return trimmed;
|
|
38
|
+
}
|
|
39
|
+
function trimInternalPathname(pathname) {
|
|
40
|
+
const recognized = recognizeRequest(pathname);
|
|
41
|
+
if (recognized) {
|
|
42
|
+
return trimRecognizedInternalPathname(pathname, recognized);
|
|
43
|
+
}
|
|
44
|
+
return pathname;
|
|
45
|
+
}
|
|
7
46
|
|
|
8
47
|
const QACTION_KEY = "qaction";
|
|
9
|
-
const QLOADER_KEY = "qloaders";
|
|
10
48
|
const QFN_KEY = "qfunc";
|
|
11
49
|
const QDATA_KEY = "qdata";
|
|
12
50
|
const Q_ROUTE = "q:route";
|
|
@@ -156,10 +194,12 @@ function walkTrieKeys(root, keys) {
|
|
|
156
194
|
if (node._L) {
|
|
157
195
|
layouts.push(node._L);
|
|
158
196
|
}
|
|
159
|
-
for (
|
|
197
|
+
for (let i = 0; i < keys.length; i++) {
|
|
198
|
+
const key = keys[i];
|
|
160
199
|
let next = node[key];
|
|
161
200
|
if (!next && node._M) {
|
|
162
|
-
for (
|
|
201
|
+
for (let j = 0; j < node._M.length; j++) {
|
|
202
|
+
const group = node._M[j];
|
|
163
203
|
next = group[key];
|
|
164
204
|
if (next) {
|
|
165
205
|
if (group._L) {
|
|
@@ -182,11 +222,21 @@ function walkTrieKeys(root, keys) {
|
|
|
182
222
|
layouts
|
|
183
223
|
};
|
|
184
224
|
}
|
|
185
|
-
function collectNodeMeta(node, groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef) {
|
|
186
|
-
for (
|
|
225
|
+
function collectNodeMeta(node, groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef, loaderHashes, loaderPathsByHash, matchedPathname = "/") {
|
|
226
|
+
for (let j = 0; j < groups.length; j++) {
|
|
227
|
+
const g = groups[j];
|
|
187
228
|
if (g._L) {
|
|
188
229
|
layouts.push(g._L);
|
|
189
230
|
}
|
|
231
|
+
if (g._R && loaderHashes) {
|
|
232
|
+
loaderHashes.push(...g._R);
|
|
233
|
+
if (loaderPathsByHash) {
|
|
234
|
+
for (let i = 0; i < g._R.length; i++) {
|
|
235
|
+
const hash = g._R[i];
|
|
236
|
+
loaderPathsByHash[hash] = matchedPathname;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
190
240
|
if (g._E) {
|
|
191
241
|
errorLoaderRef.v = g._E;
|
|
192
242
|
}
|
|
@@ -200,6 +250,15 @@ function collectNodeMeta(node, groups, layouts, errorLoaderRef, notFoundLoaderRe
|
|
|
200
250
|
if (node._L) {
|
|
201
251
|
layouts.push(node._L);
|
|
202
252
|
}
|
|
253
|
+
if (node._R && loaderHashes) {
|
|
254
|
+
loaderHashes.push(...node._R);
|
|
255
|
+
if (loaderPathsByHash) {
|
|
256
|
+
for (let i = 0; i < node._R.length; i++) {
|
|
257
|
+
const hash = node._R[i];
|
|
258
|
+
loaderPathsByHash[hash] = matchedPathname;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
203
262
|
if (node._E) {
|
|
204
263
|
errorLoaderRef.v = node._E;
|
|
205
264
|
}
|
|
@@ -210,7 +269,7 @@ function collectNodeMeta(node, groups, layouts, errorLoaderRef, notFoundLoaderRe
|
|
|
210
269
|
menuLoaderRef.v = node._N;
|
|
211
270
|
}
|
|
212
271
|
}
|
|
213
|
-
function tryWildcardMatch(node, part, partLower, parts, partIndex
|
|
272
|
+
function tryWildcardMatch(node, part, partLower, parts, partIndex) {
|
|
214
273
|
let next = node._W;
|
|
215
274
|
if (next) {
|
|
216
275
|
const prefix = next._0;
|
|
@@ -221,20 +280,24 @@ function tryWildcardMatch(node, part, partLower, parts, partIndex, params) {
|
|
|
221
280
|
if (partLower.length > pre.length + suf.length && (!pre || partLower.startsWith(pre.toLowerCase())) && (!suf || partLower.endsWith(suf.toLowerCase()))) {
|
|
222
281
|
const paramName = next._P;
|
|
223
282
|
const value = part.slice(pre.length, suf ? part.length - suf.length : void 0);
|
|
224
|
-
params[paramName] = value;
|
|
225
283
|
return {
|
|
226
284
|
next,
|
|
227
285
|
routePart: `${pre}[${paramName}]${suf}`,
|
|
228
|
-
done: false
|
|
286
|
+
done: false,
|
|
287
|
+
kind: 1,
|
|
288
|
+
paramName,
|
|
289
|
+
paramValue: value
|
|
229
290
|
};
|
|
230
291
|
}
|
|
231
292
|
} else {
|
|
232
293
|
const paramName = next._P;
|
|
233
|
-
params[paramName] = part;
|
|
234
294
|
return {
|
|
235
295
|
next,
|
|
236
296
|
routePart: `[${paramName}]`,
|
|
237
|
-
done: false
|
|
297
|
+
done: false,
|
|
298
|
+
kind: 1,
|
|
299
|
+
paramName,
|
|
300
|
+
paramValue: part
|
|
238
301
|
};
|
|
239
302
|
}
|
|
240
303
|
}
|
|
@@ -242,35 +305,39 @@ function tryWildcardMatch(node, part, partLower, parts, partIndex, params) {
|
|
|
242
305
|
if (next) {
|
|
243
306
|
const paramName = next._P;
|
|
244
307
|
const restValue = parts.slice(partIndex).join("/");
|
|
245
|
-
params[paramName] = restValue;
|
|
246
308
|
return {
|
|
247
309
|
next,
|
|
248
310
|
routePart: `[...${paramName}]`,
|
|
249
|
-
done: true
|
|
311
|
+
done: true,
|
|
312
|
+
kind: 2,
|
|
313
|
+
paramName,
|
|
314
|
+
paramValue: restValue
|
|
250
315
|
};
|
|
251
316
|
}
|
|
252
317
|
return void 0;
|
|
253
318
|
}
|
|
254
|
-
function findChild(node, part, partLower, parts, partIndex
|
|
319
|
+
function findChild(node, part, partLower, parts, partIndex) {
|
|
255
320
|
const exact = node[partLower];
|
|
256
321
|
if (exact) {
|
|
257
322
|
return {
|
|
258
323
|
next: exact,
|
|
259
324
|
groups: [],
|
|
260
325
|
routePart: part,
|
|
261
|
-
done: false
|
|
326
|
+
done: false,
|
|
327
|
+
kind: 0
|
|
262
328
|
};
|
|
263
329
|
}
|
|
264
330
|
if (node._M) {
|
|
265
|
-
for (
|
|
266
|
-
const
|
|
331
|
+
for (let j = 0; j < node._M.length; j++) {
|
|
332
|
+
const group = node._M[j];
|
|
333
|
+
const groupResult = findChild(group, part, partLower, parts, partIndex);
|
|
267
334
|
if (groupResult) {
|
|
268
335
|
groupResult.groups.unshift(group);
|
|
269
336
|
return groupResult;
|
|
270
337
|
}
|
|
271
338
|
}
|
|
272
339
|
}
|
|
273
|
-
const wildcard = tryWildcardMatch(node, part, partLower, parts, partIndex
|
|
340
|
+
const wildcard = tryWildcardMatch(node, part, partLower, parts, partIndex);
|
|
274
341
|
if (wildcard) {
|
|
275
342
|
return {
|
|
276
343
|
...wildcard,
|
|
@@ -287,7 +354,8 @@ function findIndexNode(node) {
|
|
|
287
354
|
};
|
|
288
355
|
}
|
|
289
356
|
if (node._M) {
|
|
290
|
-
for (
|
|
357
|
+
for (let j = 0; j < node._M.length; j++) {
|
|
358
|
+
const group = node._M[j];
|
|
291
359
|
const result = findIndexNode(group);
|
|
292
360
|
if (result) {
|
|
293
361
|
if (result.target !== group) {
|
|
@@ -311,7 +379,8 @@ function resolveLoaders(root, node, gatheredLayouts) {
|
|
|
311
379
|
if (!targetNode._I && targetNode._G == null) {
|
|
312
380
|
const indexResult = findIndexNode(targetNode);
|
|
313
381
|
if (indexResult) {
|
|
314
|
-
for (
|
|
382
|
+
for (let j = 0; j < indexResult.groups.length; j++) {
|
|
383
|
+
const g = indexResult.groups[j];
|
|
315
384
|
if (g._L) {
|
|
316
385
|
targetLayouts.push(g._L);
|
|
317
386
|
}
|
|
@@ -344,7 +413,8 @@ function findRestNode(node) {
|
|
|
344
413
|
};
|
|
345
414
|
}
|
|
346
415
|
if (node._M) {
|
|
347
|
-
for (
|
|
416
|
+
for (let j = 0; j < node._M.length; j++) {
|
|
417
|
+
const group = node._M[j];
|
|
348
418
|
const result = findRestNode(group);
|
|
349
419
|
if (result) {
|
|
350
420
|
result.groups.unshift(group);
|
|
@@ -359,6 +429,8 @@ function matchRouteTree(root = {}, pathname) {
|
|
|
359
429
|
const params = {};
|
|
360
430
|
const routeParts = [];
|
|
361
431
|
const layouts = [];
|
|
432
|
+
const loaderHashes = [];
|
|
433
|
+
const loaderPathsByHash = {};
|
|
362
434
|
const errorLoaderRef = {
|
|
363
435
|
v: void 0
|
|
364
436
|
};
|
|
@@ -371,6 +443,13 @@ function matchRouteTree(root = {}, pathname) {
|
|
|
371
443
|
if (root._L) {
|
|
372
444
|
layouts.push(root._L);
|
|
373
445
|
}
|
|
446
|
+
if (root._R) {
|
|
447
|
+
loaderHashes.push(...root._R);
|
|
448
|
+
for (let i2 = 0; i2 < root._R.length; i2++) {
|
|
449
|
+
const hash = root._R[i2];
|
|
450
|
+
loaderPathsByHash[hash] = "/";
|
|
451
|
+
}
|
|
452
|
+
}
|
|
374
453
|
if (root._E) {
|
|
375
454
|
errorLoaderRef.v = root._E;
|
|
376
455
|
}
|
|
@@ -389,7 +468,12 @@ function matchRouteTree(root = {}, pathname) {
|
|
|
389
468
|
for (; !done && i < len; i++) {
|
|
390
469
|
const part = parts[i];
|
|
391
470
|
const partLower = part.toLowerCase();
|
|
392
|
-
const
|
|
471
|
+
const found = findChild(node, part, partLower, parts, i);
|
|
472
|
+
if (!found) {
|
|
473
|
+
matched = false;
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
const restInfo = found.kind === 1 ? findRestNode(node) : void 0;
|
|
393
477
|
if (restInfo) {
|
|
394
478
|
restFallback = {
|
|
395
479
|
aNode: restInfo.next,
|
|
@@ -405,26 +489,28 @@ function matchRouteTree(root = {}, pathname) {
|
|
|
405
489
|
layouts: [
|
|
406
490
|
...layouts
|
|
407
491
|
],
|
|
492
|
+
loaderPathsByHash: {
|
|
493
|
+
...loaderPathsByHash
|
|
494
|
+
},
|
|
408
495
|
errorLoader: errorLoaderRef.v,
|
|
409
496
|
notFoundLoader: notFoundLoaderRef.v,
|
|
410
497
|
menuLoader: menuLoaderRef.v
|
|
411
498
|
};
|
|
412
499
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
matched = false;
|
|
416
|
-
break;
|
|
500
|
+
if (found.paramName) {
|
|
501
|
+
params[found.paramName] = found.paramValue;
|
|
417
502
|
}
|
|
418
503
|
routeParts.push(found.routePart);
|
|
419
504
|
done = found.done;
|
|
420
505
|
node = found.next;
|
|
421
|
-
|
|
506
|
+
const matchedPathname = `/${parts.slice(0, found.done ? len : i + 1).join("/")}/`;
|
|
507
|
+
collectNodeMeta(node, found.groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef, loaderHashes, loaderPathsByHash, matchedPathname);
|
|
422
508
|
}
|
|
423
509
|
if (matched && !done && i === len) {
|
|
424
510
|
if (!node._I && node._G == null) {
|
|
425
511
|
const indexResult = findIndexNode(node);
|
|
426
512
|
if (indexResult) {
|
|
427
|
-
collectNodeMeta(indexResult.target, indexResult.groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef);
|
|
513
|
+
collectNodeMeta(indexResult.target, indexResult.groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef, loaderHashes, loaderPathsByHash, pathname);
|
|
428
514
|
node = indexResult.target;
|
|
429
515
|
}
|
|
430
516
|
}
|
|
@@ -448,7 +534,7 @@ function matchRouteTree(root = {}, pathname) {
|
|
|
448
534
|
const paramName = next._P;
|
|
449
535
|
params[paramName] = "";
|
|
450
536
|
routeParts.push(`[...${paramName}]`);
|
|
451
|
-
collectNodeMeta(next, restInfo.groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef);
|
|
537
|
+
collectNodeMeta(next, restInfo.groups, layouts, errorLoaderRef, notFoundLoaderRef, menuLoaderRef, loaderHashes, loaderPathsByHash, pathname);
|
|
452
538
|
node = next;
|
|
453
539
|
}
|
|
454
540
|
}
|
|
@@ -467,6 +553,9 @@ function matchRouteTree(root = {}, pathname) {
|
|
|
467
553
|
const fbLayouts = [
|
|
468
554
|
...fb.layouts
|
|
469
555
|
];
|
|
556
|
+
const fbLoaderPathsByHash = {
|
|
557
|
+
...fb.loaderPathsByHash
|
|
558
|
+
};
|
|
470
559
|
const fbErrorRef = {
|
|
471
560
|
v: fb.errorLoader
|
|
472
561
|
};
|
|
@@ -476,7 +565,8 @@ function matchRouteTree(root = {}, pathname) {
|
|
|
476
565
|
const fbMenuRef = {
|
|
477
566
|
v: fb.menuLoader
|
|
478
567
|
};
|
|
479
|
-
|
|
568
|
+
const fbLoaderHashes = [];
|
|
569
|
+
collectNodeMeta(fb.aNode, fb.groups, fbLayouts, fbErrorRef, fbNotFoundRef, fbMenuRef, fbLoaderHashes, fbLoaderPathsByHash, pathname);
|
|
480
570
|
const fbLoaders = resolveLoaders(root, fb.aNode, fbLayouts);
|
|
481
571
|
if (fbLoaders) {
|
|
482
572
|
return {
|
|
@@ -485,6 +575,8 @@ function matchRouteTree(root = {}, pathname) {
|
|
|
485
575
|
routeParts: fbRouteParts,
|
|
486
576
|
notFound: false,
|
|
487
577
|
routeBundleNames: fb.aNode._B,
|
|
578
|
+
loaderHashes: fbLoaderHashes.length > 0 ? fbLoaderHashes : void 0,
|
|
579
|
+
loaderPathsByHash: Object.keys(fbLoaderPathsByHash).length > 0 ? fbLoaderPathsByHash : void 0,
|
|
488
580
|
menuLoader: fbMenuRef.v,
|
|
489
581
|
errorLoader: fbErrorRef.v,
|
|
490
582
|
notFoundLoader: fbNotFoundRef.v
|
|
@@ -504,17 +596,29 @@ function matchRouteTree(root = {}, pathname) {
|
|
|
504
596
|
routeParts,
|
|
505
597
|
notFound: true,
|
|
506
598
|
routeBundleNames: void 0,
|
|
599
|
+
loaderHashes: void 0,
|
|
600
|
+
loaderPathsByHash: void 0,
|
|
507
601
|
menuLoader: menuLoaderRef.v,
|
|
508
602
|
errorLoader: errorLoaderRef.v,
|
|
509
603
|
notFoundLoader: notFoundLoaderRef.v
|
|
510
604
|
};
|
|
511
605
|
}
|
|
606
|
+
if (node._R) {
|
|
607
|
+
loaderHashes.push(...node._R);
|
|
608
|
+
const matchedPathname = ensureSlash(pathname);
|
|
609
|
+
for (let i2 = 0; i2 < node._R.length; i2++) {
|
|
610
|
+
const hash = node._R[i2];
|
|
611
|
+
loaderPathsByHash[hash] = matchedPathname;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
512
614
|
return {
|
|
513
615
|
loaders,
|
|
514
616
|
params,
|
|
515
617
|
routeParts,
|
|
516
618
|
notFound: false,
|
|
517
619
|
routeBundleNames: node._B,
|
|
620
|
+
loaderHashes: loaderHashes.length > 0 ? loaderHashes : void 0,
|
|
621
|
+
loaderPathsByHash: Object.keys(loaderPathsByHash).length > 0 ? loaderPathsByHash : void 0,
|
|
518
622
|
menuLoader: menuLoaderRef.v,
|
|
519
623
|
errorLoader: errorLoaderRef.v,
|
|
520
624
|
notFoundLoader: notFoundLoaderRef.v
|
|
@@ -540,19 +644,18 @@ const loadModule = (moduleLoader, pendingLoads, moduleSetter, cacheModules) => {
|
|
|
540
644
|
}
|
|
541
645
|
}
|
|
542
646
|
};
|
|
543
|
-
const loadRoute = async (routes, cacheModules, pathname
|
|
647
|
+
const loadRoute = async (routes, cacheModules, pathname) => {
|
|
544
648
|
const result = matchRouteTree(routes, pathname);
|
|
545
|
-
const { loaders, params, routeParts, notFound, routeBundleNames, menuLoader, errorLoader, notFoundLoader } = result;
|
|
649
|
+
const { loaders, params, routeParts, notFound, routeBundleNames, loaderHashes, loaderPathsByHash, menuLoader, errorLoader, notFoundLoader } = result;
|
|
546
650
|
const routeName = "/" + routeParts.join("/");
|
|
547
651
|
const modules = new Array(loaders.length);
|
|
548
652
|
const pendingLoads = [];
|
|
549
|
-
loaders.
|
|
653
|
+
for (let i = 0; i < loaders.length; i++) {
|
|
654
|
+
const moduleLoader = loaders[i];
|
|
550
655
|
loadModule(moduleLoader, pendingLoads, (routeModule) => modules[i] = routeModule, cacheModules);
|
|
551
|
-
});
|
|
552
|
-
let menu = void 0;
|
|
553
|
-
if (!isInternal) {
|
|
554
|
-
loadModule(menuLoader, pendingLoads, (menuModule) => menu = menuModule?.default, cacheModules);
|
|
555
656
|
}
|
|
657
|
+
let menu = void 0;
|
|
658
|
+
loadModule(menuLoader, pendingLoads, (menuModule) => menu = menuModule?.default, cacheModules);
|
|
556
659
|
if (notFound && notFoundLoader) {
|
|
557
660
|
let notFoundMod;
|
|
558
661
|
let errorMod;
|
|
@@ -572,7 +675,9 @@ const loadRoute = async (routes, cacheModules, pathname, isInternal) => {
|
|
|
572
675
|
$menu$: deepFreeze(menu),
|
|
573
676
|
$routeBundleNames$: routeBundleNames,
|
|
574
677
|
$notFound$: notFound,
|
|
575
|
-
$errorLoader$: errorLoader
|
|
678
|
+
$errorLoader$: errorLoader,
|
|
679
|
+
$loaders$: loaderHashes,
|
|
680
|
+
$loaderPaths$: loaderPathsByHash
|
|
576
681
|
};
|
|
577
682
|
}
|
|
578
683
|
if (pendingLoads.length > 0) {
|
|
@@ -585,7 +690,9 @@ const loadRoute = async (routes, cacheModules, pathname, isInternal) => {
|
|
|
585
690
|
$menu$: deepFreeze(menu),
|
|
586
691
|
$routeBundleNames$: routeBundleNames,
|
|
587
692
|
$notFound$: notFound,
|
|
588
|
-
$errorLoader$: errorLoader
|
|
693
|
+
$errorLoader$: errorLoader,
|
|
694
|
+
$loaders$: loaderHashes,
|
|
695
|
+
$loaderPaths$: loaderPathsByHash
|
|
589
696
|
};
|
|
590
697
|
};
|
|
591
698
|
|
|
@@ -594,7 +701,38 @@ const isPromise = (value) => {
|
|
|
594
701
|
};
|
|
595
702
|
|
|
596
703
|
const MAX_CACHE_SIZE = typeof globalThis.__SSR_CACHE_SIZE__ === "number" ? globalThis.__SSR_CACHE_SIZE__ : 50;
|
|
597
|
-
|
|
704
|
+
function createLruCache() {
|
|
705
|
+
const cache = /* @__PURE__ */ new Map();
|
|
706
|
+
return {
|
|
707
|
+
get(key) {
|
|
708
|
+
const entry = cache.get(key);
|
|
709
|
+
if (entry !== void 0) {
|
|
710
|
+
cache.delete(key);
|
|
711
|
+
cache.set(key, entry);
|
|
712
|
+
}
|
|
713
|
+
return entry;
|
|
714
|
+
},
|
|
715
|
+
set(key, entry) {
|
|
716
|
+
if (MAX_CACHE_SIZE <= 0) {
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
if (cache.size >= MAX_CACHE_SIZE) {
|
|
720
|
+
const firstKey = cache.keys().next().value;
|
|
721
|
+
cache.delete(firstKey);
|
|
722
|
+
}
|
|
723
|
+
cache.set(key, entry);
|
|
724
|
+
},
|
|
725
|
+
clear(key) {
|
|
726
|
+
if (key != null) {
|
|
727
|
+
cache.delete(key);
|
|
728
|
+
} else {
|
|
729
|
+
cache.clear();
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
}
|
|
734
|
+
const ssrCache = createLruCache();
|
|
735
|
+
const loaderCache = createLruCache();
|
|
598
736
|
function resolveETag(eTagExport, headProps) {
|
|
599
737
|
if (eTagExport === void 0) {
|
|
600
738
|
return null;
|
|
@@ -604,32 +742,36 @@ function resolveETag(eTagExport, headProps) {
|
|
|
604
742
|
}
|
|
605
743
|
return eTagExport;
|
|
606
744
|
}
|
|
607
|
-
function resolveCacheKey(cacheKeyExport,
|
|
745
|
+
function resolveCacheKey(cacheKeyExport, defaultKey, requestEv, eTag) {
|
|
608
746
|
if (cacheKeyExport === true) {
|
|
609
|
-
return
|
|
747
|
+
return defaultKey(requestEv, eTag);
|
|
610
748
|
}
|
|
611
749
|
if (typeof cacheKeyExport !== "function") {
|
|
612
|
-
return
|
|
750
|
+
return "";
|
|
613
751
|
}
|
|
614
|
-
return cacheKeyExport(
|
|
752
|
+
return cacheKeyExport(requestEv, eTag) || "";
|
|
615
753
|
}
|
|
616
|
-
function
|
|
617
|
-
const
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
ssrCache.set(key, html);
|
|
621
|
-
}
|
|
622
|
-
return html;
|
|
754
|
+
function defaultSsrCacheKey(requestEv, eTag) {
|
|
755
|
+
const status = requestEv.status();
|
|
756
|
+
const pathname = requestEv.url.pathname;
|
|
757
|
+
return eTag ? `${status}|${eTag}|${pathname}` : `${status}|${pathname}`;
|
|
623
758
|
}
|
|
624
|
-
function
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
759
|
+
function defaultLoaderCacheKey(requestEv, eTag) {
|
|
760
|
+
const loaderId = requestEv.sharedMap.get(QLoaderId$1);
|
|
761
|
+
const base = `${requestEv.url.pathname}|${requestEv.url.search}|${loaderId}`;
|
|
762
|
+
return eTag ? `${base}|${eTag}` : base;
|
|
763
|
+
}
|
|
764
|
+
function getCachedSsr(key) {
|
|
765
|
+
return ssrCache.get(key);
|
|
766
|
+
}
|
|
767
|
+
function setCachedSsr(key, entry) {
|
|
768
|
+
ssrCache.set(key, entry);
|
|
769
|
+
}
|
|
770
|
+
function getCachedLoader(key) {
|
|
771
|
+
return loaderCache.get(key);
|
|
772
|
+
}
|
|
773
|
+
function setCachedLoader(key, entry) {
|
|
774
|
+
loaderCache.set(key, entry);
|
|
633
775
|
}
|
|
634
776
|
|
|
635
777
|
var HttpStatus = /* @__PURE__ */ (function(HttpStatus2) {
|
|
@@ -697,10 +839,8 @@ var HttpStatus = /* @__PURE__ */ (function(HttpStatus2) {
|
|
|
697
839
|
return HttpStatus2;
|
|
698
840
|
})({});
|
|
699
841
|
|
|
700
|
-
const RequestEvLoaders = /* @__PURE__ */ Symbol("RequestEvLoaders");
|
|
701
842
|
const RequestEvMode = /* @__PURE__ */ Symbol("RequestEvMode");
|
|
702
843
|
const RequestEvRoute = /* @__PURE__ */ Symbol("RequestEvRoute");
|
|
703
|
-
const RequestEvLoaderSerializationStrategyMap = /* @__PURE__ */ Symbol("RequestEvLoaderSerializationStrategyMap");
|
|
704
844
|
const RequestRouteName = "@routeName";
|
|
705
845
|
const RequestEvSharedActionId = "@actionId";
|
|
706
846
|
const RequestEvSharedActionFormData = "@actionFormData";
|
|
@@ -709,13 +849,6 @@ const RequestEvIsRewrite = "@rewrite";
|
|
|
709
849
|
const RequestEvShareServerTiming = "@serverTiming";
|
|
710
850
|
const RequestEvETagCacheKey = "@eTagCacheKey";
|
|
711
851
|
const RequestEvHttpStatusMessage = "@httpStatusMessage";
|
|
712
|
-
const RequestEvShareQData = "qData";
|
|
713
|
-
function getRequestLoaders(requestEv) {
|
|
714
|
-
return requestEv[RequestEvLoaders];
|
|
715
|
-
}
|
|
716
|
-
function getRequestLoaderSerializationStrategyMap(requestEv) {
|
|
717
|
-
return requestEv[RequestEvLoaderSerializationStrategyMap];
|
|
718
|
-
}
|
|
719
852
|
function getRequestRoute(requestEv) {
|
|
720
853
|
return requestEv[RequestEvRoute];
|
|
721
854
|
}
|
|
@@ -835,10 +968,23 @@ function createRequestEventWithDeps(deps, serverRequestEv, loadedRoute, requestH
|
|
|
835
968
|
const cookie = new deps.Cookie(request.headers.get("cookie"));
|
|
836
969
|
const headers = new Headers();
|
|
837
970
|
const url = new URL(request.url);
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
971
|
+
let internalRequest = false;
|
|
972
|
+
const recognized = deps.recognizeRequest(url.pathname);
|
|
973
|
+
if (recognized) {
|
|
974
|
+
url.pathname = deps.trimRecognizedInternalPathname(url.pathname, recognized);
|
|
975
|
+
sharedMap.set(recognized.type, true);
|
|
976
|
+
internalRequest = "loader";
|
|
977
|
+
if (recognized.data?.loaderId) {
|
|
978
|
+
sharedMap.set(deps.QLoaderId, recognized.data.loaderId);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
const actionId = url.searchParams.get(deps.QACTION_KEY);
|
|
982
|
+
if (actionId) {
|
|
983
|
+
sharedMap.set(deps.IsQAction, true);
|
|
984
|
+
sharedMap.set(deps.QActionId, actionId);
|
|
985
|
+
if (request.method === "POST" && request.headers.get("accept")?.includes("application/json")) {
|
|
986
|
+
internalRequest = "action";
|
|
987
|
+
}
|
|
842
988
|
}
|
|
843
989
|
let routeModuleIndex = -1;
|
|
844
990
|
let writableStream = null;
|
|
@@ -907,10 +1053,7 @@ function createRequestEventWithDeps(deps, serverRequestEv, loadedRoute, requestH
|
|
|
907
1053
|
routeModuleIndex = ABORT_INDEX;
|
|
908
1054
|
return message;
|
|
909
1055
|
};
|
|
910
|
-
const loaders = {};
|
|
911
1056
|
const requestEv = {
|
|
912
|
-
[RequestEvLoaders]: loaders,
|
|
913
|
-
[RequestEvLoaderSerializationStrategyMap]: /* @__PURE__ */ new Map(),
|
|
914
1057
|
[RequestEvMode]: serverRequestEv.mode,
|
|
915
1058
|
get [RequestEvRoute]() {
|
|
916
1059
|
return loadedRoute;
|
|
@@ -933,6 +1076,7 @@ function createRequestEventWithDeps(deps, serverRequestEv, loadedRoute, requestH
|
|
|
933
1076
|
},
|
|
934
1077
|
request,
|
|
935
1078
|
url,
|
|
1079
|
+
internalRequest,
|
|
936
1080
|
basePathname,
|
|
937
1081
|
sharedMap,
|
|
938
1082
|
get headersSent() {
|
|
@@ -952,16 +1096,14 @@ function createRequestEventWithDeps(deps, serverRequestEv, loadedRoute, requestH
|
|
|
952
1096
|
headers.set(target, deps.createCacheControl(cacheControl));
|
|
953
1097
|
},
|
|
954
1098
|
resolveValue: async (loaderOrAction) => {
|
|
955
|
-
const id = loaderOrAction.__id;
|
|
956
1099
|
if (loaderOrAction.__brand === "server_loader") {
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
if (loaders[id] === _UNINITIALIZED) {
|
|
961
|
-
await deps.getRouteLoaderPromise(loaderOrAction, loaders, requestEv[RequestEvLoaderSerializationStrategyMap], requestEv);
|
|
1100
|
+
const loaderValues = getRouteLoaderValues(requestEv);
|
|
1101
|
+
if (loaderOrAction.__id in loaderValues) {
|
|
1102
|
+
return loaderValues[loaderOrAction.__id];
|
|
962
1103
|
}
|
|
1104
|
+
return loadRouteLoader(loaderOrAction, requestEv);
|
|
963
1105
|
}
|
|
964
|
-
return
|
|
1106
|
+
return void 0;
|
|
965
1107
|
},
|
|
966
1108
|
status: (statusCode) => {
|
|
967
1109
|
if (typeof statusCode === "number") {
|
|
@@ -1001,15 +1143,18 @@ function createRequestEventWithDeps(deps, serverRequestEv, loadedRoute, requestH
|
|
|
1001
1143
|
if (statusCode > 301) {
|
|
1002
1144
|
headers.set("Cache-Control", "no-store");
|
|
1003
1145
|
}
|
|
1146
|
+
if (internalRequest === "loader") {
|
|
1147
|
+
return new deps.RedirectMessage();
|
|
1148
|
+
}
|
|
1004
1149
|
return exit(new deps.RedirectMessage());
|
|
1005
1150
|
},
|
|
1006
|
-
rewrite: (
|
|
1151
|
+
rewrite: (pathname) => {
|
|
1007
1152
|
check();
|
|
1008
|
-
if (
|
|
1153
|
+
if (pathname.startsWith("http")) {
|
|
1009
1154
|
throw new deps.ServerError(400, isDev ? "Rewrite does not support absolute urls" : "Bad Request");
|
|
1010
1155
|
}
|
|
1011
1156
|
sharedMap.set(RequestEvIsRewrite, true);
|
|
1012
|
-
return exit(new deps.RewriteMessage(
|
|
1157
|
+
return exit(new deps.RewriteMessage(pathname.replace(/\/+/g, "/")));
|
|
1013
1158
|
},
|
|
1014
1159
|
defer: (returnData) => {
|
|
1015
1160
|
return typeof returnData === "function" ? returnData : () => returnData;
|
|
@@ -1061,105 +1206,6 @@ function createRequestEventWithDeps(deps, serverRequestEv, loadedRoute, requestH
|
|
|
1061
1206
|
return requestEv;
|
|
1062
1207
|
}
|
|
1063
1208
|
|
|
1064
|
-
function verifySerializable(data, qrl) {
|
|
1065
|
-
try {
|
|
1066
|
-
_verifySerializable(data, void 0);
|
|
1067
|
-
} catch (e) {
|
|
1068
|
-
if (e instanceof Error && qrl.dev) {
|
|
1069
|
-
e.loc = qrl.dev;
|
|
1070
|
-
}
|
|
1071
|
-
throw e;
|
|
1072
|
-
}
|
|
1073
|
-
}
|
|
1074
|
-
function now() {
|
|
1075
|
-
return typeof performance !== "undefined" ? performance.now() : 0;
|
|
1076
|
-
}
|
|
1077
|
-
async function measure(requestEv, name, fn) {
|
|
1078
|
-
const start = now();
|
|
1079
|
-
try {
|
|
1080
|
-
return await fn();
|
|
1081
|
-
} finally {
|
|
1082
|
-
const duration = now() - start;
|
|
1083
|
-
let measurements = requestEv.sharedMap.get("@serverTiming");
|
|
1084
|
-
if (!measurements) {
|
|
1085
|
-
requestEv.sharedMap.set("@serverTiming", measurements = []);
|
|
1086
|
-
}
|
|
1087
|
-
measurements.push([
|
|
1088
|
-
name,
|
|
1089
|
-
duration
|
|
1090
|
-
]);
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
async function runValidators(requestEv, validators, data) {
|
|
1094
|
-
let lastResult = {
|
|
1095
|
-
success: true,
|
|
1096
|
-
data
|
|
1097
|
-
};
|
|
1098
|
-
if (validators) {
|
|
1099
|
-
for (const validator of validators) {
|
|
1100
|
-
if (isDev) {
|
|
1101
|
-
lastResult = await measure(requestEv, `validator$`, () => validator.validate(requestEv, data));
|
|
1102
|
-
} else {
|
|
1103
|
-
lastResult = await validator.validate(requestEv, data);
|
|
1104
|
-
}
|
|
1105
|
-
if (!lastResult.success) {
|
|
1106
|
-
return lastResult;
|
|
1107
|
-
} else {
|
|
1108
|
-
data = lastResult.data;
|
|
1109
|
-
}
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
return lastResult;
|
|
1113
|
-
}
|
|
1114
|
-
async function getRouteLoaderPromise(loader, loaders, loadersSerializationStrategy, requestEv) {
|
|
1115
|
-
const loaderId = loader.__id;
|
|
1116
|
-
loaders[loaderId] = runValidators(
|
|
1117
|
-
requestEv,
|
|
1118
|
-
loader.__validators,
|
|
1119
|
-
void 0
|
|
1120
|
-
// data
|
|
1121
|
-
).then((res) => {
|
|
1122
|
-
if (res.success) {
|
|
1123
|
-
if (isDev) {
|
|
1124
|
-
return measure(requestEv, loader.__qrl.getHash(), () => loader.__qrl.call(requestEv, requestEv));
|
|
1125
|
-
} else {
|
|
1126
|
-
return loader.__qrl.call(requestEv, requestEv);
|
|
1127
|
-
}
|
|
1128
|
-
} else {
|
|
1129
|
-
return requestEv.fail(res.status ?? 500, res.error);
|
|
1130
|
-
}
|
|
1131
|
-
}).then((resolvedLoader) => {
|
|
1132
|
-
if (typeof resolvedLoader === "function") {
|
|
1133
|
-
loaders[loaderId] = resolvedLoader();
|
|
1134
|
-
} else {
|
|
1135
|
-
if (isDev) {
|
|
1136
|
-
verifySerializable(resolvedLoader, loader.__qrl);
|
|
1137
|
-
}
|
|
1138
|
-
loaders[loaderId] = resolvedLoader;
|
|
1139
|
-
}
|
|
1140
|
-
return resolvedLoader;
|
|
1141
|
-
});
|
|
1142
|
-
loadersSerializationStrategy.set(loaderId, loader.__serializationStrategy);
|
|
1143
|
-
return loaders[loaderId];
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
const IsQData = "@isQData";
|
|
1147
|
-
const QDATA_JSON = "/q-data.json";
|
|
1148
|
-
function getRouteMatchPathname(pathname) {
|
|
1149
|
-
const isInternal = pathname.endsWith(QDATA_JSON);
|
|
1150
|
-
if (isInternal) {
|
|
1151
|
-
const trimEnd = pathname.length - QDATA_JSON.length + (globalThis.__NO_TRAILING_SLASH__ ? 0 : 1);
|
|
1152
|
-
pathname = pathname.slice(0, trimEnd);
|
|
1153
|
-
if (pathname === "") {
|
|
1154
|
-
pathname = "/";
|
|
1155
|
-
}
|
|
1156
|
-
}
|
|
1157
|
-
return {
|
|
1158
|
-
pathname,
|
|
1159
|
-
isInternal
|
|
1160
|
-
};
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
1209
|
const encoder = /* @__PURE__ */ new TextEncoder();
|
|
1164
1210
|
function getContentType(headers) {
|
|
1165
1211
|
return (headers.get("content-type")?.split(/[;,]/, 1)[0].trim() ?? "").toLowerCase();
|
|
@@ -1180,22 +1226,20 @@ class RedirectMessage extends AbortMessage {
|
|
|
1180
1226
|
}
|
|
1181
1227
|
|
|
1182
1228
|
function createResolveRequestHandlers(deps) {
|
|
1183
|
-
const resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderHandler
|
|
1229
|
+
const resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderHandler) => {
|
|
1184
1230
|
const routeLoaders = [];
|
|
1185
1231
|
const routeActions = [];
|
|
1186
1232
|
const requestHandlers = [];
|
|
1187
1233
|
const isPageRoute = !!isLastModulePageRoute(route.$mods$);
|
|
1188
|
-
if (isInternal) {
|
|
1189
|
-
requestHandlers.push(handleQDataRedirect);
|
|
1190
|
-
}
|
|
1191
1234
|
if (isPageRoute) {
|
|
1235
|
+
requestHandlers.push(jsonRequestWrapper());
|
|
1192
1236
|
requestHandlers.push(serverErrorMiddleware(route, renderHandler));
|
|
1193
1237
|
}
|
|
1194
1238
|
if (serverPlugins) {
|
|
1195
1239
|
_resolveRequestHandlers(routeLoaders, routeActions, requestHandlers, serverPlugins, isPageRoute, method);
|
|
1196
1240
|
}
|
|
1197
1241
|
const routeModules = route.$mods$;
|
|
1198
|
-
_resolveRequestHandlers(routeLoaders, routeActions, requestHandlers, routeModules, isPageRoute, method);
|
|
1242
|
+
_resolveRequestHandlers(routeLoaders, routeActions, requestHandlers, routeModules, isPageRoute, method, isPageRoute);
|
|
1199
1243
|
const routeName = route.$routeName$;
|
|
1200
1244
|
if (checkOrigin && (method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE")) {
|
|
1201
1245
|
if (checkOrigin === "lax-proto") {
|
|
@@ -1205,70 +1249,32 @@ function createResolveRequestHandlers(deps) {
|
|
|
1205
1249
|
}
|
|
1206
1250
|
}
|
|
1207
1251
|
if (isPageRoute) {
|
|
1252
|
+
requestHandlers.push(loaderHandler(routeLoaders, route.$loaderPaths$));
|
|
1253
|
+
requestHandlers.push(actionHandler(routeActions));
|
|
1208
1254
|
if (method === "POST" || method === "GET") {
|
|
1209
1255
|
requestHandlers.push(runServerFunction);
|
|
1210
1256
|
}
|
|
1211
1257
|
if (!route.$notFound$) {
|
|
1212
1258
|
requestHandlers.push(fixTrailingSlash);
|
|
1213
1259
|
}
|
|
1214
|
-
if (isInternal) {
|
|
1215
|
-
requestHandlers.push(renderQData);
|
|
1216
|
-
}
|
|
1217
1260
|
}
|
|
1218
1261
|
if (isPageRoute) {
|
|
1219
1262
|
requestHandlers.push((ev) => {
|
|
1220
1263
|
ev.sharedMap.set(deps.RequestRouteName, routeName);
|
|
1221
1264
|
});
|
|
1222
1265
|
requestHandlers.push(actionsMiddleware(routeActions));
|
|
1223
|
-
requestHandlers.push(loadersMiddleware(routeLoaders));
|
|
1266
|
+
requestHandlers.push(loadersMiddleware(routeLoaders, route));
|
|
1224
1267
|
requestHandlers.push(eTagMiddleware(route));
|
|
1225
1268
|
requestHandlers.push(renderHandler);
|
|
1226
1269
|
}
|
|
1227
1270
|
return requestHandlers;
|
|
1228
1271
|
};
|
|
1229
|
-
|
|
1230
|
-
for (
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
}
|
|
1236
|
-
let methodReqHandler;
|
|
1237
|
-
switch (method) {
|
|
1238
|
-
case "GET": {
|
|
1239
|
-
methodReqHandler = routeModule.onGet;
|
|
1240
|
-
break;
|
|
1241
|
-
}
|
|
1242
|
-
case "POST": {
|
|
1243
|
-
methodReqHandler = routeModule.onPost;
|
|
1244
|
-
break;
|
|
1245
|
-
}
|
|
1246
|
-
case "PUT": {
|
|
1247
|
-
methodReqHandler = routeModule.onPut;
|
|
1248
|
-
break;
|
|
1249
|
-
}
|
|
1250
|
-
case "PATCH": {
|
|
1251
|
-
methodReqHandler = routeModule.onPatch;
|
|
1252
|
-
break;
|
|
1253
|
-
}
|
|
1254
|
-
case "DELETE": {
|
|
1255
|
-
methodReqHandler = routeModule.onDelete;
|
|
1256
|
-
break;
|
|
1257
|
-
}
|
|
1258
|
-
case "OPTIONS": {
|
|
1259
|
-
methodReqHandler = routeModule.onOptions;
|
|
1260
|
-
break;
|
|
1261
|
-
}
|
|
1262
|
-
case "HEAD": {
|
|
1263
|
-
methodReqHandler = routeModule.onHead;
|
|
1264
|
-
break;
|
|
1265
|
-
}
|
|
1266
|
-
}
|
|
1267
|
-
if (typeof methodReqHandler === "function") {
|
|
1268
|
-
requestHandlers.push(methodReqHandler);
|
|
1269
|
-
} else if (Array.isArray(methodReqHandler)) {
|
|
1270
|
-
requestHandlers.push(...methodReqHandler);
|
|
1271
|
-
}
|
|
1272
|
+
function _resolveRequestHandlers(routeLoaders, routeActions, requestHandlers, routeModules, collectActions, method, guardPageHandlersForLoader = false) {
|
|
1273
|
+
for (let i = 0; i < routeModules.length; i++) {
|
|
1274
|
+
const routeModule = routeModules[i];
|
|
1275
|
+
const moduleHandlers = getModuleRequestHandlers(routeModule, method);
|
|
1276
|
+
const shouldGuardPageHandlers = guardPageHandlersForLoader && i === routeModules.length - 1;
|
|
1277
|
+
requestHandlers.push(...shouldGuardPageHandlers ? moduleHandlers.map((handler) => guardPageHandlerForLoader(routeModule, handler)) : moduleHandlers);
|
|
1272
1278
|
if (collectActions) {
|
|
1273
1279
|
for (const module of Object.values(routeModule)) {
|
|
1274
1280
|
if (typeof module === "function") {
|
|
@@ -1281,7 +1287,73 @@ function createResolveRequestHandlers(deps) {
|
|
|
1281
1287
|
}
|
|
1282
1288
|
}
|
|
1283
1289
|
}
|
|
1284
|
-
}
|
|
1290
|
+
}
|
|
1291
|
+
function getModuleRequestHandlers(routeModule, method) {
|
|
1292
|
+
const handlers = [];
|
|
1293
|
+
addRequestHandlers(handlers, routeModule.onRequest);
|
|
1294
|
+
let methodReqHandler;
|
|
1295
|
+
switch (method) {
|
|
1296
|
+
case "GET": {
|
|
1297
|
+
methodReqHandler = routeModule.onGet;
|
|
1298
|
+
break;
|
|
1299
|
+
}
|
|
1300
|
+
case "POST": {
|
|
1301
|
+
methodReqHandler = routeModule.onPost;
|
|
1302
|
+
break;
|
|
1303
|
+
}
|
|
1304
|
+
case "PUT": {
|
|
1305
|
+
methodReqHandler = routeModule.onPut;
|
|
1306
|
+
break;
|
|
1307
|
+
}
|
|
1308
|
+
case "PATCH": {
|
|
1309
|
+
methodReqHandler = routeModule.onPatch;
|
|
1310
|
+
break;
|
|
1311
|
+
}
|
|
1312
|
+
case "DELETE": {
|
|
1313
|
+
methodReqHandler = routeModule.onDelete;
|
|
1314
|
+
break;
|
|
1315
|
+
}
|
|
1316
|
+
case "OPTIONS": {
|
|
1317
|
+
methodReqHandler = routeModule.onOptions;
|
|
1318
|
+
break;
|
|
1319
|
+
}
|
|
1320
|
+
case "HEAD": {
|
|
1321
|
+
methodReqHandler = routeModule.onHead;
|
|
1322
|
+
break;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
addRequestHandlers(handlers, methodReqHandler);
|
|
1326
|
+
return handlers;
|
|
1327
|
+
}
|
|
1328
|
+
function addRequestHandlers(handlers, handler) {
|
|
1329
|
+
if (typeof handler === "function") {
|
|
1330
|
+
handlers.push(handler);
|
|
1331
|
+
} else if (Array.isArray(handler)) {
|
|
1332
|
+
handlers.push(...handler);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
function guardPageHandlerForLoader(routeModule, handler) {
|
|
1336
|
+
return (requestEv) => {
|
|
1337
|
+
if (requestEv.sharedMap.has(IsQLoader$1)) {
|
|
1338
|
+
const loaderId = requestEv.sharedMap.get(QLoaderId$1);
|
|
1339
|
+
if (!moduleHasLoader(routeModule, loaderId)) {
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
return handler(requestEv);
|
|
1344
|
+
};
|
|
1345
|
+
}
|
|
1346
|
+
function moduleHasLoader(routeModule, loaderId) {
|
|
1347
|
+
if (typeof loaderId !== "string") {
|
|
1348
|
+
return false;
|
|
1349
|
+
}
|
|
1350
|
+
for (const value of Object.values(routeModule)) {
|
|
1351
|
+
if (checkBrand(value, "server_loader") && value.__id === loaderId) {
|
|
1352
|
+
return true;
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
return false;
|
|
1356
|
+
}
|
|
1285
1357
|
const checkBrand = (obj, brand) => {
|
|
1286
1358
|
return obj && typeof obj === "function" && obj.__brand === brand;
|
|
1287
1359
|
};
|
|
@@ -1293,8 +1365,7 @@ function createResolveRequestHandlers(deps) {
|
|
|
1293
1365
|
return;
|
|
1294
1366
|
}
|
|
1295
1367
|
const { method } = requestEv;
|
|
1296
|
-
|
|
1297
|
-
if (isDev && method === "GET") {
|
|
1368
|
+
if (isDev$1 && method === "GET") {
|
|
1298
1369
|
if (requestEv.query.has(deps.QACTION_KEY)) {
|
|
1299
1370
|
console.warn('Seems like you are submitting a Qwik Action via GET request. Qwik Actions should be submitted via POST request.\nMake sure your <form> has method="POST" attribute, like this: <form method="POST">');
|
|
1300
1371
|
}
|
|
@@ -1311,66 +1382,79 @@ function createResolveRequestHandlers(deps) {
|
|
|
1311
1382
|
throw new Error(`Expected request data for the action id ${selectedActionId} to be an object`);
|
|
1312
1383
|
}
|
|
1313
1384
|
const result = await runValidators(requestEv, action.__validators, data);
|
|
1385
|
+
let actionResult;
|
|
1314
1386
|
if (!result.success) {
|
|
1315
|
-
|
|
1387
|
+
actionResult = requestEv.fail(result.status ?? 500, result.error);
|
|
1316
1388
|
} else {
|
|
1317
|
-
const actionResolved = isDev ? await measure(requestEv, action.__qrl.getHash(), () => action.__qrl.call(requestEv, result.data, requestEv)) : await action.__qrl.call(requestEv, result.data, requestEv);
|
|
1318
|
-
if (isDev) {
|
|
1389
|
+
const actionResolved = isDev$1 ? await measure(requestEv, action.__qrl.getHash(), () => action.__qrl.call(requestEv, result.data, requestEv)) : await action.__qrl.call(requestEv, result.data, requestEv);
|
|
1390
|
+
if (isDev$1) {
|
|
1319
1391
|
verifySerializable(actionResolved, action.__qrl);
|
|
1320
1392
|
}
|
|
1321
|
-
|
|
1393
|
+
actionResult = actionResolved;
|
|
1322
1394
|
}
|
|
1395
|
+
requestEv.sharedMap.set("@actionResult", actionResult);
|
|
1323
1396
|
}
|
|
1324
1397
|
}
|
|
1325
1398
|
}
|
|
1326
1399
|
};
|
|
1327
1400
|
}
|
|
1328
|
-
function loadersMiddleware(routeLoaders) {
|
|
1401
|
+
function loadersMiddleware(routeLoaders, route) {
|
|
1329
1402
|
return async (requestEvent) => {
|
|
1330
1403
|
const requestEv = requestEvent;
|
|
1331
1404
|
if (requestEv.headersSent) {
|
|
1332
1405
|
requestEv.exit();
|
|
1333
1406
|
return;
|
|
1334
1407
|
}
|
|
1335
|
-
const loaders = deps.getRequestLoaders(requestEv);
|
|
1336
|
-
const loadersSerializationStrategy = deps.getRequestLoaderSerializationStrategyMap(requestEv);
|
|
1337
1408
|
if (routeLoaders.length > 0) {
|
|
1338
|
-
|
|
1339
|
-
|
|
1409
|
+
setLoaderData(requestEv, routeLoaders, route);
|
|
1410
|
+
const loaderValues = getRouteLoaderValues(requestEv);
|
|
1411
|
+
await Promise.all(routeLoaders.map(async (loader) => {
|
|
1412
|
+
loaderValues[loader.__id] = await loadRouteLoader(loader, requestEv);
|
|
1413
|
+
}));
|
|
1340
1414
|
}
|
|
1341
1415
|
};
|
|
1342
1416
|
}
|
|
1417
|
+
function setLoaderData(requestEv, routeLoaders, route) {
|
|
1418
|
+
if (routeLoaders.length === 0) {
|
|
1419
|
+
return;
|
|
1420
|
+
}
|
|
1421
|
+
const routeLoaderCtx = getRouteLoaderCtx(requestEv);
|
|
1422
|
+
if (route.$loaderPaths$) {
|
|
1423
|
+
Object.assign(routeLoaderCtx.loaderPaths, route.$loaderPaths$);
|
|
1424
|
+
}
|
|
1425
|
+
setRouteLoaders(requestEv, routeLoaders);
|
|
1426
|
+
}
|
|
1343
1427
|
function eTagMiddleware(route) {
|
|
1344
1428
|
return (requestEv) => {
|
|
1345
1429
|
if (requestEv.headersSent) {
|
|
1346
1430
|
return;
|
|
1347
1431
|
}
|
|
1348
|
-
if (requestEv.method !== "GET"
|
|
1432
|
+
if (requestEv.method !== "GET") {
|
|
1349
1433
|
return;
|
|
1350
1434
|
}
|
|
1351
1435
|
const mods = route.$mods$;
|
|
1352
|
-
const
|
|
1436
|
+
const hasCachingConfig = mods.some((m) => {
|
|
1353
1437
|
if (!m) {
|
|
1354
1438
|
return false;
|
|
1355
1439
|
}
|
|
1356
1440
|
if (m.routeConfig) {
|
|
1357
|
-
return typeof m.routeConfig === "function" || m.routeConfig.eTag !== void 0;
|
|
1441
|
+
return typeof m.routeConfig === "function" || m.routeConfig.eTag !== void 0 || m.routeConfig.cacheKey !== void 0;
|
|
1358
1442
|
}
|
|
1359
|
-
return m.eTag !== void 0;
|
|
1443
|
+
return m.eTag !== void 0 || m.cacheKey !== void 0;
|
|
1360
1444
|
});
|
|
1361
|
-
if (!
|
|
1445
|
+
if (!hasCachingConfig) {
|
|
1362
1446
|
return;
|
|
1363
1447
|
}
|
|
1364
|
-
const
|
|
1448
|
+
const loaderValues = getRouteLoaderValues(requestEv);
|
|
1365
1449
|
const getData = (loaderOrAction) => {
|
|
1366
1450
|
const id = loaderOrAction.__id;
|
|
1367
|
-
if (loaderOrAction.__brand === "server_loader"
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1451
|
+
if (loaderOrAction.__brand === "server_loader") {
|
|
1452
|
+
if (!(id in loaderValues)) {
|
|
1453
|
+
throw new Error("Loader not executed for this request.");
|
|
1454
|
+
}
|
|
1455
|
+
return loaderValues[id];
|
|
1372
1456
|
}
|
|
1373
|
-
return
|
|
1457
|
+
return requestEv.sharedMap.get(deps.RequestEvSharedActionId) === id ? requestEv.sharedMap.get("@actionResult") : void 0;
|
|
1374
1458
|
};
|
|
1375
1459
|
const routeLocation = {
|
|
1376
1460
|
params: requestEv.params,
|
|
@@ -1387,32 +1471,36 @@ function createResolveRequestHandlers(deps) {
|
|
|
1387
1471
|
resolveValue: getData,
|
|
1388
1472
|
...routeLocation
|
|
1389
1473
|
};
|
|
1390
|
-
const
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
}
|
|
1394
|
-
requestEv.headers.set("ETag", eTag);
|
|
1395
|
-
const ifNoneMatch = requestEv.request.headers.get("If-None-Match");
|
|
1396
|
-
if (ifNoneMatch && (ifNoneMatch === eTag || ifNoneMatch === `W/${eTag}` || `W/${ifNoneMatch}` === eTag)) {
|
|
1397
|
-
requestEv.status(304);
|
|
1398
|
-
requestEv.send(304, "");
|
|
1474
|
+
const resolvedETag = deps.resolveETag(config.eTag, headProps);
|
|
1475
|
+
const normalizedETag = resolvedETag !== null ? normalizeETag(resolvedETag) : "";
|
|
1476
|
+
if (normalizedETag && performETagMatch(requestEv, normalizedETag)) {
|
|
1399
1477
|
return;
|
|
1400
1478
|
}
|
|
1401
1479
|
if (deps.MAX_CACHE_SIZE <= 0) {
|
|
1402
1480
|
return;
|
|
1403
1481
|
}
|
|
1404
|
-
const cacheKey = deps.resolveCacheKey(config.cacheKey,
|
|
1482
|
+
const cacheKey = deps.resolveCacheKey(config.cacheKey, deps.defaultSsrCacheKey, requestEv, normalizedETag);
|
|
1405
1483
|
if (!cacheKey) {
|
|
1406
1484
|
return;
|
|
1407
1485
|
}
|
|
1408
|
-
const
|
|
1409
|
-
if (
|
|
1486
|
+
const cached = deps.getCachedSsr(cacheKey);
|
|
1487
|
+
if (cached) {
|
|
1410
1488
|
requestEv.headers.set("Content-Type", "text/html; charset=utf-8");
|
|
1411
1489
|
requestEv.headers.set("X-SSR-Cache", "HIT");
|
|
1412
|
-
|
|
1490
|
+
if (!normalizedETag) {
|
|
1491
|
+
if (performETagMatch(requestEv, cached.eTag)) {
|
|
1492
|
+
return;
|
|
1493
|
+
}
|
|
1494
|
+
} else {
|
|
1495
|
+
setETagHeader(requestEv, cached.eTag);
|
|
1496
|
+
}
|
|
1497
|
+
requestEv.send(status, cached.body);
|
|
1413
1498
|
return;
|
|
1414
1499
|
}
|
|
1415
|
-
requestEv.sharedMap.set(deps.RequestEvETagCacheKey,
|
|
1500
|
+
requestEv.sharedMap.set(deps.RequestEvETagCacheKey, {
|
|
1501
|
+
key: cacheKey,
|
|
1502
|
+
eTag: normalizedETag
|
|
1503
|
+
});
|
|
1416
1504
|
};
|
|
1417
1505
|
}
|
|
1418
1506
|
function serverErrorMiddleware(route, renderHandler) {
|
|
@@ -1423,9 +1511,6 @@ function createResolveRequestHandlers(deps) {
|
|
|
1423
1511
|
if (!(e instanceof deps.ServerError) || requestEv.headersSent) {
|
|
1424
1512
|
throw e;
|
|
1425
1513
|
}
|
|
1426
|
-
if (requestEv.sharedMap.has(deps.IsQData)) {
|
|
1427
|
-
throw e;
|
|
1428
|
-
}
|
|
1429
1514
|
const accept = requestEv.request.headers.get("Accept");
|
|
1430
1515
|
if (accept && !accept.includes("text/html")) {
|
|
1431
1516
|
throw e;
|
|
@@ -1449,7 +1534,7 @@ function createResolveRequestHandlers(deps) {
|
|
|
1449
1534
|
};
|
|
1450
1535
|
if (validators) {
|
|
1451
1536
|
for (const validator of validators) {
|
|
1452
|
-
if (isDev) {
|
|
1537
|
+
if (isDev$1) {
|
|
1453
1538
|
lastResult = await measure(requestEv, `validator$`, () => validator.validate(requestEv, data));
|
|
1454
1539
|
} else {
|
|
1455
1540
|
lastResult = await validator.validate(requestEv, data);
|
|
@@ -1477,7 +1562,7 @@ function createResolveRequestHandlers(deps) {
|
|
|
1477
1562
|
const qrl = inlinedQrl(null, serverFnHash, data.slice(1));
|
|
1478
1563
|
let result;
|
|
1479
1564
|
try {
|
|
1480
|
-
if (isDev) {
|
|
1565
|
+
if (isDev$1) {
|
|
1481
1566
|
result = await measure(ev, `server_${serverFnHash}`, () => qrl.apply(ev, data[0]));
|
|
1482
1567
|
} else {
|
|
1483
1568
|
result = await qrl.apply(ev, data[0]);
|
|
@@ -1494,7 +1579,7 @@ function createResolveRequestHandlers(deps) {
|
|
|
1494
1579
|
const writable = ev.getWritableStream();
|
|
1495
1580
|
const stream = writable.getWriter();
|
|
1496
1581
|
for await (const item of result) {
|
|
1497
|
-
if (isDev) {
|
|
1582
|
+
if (isDev$1) {
|
|
1498
1583
|
verifySerializable(item, qrl);
|
|
1499
1584
|
}
|
|
1500
1585
|
const message = await _serialize(item);
|
|
@@ -1515,16 +1600,15 @@ function createResolveRequestHandlers(deps) {
|
|
|
1515
1600
|
}
|
|
1516
1601
|
}
|
|
1517
1602
|
function fixTrailingSlash(ev) {
|
|
1518
|
-
const { basePathname, originalUrl
|
|
1603
|
+
const { basePathname, originalUrl } = ev;
|
|
1519
1604
|
const { pathname, search } = originalUrl;
|
|
1520
|
-
const isQData = sharedMap.has(deps.IsQData);
|
|
1521
1605
|
if (!pathname.startsWith("/") || pathname.startsWith("//")) {
|
|
1522
1606
|
return;
|
|
1523
1607
|
}
|
|
1524
|
-
if (
|
|
1608
|
+
if (pathname !== basePathname && !pathname.endsWith(".html")) {
|
|
1525
1609
|
if (!globalThis.__NO_TRAILING_SLASH__) {
|
|
1526
1610
|
if (!pathname.endsWith("/")) {
|
|
1527
|
-
throw ev.redirect(deps.HttpStatus.MovedPermanently, pathname +
|
|
1611
|
+
throw ev.redirect(deps.HttpStatus.MovedPermanently, ensureSlash(pathname) + search);
|
|
1528
1612
|
}
|
|
1529
1613
|
} else {
|
|
1530
1614
|
if (pathname.endsWith("/")) {
|
|
@@ -1552,12 +1636,9 @@ function createResolveRequestHandlers(deps) {
|
|
|
1552
1636
|
}
|
|
1553
1637
|
function getPathname(url) {
|
|
1554
1638
|
url = new URL(url);
|
|
1555
|
-
if (url.pathname.endsWith(deps.QDATA_JSON)) {
|
|
1556
|
-
url.pathname = url.pathname.slice(0, -deps.QDATA_JSON.length);
|
|
1557
|
-
}
|
|
1558
1639
|
if (!globalThis.__NO_TRAILING_SLASH__) {
|
|
1559
1640
|
if (!url.pathname.endsWith("/")) {
|
|
1560
|
-
url.pathname
|
|
1641
|
+
url.pathname = ensureSlash(url.pathname);
|
|
1561
1642
|
}
|
|
1562
1643
|
} else {
|
|
1563
1644
|
if (url.pathname.endsWith("/")) {
|
|
@@ -1594,19 +1675,16 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
|
|
|
1594
1675
|
if (requestEv.headersSent) {
|
|
1595
1676
|
return;
|
|
1596
1677
|
}
|
|
1597
|
-
if (requestEv.sharedMap.has(deps.IsQData)) {
|
|
1598
|
-
return;
|
|
1599
|
-
}
|
|
1600
1678
|
const responseHeaders = requestEv.headers;
|
|
1601
1679
|
if (!responseHeaders.has("Content-Type")) {
|
|
1602
1680
|
responseHeaders.set("Content-Type", "text/html; charset=utf-8");
|
|
1603
1681
|
}
|
|
1604
|
-
const
|
|
1682
|
+
const cachePlan = requestEv.sharedMap.get(deps.RequestEvETagCacheKey);
|
|
1605
1683
|
const { readable, writable } = new TextEncoderStream();
|
|
1606
1684
|
const writableStream = requestEv.getWritableStream();
|
|
1607
1685
|
let cacheChunks;
|
|
1608
1686
|
let pipeSource = readable;
|
|
1609
|
-
if (
|
|
1687
|
+
if (cachePlan) {
|
|
1610
1688
|
cacheChunks = [];
|
|
1611
1689
|
const capture = new TransformStream({
|
|
1612
1690
|
transform(chunk, controller) {
|
|
@@ -1623,29 +1701,24 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
|
|
|
1623
1701
|
pipeError = error;
|
|
1624
1702
|
});
|
|
1625
1703
|
const stream = writable.getWriter();
|
|
1626
|
-
const status = requestEv.status();
|
|
1627
1704
|
try {
|
|
1628
1705
|
const isStatic = deps.getRequestMode(requestEv) === "static";
|
|
1629
1706
|
const serverData = deps.getQwikRouterServerData(requestEv);
|
|
1630
1707
|
const result = await render({
|
|
1631
1708
|
base: requestEv.basePathname + "build/",
|
|
1632
1709
|
stream,
|
|
1710
|
+
streaming: isStatic ? {
|
|
1711
|
+
outOfOrder: false
|
|
1712
|
+
} : void 0,
|
|
1633
1713
|
serverData,
|
|
1634
1714
|
containerAttributes: {
|
|
1635
1715
|
["q:render"]: isStatic ? "static" : "",
|
|
1636
1716
|
...serverData.containerAttributes
|
|
1637
1717
|
}
|
|
1638
1718
|
});
|
|
1639
|
-
const qData = {
|
|
1640
|
-
loaders: deps.getRequestLoaders(requestEv),
|
|
1641
|
-
action: requestEv.sharedMap.get(deps.RequestEvSharedActionId),
|
|
1642
|
-
status: status !== 200 ? status : 200,
|
|
1643
|
-
href: getPathname(requestEv.url)
|
|
1644
|
-
};
|
|
1645
1719
|
if (typeof result.html === "string") {
|
|
1646
1720
|
await stream.write(result.html);
|
|
1647
1721
|
}
|
|
1648
|
-
requestEv.sharedMap.set(deps.RequestEvShareQData, qData);
|
|
1649
1722
|
} finally {
|
|
1650
1723
|
await stream.ready;
|
|
1651
1724
|
await stream.close();
|
|
@@ -1654,7 +1727,7 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
|
|
|
1654
1727
|
if (pipeError) {
|
|
1655
1728
|
throw pipeError;
|
|
1656
1729
|
}
|
|
1657
|
-
if (
|
|
1730
|
+
if (cachePlan && cacheChunks && cacheChunks.length > 0) {
|
|
1658
1731
|
const totalLength = cacheChunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
1659
1732
|
const combined = new Uint8Array(totalLength);
|
|
1660
1733
|
let offset = 0;
|
|
@@ -1662,86 +1735,16 @@ The request origin "${inputOrigin}" does not match the server origin "${origin}"
|
|
|
1662
1735
|
combined.set(chunk, offset);
|
|
1663
1736
|
offset += chunk.length;
|
|
1664
1737
|
}
|
|
1665
|
-
|
|
1738
|
+
const html = new TextDecoder().decode(combined);
|
|
1739
|
+
const cachedETag = cachePlan.eTag || hash(html);
|
|
1740
|
+
deps.setCachedSsr(cachePlan.key, {
|
|
1741
|
+
eTag: cachedETag,
|
|
1742
|
+
body: html
|
|
1743
|
+
});
|
|
1666
1744
|
}
|
|
1667
1745
|
await writableStream.close();
|
|
1668
1746
|
};
|
|
1669
1747
|
}
|
|
1670
|
-
async function handleQDataRedirect(requestEv) {
|
|
1671
|
-
try {
|
|
1672
|
-
await requestEv.next();
|
|
1673
|
-
} catch (err) {
|
|
1674
|
-
if (!(err instanceof deps.RedirectMessage)) {
|
|
1675
|
-
throw err;
|
|
1676
|
-
}
|
|
1677
|
-
}
|
|
1678
|
-
if (requestEv.headersSent) {
|
|
1679
|
-
return;
|
|
1680
|
-
}
|
|
1681
|
-
const status = requestEv.status();
|
|
1682
|
-
const location = requestEv.headers.get("Location");
|
|
1683
|
-
const isRedirect = status >= 301 && status <= 308 && location;
|
|
1684
|
-
if (isRedirect) {
|
|
1685
|
-
const adaptedLocation = makeQDataPath(location);
|
|
1686
|
-
if (adaptedLocation) {
|
|
1687
|
-
requestEv.headers.set("Location", adaptedLocation);
|
|
1688
|
-
requestEv.getWritableStream().close();
|
|
1689
|
-
return;
|
|
1690
|
-
} else {
|
|
1691
|
-
requestEv.status(200);
|
|
1692
|
-
requestEv.headers.delete("Location");
|
|
1693
|
-
}
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
async function renderQData(requestEv) {
|
|
1697
|
-
await requestEv.next();
|
|
1698
|
-
if (requestEv.headersSent || requestEv.exited) {
|
|
1699
|
-
return;
|
|
1700
|
-
}
|
|
1701
|
-
const status = requestEv.status();
|
|
1702
|
-
const redirectLocation = requestEv.headers.get("Location");
|
|
1703
|
-
requestEv.headers.set("Content-Type", "application/json; charset=utf-8");
|
|
1704
|
-
let loaders = deps.getRequestLoaders(requestEv);
|
|
1705
|
-
const selectedLoaderIds = requestEv.query.getAll(deps.QLOADER_KEY);
|
|
1706
|
-
const hasCustomLoaders = selectedLoaderIds.length > 0;
|
|
1707
|
-
if (hasCustomLoaders) {
|
|
1708
|
-
const selectedLoaders = {};
|
|
1709
|
-
for (const loaderId of selectedLoaderIds) {
|
|
1710
|
-
const loader = loaders[loaderId];
|
|
1711
|
-
selectedLoaders[loaderId] = loader;
|
|
1712
|
-
}
|
|
1713
|
-
loaders = selectedLoaders;
|
|
1714
|
-
}
|
|
1715
|
-
const qData = hasCustomLoaders ? {
|
|
1716
|
-
loaders,
|
|
1717
|
-
status: status !== 200 ? status : 200,
|
|
1718
|
-
href: getPathname(requestEv.url)
|
|
1719
|
-
} : {
|
|
1720
|
-
loaders,
|
|
1721
|
-
action: requestEv.sharedMap.get(deps.RequestEvSharedActionId),
|
|
1722
|
-
status: status !== 200 ? status : 200,
|
|
1723
|
-
href: getPathname(requestEv.url),
|
|
1724
|
-
redirect: redirectLocation ?? void 0,
|
|
1725
|
-
isRewrite: requestEv.sharedMap.get(deps.RequestEvIsRewrite)
|
|
1726
|
-
};
|
|
1727
|
-
const writer = requestEv.getWritableStream().getWriter();
|
|
1728
|
-
const data = await _serialize(qData);
|
|
1729
|
-
writer.write(deps.encoder.encode(data));
|
|
1730
|
-
requestEv.sharedMap.set(deps.RequestEvShareQData, qData);
|
|
1731
|
-
writer.close();
|
|
1732
|
-
}
|
|
1733
|
-
function makeQDataPath(href) {
|
|
1734
|
-
if (href.startsWith("/")) {
|
|
1735
|
-
if (!href.includes(deps.QDATA_JSON)) {
|
|
1736
|
-
const url = new URL(href, "http://localhost");
|
|
1737
|
-
const pathname = url.pathname.endsWith("/") ? url.pathname.slice(0, -1) : url.pathname;
|
|
1738
|
-
return pathname + deps.QDATA_JSON + url.search;
|
|
1739
|
-
}
|
|
1740
|
-
return href;
|
|
1741
|
-
} else {
|
|
1742
|
-
return void 0;
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
1748
|
function now() {
|
|
1746
1749
|
return typeof performance !== "undefined" ? performance.now() : 0;
|
|
1747
1750
|
}
|
|
@@ -1790,6 +1793,7 @@ function getQwikRouterServerDataWithDeps(deps, requestEv) {
|
|
|
1790
1793
|
const requestHeaders = {};
|
|
1791
1794
|
request.headers.forEach((value, key) => requestHeaders[key] = value);
|
|
1792
1795
|
const action = requestEv.sharedMap.get(deps.RequestEvSharedActionId);
|
|
1796
|
+
const actionResult = requestEv.sharedMap.get("@actionResult");
|
|
1793
1797
|
const formData = requestEv.sharedMap.get(deps.RequestEvSharedActionFormData);
|
|
1794
1798
|
const routeName = requestEv.sharedMap.get(deps.RequestRouteName);
|
|
1795
1799
|
const nonce = requestEv.sharedMap.get(deps.RequestEvSharedNonce);
|
|
@@ -1804,11 +1808,12 @@ function getQwikRouterServerDataWithDeps(deps, requestEv) {
|
|
|
1804
1808
|
if (protocol) {
|
|
1805
1809
|
reconstructedUrl.protocol = protocol;
|
|
1806
1810
|
}
|
|
1807
|
-
const
|
|
1808
|
-
const
|
|
1811
|
+
const routeLoaderCtx = getRouteLoaderCtx(requestEv);
|
|
1812
|
+
const loaderValues = getRouteLoaderValues(requestEv);
|
|
1809
1813
|
return {
|
|
1810
1814
|
url: reconstructedUrl.href,
|
|
1811
1815
|
requestHeaders,
|
|
1816
|
+
renderMode: deps.getRequestMode(requestEv),
|
|
1812
1817
|
locale: locale(),
|
|
1813
1818
|
nonce,
|
|
1814
1819
|
containerAttributes: {
|
|
@@ -1821,12 +1826,13 @@ function getQwikRouterServerDataWithDeps(deps, requestEv) {
|
|
|
1821
1826
|
...params
|
|
1822
1827
|
},
|
|
1823
1828
|
loadedRoute: deps.getRequestRoute(requestEv),
|
|
1829
|
+
routeLoaderCtx,
|
|
1830
|
+
loaderValues,
|
|
1824
1831
|
response: {
|
|
1825
1832
|
status: status(),
|
|
1826
1833
|
statusMessage: requestEv.sharedMap.get(deps.RequestEvHttpStatusMessage),
|
|
1827
|
-
loaders,
|
|
1828
|
-
loadersSerializationStrategy,
|
|
1829
1834
|
action,
|
|
1835
|
+
actionResult,
|
|
1830
1836
|
formData
|
|
1831
1837
|
}
|
|
1832
1838
|
}
|
|
@@ -1840,8 +1846,7 @@ const responsePageDeps = {
|
|
|
1840
1846
|
RequestEvSharedActionId,
|
|
1841
1847
|
RequestEvSharedNonce,
|
|
1842
1848
|
RequestRouteName,
|
|
1843
|
-
|
|
1844
|
-
getRequestLoaderSerializationStrategyMap,
|
|
1849
|
+
getRequestMode,
|
|
1845
1850
|
getRequestRoute
|
|
1846
1851
|
};
|
|
1847
1852
|
function getQwikRouterServerData(...args) {
|
|
@@ -1851,13 +1856,8 @@ function getQwikRouterServerData(...args) {
|
|
|
1851
1856
|
const requestHandlers = createResolveRequestHandlers({
|
|
1852
1857
|
QACTION_KEY,
|
|
1853
1858
|
QFN_KEY,
|
|
1854
|
-
QLOADER_KEY,
|
|
1855
|
-
QDATA_JSON,
|
|
1856
|
-
IsQData,
|
|
1857
1859
|
RequestEvETagCacheKey,
|
|
1858
1860
|
RequestEvHttpStatusMessage,
|
|
1859
|
-
RequestEvIsRewrite,
|
|
1860
|
-
RequestEvShareQData,
|
|
1861
1861
|
RequestEvShareServerTiming,
|
|
1862
1862
|
RequestEvSharedActionId,
|
|
1863
1863
|
RequestRouteName,
|
|
@@ -1866,18 +1866,19 @@ const requestHandlers = createResolveRequestHandlers({
|
|
|
1866
1866
|
HttpStatus,
|
|
1867
1867
|
encoder,
|
|
1868
1868
|
isContentType,
|
|
1869
|
-
|
|
1869
|
+
defaultSsrCacheKey,
|
|
1870
|
+
defaultLoaderCacheKey,
|
|
1871
|
+
getCachedSsr,
|
|
1872
|
+
getCachedLoader,
|
|
1870
1873
|
getQwikRouterServerData,
|
|
1871
|
-
getRequestLoaderSerializationStrategyMap,
|
|
1872
|
-
getRequestLoaders,
|
|
1873
1874
|
getRequestMode,
|
|
1874
|
-
getRouteLoaderPromise,
|
|
1875
1875
|
loadHttpError: () => import('./http-error.qwik.mjs'),
|
|
1876
1876
|
MAX_CACHE_SIZE,
|
|
1877
1877
|
resolveCacheKey,
|
|
1878
1878
|
resolveETag,
|
|
1879
1879
|
resolveRouteConfig,
|
|
1880
|
-
|
|
1880
|
+
setCachedSsr,
|
|
1881
|
+
setCachedLoader
|
|
1881
1882
|
});
|
|
1882
1883
|
const { renderQwikMiddleware, resolveRequestHandlers} = requestHandlers;
|
|
1883
1884
|
|
|
@@ -2090,6 +2091,7 @@ class RewriteMessage extends AbortMessage$1 {
|
|
|
2090
2091
|
|
|
2091
2092
|
const requestEventDeps = {
|
|
2092
2093
|
QDATA_KEY,
|
|
2094
|
+
QACTION_KEY,
|
|
2093
2095
|
isPromise,
|
|
2094
2096
|
createCacheControl,
|
|
2095
2097
|
Cookie,
|
|
@@ -2097,9 +2099,12 @@ const requestEventDeps = {
|
|
|
2097
2099
|
RedirectMessage,
|
|
2098
2100
|
RewriteMessage,
|
|
2099
2101
|
ServerError,
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2102
|
+
recognizeRequest,
|
|
2103
|
+
trimRecognizedInternalPathname,
|
|
2104
|
+
IsQLoader,
|
|
2105
|
+
IsQAction,
|
|
2106
|
+
QLoaderId,
|
|
2107
|
+
QActionId,
|
|
2103
2108
|
encoder,
|
|
2104
2109
|
getContentType
|
|
2105
2110
|
};
|
|
@@ -2271,18 +2276,13 @@ function runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, rebuildRou
|
|
|
2271
2276
|
}
|
|
2272
2277
|
|
|
2273
2278
|
const staticWorkerThreadDeps = {
|
|
2274
|
-
RequestEvShareQData,
|
|
2275
2279
|
loadRoute,
|
|
2276
2280
|
renderQwikMiddleware,
|
|
2277
2281
|
resolveRequestHandlers,
|
|
2278
|
-
|
|
2282
|
+
trimInternalPathname,
|
|
2279
2283
|
runQwikRouter
|
|
2280
2284
|
};
|
|
2281
2285
|
const createNoopWritableStream = () => new WritableStream();
|
|
2282
|
-
async function loadSerialize() {
|
|
2283
|
-
const { _serialize: serialize } = await import('@qwik.dev/core/internal');
|
|
2284
|
-
return serialize;
|
|
2285
|
-
}
|
|
2286
2286
|
function isRedirectMessage(value) {
|
|
2287
2287
|
return typeof value === "object" && value !== null && value.constructor?.name === "RedirectMessage";
|
|
2288
2288
|
}
|
|
@@ -2291,20 +2291,20 @@ async function requestHandlerForSsg(serverRequestEv, opts, deps) {
|
|
|
2291
2291
|
if (!qwikRouterConfig) {
|
|
2292
2292
|
throw new Error("qwikRouterConfig is required.");
|
|
2293
2293
|
}
|
|
2294
|
-
const
|
|
2294
|
+
const pathname = deps.trimInternalPathname(serverRequestEv.url.pathname);
|
|
2295
2295
|
if (pathname === "/.well-known" || pathname.startsWith("/.well-known/")) {
|
|
2296
2296
|
return null;
|
|
2297
2297
|
}
|
|
2298
2298
|
const { routes, serverPlugins, cacheModules } = qwikRouterConfig;
|
|
2299
|
-
const loadedRoute = await deps.loadRoute(routes, cacheModules, pathname
|
|
2300
|
-
const requestHandlers = deps.resolveRequestHandlers(serverPlugins, loadedRoute, serverRequestEv.request.method, checkOrigin ?? true, deps.renderQwikMiddleware(render)
|
|
2299
|
+
const loadedRoute = await deps.loadRoute(routes, cacheModules, pathname);
|
|
2300
|
+
const requestHandlers = deps.resolveRequestHandlers(serverPlugins, loadedRoute, serverRequestEv.request.method, checkOrigin ?? true, deps.renderQwikMiddleware(render));
|
|
2301
2301
|
if (qwikRouterConfig.fallthrough && loadedRoute.$notFound$) {
|
|
2302
2302
|
return null;
|
|
2303
2303
|
}
|
|
2304
2304
|
const rebuildRouteInfo = async (url) => {
|
|
2305
|
-
const
|
|
2306
|
-
const loadedRoute2 = await deps.loadRoute(routes, cacheModules,
|
|
2307
|
-
const requestHandlers2 = deps.resolveRequestHandlers(serverPlugins, loadedRoute2, serverRequestEv.request.method, checkOrigin ?? true, deps.renderQwikMiddleware(render)
|
|
2305
|
+
const cleanPathname = deps.trimInternalPathname(url.pathname);
|
|
2306
|
+
const loadedRoute2 = await deps.loadRoute(routes, cacheModules, cleanPathname);
|
|
2307
|
+
const requestHandlers2 = deps.resolveRequestHandlers(serverPlugins, loadedRoute2, serverRequestEv.request.method, checkOrigin ?? true, deps.renderQwikMiddleware(render));
|
|
2308
2308
|
return {
|
|
2309
2309
|
loadedRoute: loadedRoute2,
|
|
2310
2310
|
requestHandlers: requestHandlers2
|
|
@@ -2360,11 +2360,11 @@ async function workerRender(sys, opts, staticRoute, pendingPromises, callback, d
|
|
|
2360
2360
|
result.resourceType = "page";
|
|
2361
2361
|
}
|
|
2362
2362
|
const hasRouteWriter = isHtml ? opts.emitHtml !== false : true;
|
|
2363
|
-
const
|
|
2363
|
+
const writeLoaderDataEnabled = isHtml && opts.emitData !== false;
|
|
2364
2364
|
const stream = new WritableStream({
|
|
2365
2365
|
async start() {
|
|
2366
2366
|
try {
|
|
2367
|
-
if (hasRouteWriter ||
|
|
2367
|
+
if (hasRouteWriter || writeLoaderDataEnabled) {
|
|
2368
2368
|
await sys.ensureDir(routeFilePath);
|
|
2369
2369
|
}
|
|
2370
2370
|
if (hasRouteWriter) {
|
|
@@ -2404,23 +2404,34 @@ async function workerRender(sys, opts, staticRoute, pendingPromises, callback, d
|
|
|
2404
2404
|
async close() {
|
|
2405
2405
|
const writePromises = [];
|
|
2406
2406
|
try {
|
|
2407
|
-
if (
|
|
2408
|
-
const
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2407
|
+
if (writeLoaderDataEnabled && !is404ErrorPage) {
|
|
2408
|
+
const routeLoaders = getRouteLoaders(requestEv);
|
|
2409
|
+
const loaderValues = getRouteLoaderValues(requestEv);
|
|
2410
|
+
const manifestHash = opts.manifest?.manifestHash || "dev";
|
|
2411
|
+
for (const loader of routeLoaders) {
|
|
2412
|
+
if (loader.__expires !== 0) {
|
|
2413
|
+
continue;
|
|
2414
|
+
}
|
|
2415
|
+
const data = loaderValues[loader.__id];
|
|
2416
|
+
if (data === void 0) {
|
|
2417
|
+
continue;
|
|
2418
|
+
}
|
|
2419
|
+
const loaderFilePath = sys.getLoaderFilePath(url.pathname, loader.__id, manifestHash);
|
|
2420
|
+
const loaderWriter = sys.createWriteStream(loaderFilePath);
|
|
2421
|
+
loaderWriter.on("error", (e) => {
|
|
2413
2422
|
console.error(e);
|
|
2414
2423
|
result.error = {
|
|
2415
2424
|
message: e.message,
|
|
2416
2425
|
stack: e.stack
|
|
2417
2426
|
};
|
|
2418
2427
|
});
|
|
2419
|
-
const serialized = await deps.serialize(
|
|
2420
|
-
|
|
2428
|
+
const serialized = await deps.serialize({
|
|
2429
|
+
d: data
|
|
2430
|
+
});
|
|
2431
|
+
loaderWriter.write(serialized);
|
|
2421
2432
|
writePromises.push(new Promise((resolve) => {
|
|
2422
2433
|
result.filePath = routeFilePath;
|
|
2423
|
-
|
|
2434
|
+
loaderWriter.end(resolve);
|
|
2424
2435
|
}));
|
|
2425
2436
|
}
|
|
2426
2437
|
}
|
|
@@ -2506,7 +2517,7 @@ async function workerThread(sys) {
|
|
|
2506
2517
|
const pendingPromises = /* @__PURE__ */ new Set();
|
|
2507
2518
|
const deps = {
|
|
2508
2519
|
...staticWorkerThreadDeps,
|
|
2509
|
-
serialize:
|
|
2520
|
+
serialize: _serialize
|
|
2510
2521
|
};
|
|
2511
2522
|
process.on("uncaughtException", (e) => {
|
|
2512
2523
|
console.error("Worker uncaught exception (suppressed):", e.message);
|