@qwik.dev/router 2.0.0-beta.3 → 2.0.0-beta.5

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.
@@ -32,6 +32,7 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  AbortMessage: () => AbortMessage,
34
34
  RedirectMessage: () => RedirectMessage,
35
+ RequestEvShareQData: () => RequestEvShareQData,
35
36
  RewriteMessage: () => RewriteMessage,
36
37
  ServerError: () => ServerError,
37
38
  _TextEncoderStream_polyfill: () => _TextEncoderStream_polyfill,
@@ -272,8 +273,11 @@ var RewriteMessage = class extends AbortMessage {
272
273
  // packages/qwik-router/src/runtime/src/constants.ts
273
274
  var MODULE_CACHE = /* @__PURE__ */ new WeakMap();
274
275
  var QACTION_KEY = "qaction";
276
+ var QLOADER_KEY = "qloaders";
275
277
  var QFN_KEY = "qfunc";
276
278
  var QDATA_KEY = "qdata";
279
+ var Q_ROUTE = "q:route";
280
+ var DEFAULT_LOADERS_SERIALIZATION_STRATEGY = globalThis.__DEFAULT_LOADERS_SERIALIZATION_STRATEGY__ || "never";
277
281
 
278
282
  // packages/qwik-router/src/runtime/src/route-matcher.ts
279
283
  function matchRoute(route, path) {
@@ -395,6 +399,17 @@ function lastIndexOf(text, start, match, searchIdx, notFoundIdx) {
395
399
  return idx > start ? idx : notFoundIdx;
396
400
  }
397
401
 
402
+ // packages/qwik-router/src/runtime/src/utils.ts
403
+ var import_core2 = require("@qwik.dev/core");
404
+ var import_internal2 = require("@qwik.dev/core/internal");
405
+
406
+ // packages/qwik-router/src/runtime/src/use-endpoint.ts
407
+ var import_internal = require("@qwik.dev/core/internal");
408
+
409
+ // packages/qwik-router/src/runtime/src/client-navigate.ts
410
+ var import_core = require("@qwik.dev/core");
411
+ var import_preloader = require("@qwik.dev/core/preloader");
412
+
398
413
  // packages/qwik-router/src/runtime/src/utils.ts
399
414
  var isPromise = (value) => {
400
415
  return value && typeof value.then === "function";
@@ -418,13 +433,13 @@ var loadRoute = async (routes, menus, cacheModules, pathname) => {
418
433
  return null;
419
434
  }
420
435
  for (const routeData of routes) {
421
- const routeName = routeData[0];
436
+ const routeName = routeData[0 /* RouteName */];
422
437
  const params = matchRoute(routeName, pathname);
423
438
  if (!params) {
424
439
  continue;
425
440
  }
426
- const loaders = routeData[1];
427
- const routeBundleNames = routeData[3];
441
+ const loaders = routeData[1 /* Loaders */];
442
+ const routeBundleNames = routeData[3 /* RouteBundleNames */];
428
443
  const modules = new Array(loaders.length);
429
444
  const pendingLoads = [];
430
445
  loaders.forEach((moduleLoader, i) => {
@@ -476,14 +491,20 @@ var getMenuLoader = (menus, pathname) => {
476
491
  if (menus) {
477
492
  pathname = pathname.endsWith("/") ? pathname : pathname + "/";
478
493
  const menu = menus.find(
479
- (m) => m[0] === pathname || pathname.startsWith(m[0] + (pathname.endsWith("/") ? "" : "/"))
494
+ (m) => m[0 /* Pathname */] === pathname || pathname.startsWith(m[0 /* Pathname */] + (pathname.endsWith("/") ? "" : "/"))
480
495
  );
481
496
  if (menu) {
482
- return menu[1];
497
+ return menu[1 /* MenuLoader */];
483
498
  }
484
499
  }
485
500
  };
486
501
 
502
+ // packages/qwik-router/src/middleware/request-handler/resolve-request-handlers.ts
503
+ var import_internal4 = require("@qwik.dev/core/internal");
504
+
505
+ // packages/qwik-router/src/middleware/request-handler/request-event.ts
506
+ var import_internal3 = require("@qwik.dev/core/internal");
507
+
487
508
  // packages/qwik-router/src/middleware/request-handler/cache-control.ts
488
509
  function createCacheControl(cacheControl) {
489
510
  const controls = [];
@@ -659,12 +680,17 @@ var RequestEvLoaders = Symbol("RequestEvLoaders");
659
680
  var RequestEvMode = Symbol("RequestEvMode");
660
681
  var RequestEvRoute = Symbol("RequestEvRoute");
661
682
  var RequestEvQwikSerializer = Symbol("RequestEvQwikSerializer");
683
+ var RequestEvLoaderSerializationStrategyMap = Symbol(
684
+ "RequestEvLoaderSerializationStrategyMap"
685
+ );
662
686
  var RequestEvTrailingSlash = Symbol("RequestEvTrailingSlash");
663
687
  var RequestRouteName = "@routeName";
664
688
  var RequestEvSharedActionId = "@actionId";
665
689
  var RequestEvSharedActionFormData = "@actionFormData";
666
690
  var RequestEvSharedNonce = "@nonce";
667
691
  var RequestEvIsRewrite = "@rewrite";
692
+ var RequestEvShareServerTiming = "@serverTiming";
693
+ var RequestEvShareQData = "qData";
668
694
  function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trailingSlash, basePathname, qwikSerializer, resolved) {
669
695
  const { request, platform, env } = serverRequestEv;
670
696
  const sharedMap = /* @__PURE__ */ new Map();
@@ -748,6 +774,7 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trail
748
774
  const loaders = {};
749
775
  const requestEv = {
750
776
  [RequestEvLoaders]: loaders,
777
+ [RequestEvLoaderSerializationStrategyMap]: /* @__PURE__ */ new Map(),
751
778
  [RequestEvMode]: serverRequestEv.mode,
752
779
  [RequestEvTrailingSlash]: trailingSlash,
753
780
  get [RequestEvRoute]() {
@@ -761,7 +788,7 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trail
761
788
  signal: request.signal,
762
789
  originalUrl: new URL(url),
763
790
  get params() {
764
- return (loadedRoute == null ? void 0 : loadedRoute[1]) ?? {};
791
+ return (loadedRoute == null ? void 0 : loadedRoute[1 /* Params */]) ?? {};
765
792
  },
766
793
  get pathname() {
767
794
  return url.pathname;
@@ -798,6 +825,10 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trail
798
825
  "You can not get the returned data of a loader that has not been executed for this request."
799
826
  );
800
827
  }
828
+ if (loaders[id] === import_internal3._UNINITIALIZED) {
829
+ const isDev = getRequestMode(requestEv) === "dev";
830
+ await getRouteLoaderPromise(loaderOrAction, loaders, requestEv, isDev, qwikSerializer);
831
+ }
801
832
  }
802
833
  return loaders[id];
803
834
  },
@@ -879,9 +910,12 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trail
879
910
  getWritableStream: () => {
880
911
  if (writableStream === null) {
881
912
  if (serverRequestEv.mode === "dev") {
882
- const serverTiming = sharedMap.get("@serverTiming");
913
+ const serverTiming = sharedMap.get(RequestEvShareServerTiming);
883
914
  if (serverTiming) {
884
- headers.set("Server-Timing", serverTiming.map((a) => `${a[0]};dur=${a[1]}`).join(","));
915
+ headers.set(
916
+ "Server-Timing",
917
+ serverTiming.map(([name, duration]) => `${name};dur=${duration}`).join(",")
918
+ );
885
919
  }
886
920
  }
887
921
  writableStream = serverRequestEv.getWritableStream(
@@ -900,6 +934,9 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trail
900
934
  function getRequestLoaders(requestEv) {
901
935
  return requestEv[RequestEvLoaders];
902
936
  }
937
+ function getRequestLoaderSerializationStrategyMap(requestEv) {
938
+ return requestEv[RequestEvLoaderSerializationStrategyMap];
939
+ }
903
940
  function getRequestTrailingSlash(requestEv) {
904
941
  return requestEv[RequestEvTrailingSlash];
905
942
  }
@@ -972,13 +1009,15 @@ function getQwikRouterServerData(requestEv) {
972
1009
  if (protocol) {
973
1010
  reconstructedUrl.protocol = protocol;
974
1011
  }
1012
+ const loaders = getRequestLoaders(requestEv);
1013
+ const loadersSerializationStrategy = getRequestLoaderSerializationStrategyMap(requestEv);
975
1014
  return {
976
1015
  url: reconstructedUrl.href,
977
1016
  requestHeaders,
978
1017
  locale: locale(),
979
1018
  nonce,
980
1019
  containerAttributes: {
981
- "q:route": routeName
1020
+ [Q_ROUTE]: routeName
982
1021
  },
983
1022
  qwikrouter: {
984
1023
  routeName,
@@ -987,7 +1026,8 @@ function getQwikRouterServerData(requestEv) {
987
1026
  loadedRoute: getRequestRoute(requestEv),
988
1027
  response: {
989
1028
  status: status(),
990
- loaders: getRequestLoaders(requestEv),
1029
+ loaders,
1030
+ loadersSerializationStrategy,
991
1031
  action,
992
1032
  formData
993
1033
  }
@@ -1000,7 +1040,7 @@ var resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderH
1000
1040
  const routeLoaders = [];
1001
1041
  const routeActions = [];
1002
1042
  const requestHandlers = [];
1003
- const isPageRoute = !!(route && isLastModulePageRoute(route[2]));
1043
+ const isPageRoute = !!(route && isLastModulePageRoute(route[2 /* Mods */]));
1004
1044
  if (serverPlugins) {
1005
1045
  _resolveRequestHandlers(
1006
1046
  routeLoaders,
@@ -1012,7 +1052,7 @@ var resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderH
1012
1052
  );
1013
1053
  }
1014
1054
  if (route) {
1015
- const routeName = route[0];
1055
+ const routeName = route[0 /* RouteName */];
1016
1056
  if (checkOrigin && (method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE")) {
1017
1057
  requestHandlers.unshift(csrfCheckMiddleware);
1018
1058
  }
@@ -1023,7 +1063,7 @@ var resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderH
1023
1063
  requestHandlers.push(fixTrailingSlash);
1024
1064
  requestHandlers.push(renderQData);
1025
1065
  }
1026
- const routeModules = route[2];
1066
+ const routeModules = route[2 /* Mods */];
1027
1067
  requestHandlers.push(handleRedirect);
1028
1068
  _resolveRequestHandlers(
1029
1069
  routeLoaders,
@@ -1037,7 +1077,8 @@ var resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderH
1037
1077
  requestHandlers.push((ev) => {
1038
1078
  ev.sharedMap.set(RequestRouteName, routeName);
1039
1079
  });
1040
- requestHandlers.push(actionsMiddleware(routeActions, routeLoaders));
1080
+ requestHandlers.push(actionsMiddleware(routeActions));
1081
+ requestHandlers.push(loadersMiddleware(routeLoaders));
1041
1082
  requestHandlers.push(renderHandler);
1042
1083
  }
1043
1084
  }
@@ -1099,8 +1140,9 @@ var _resolveRequestHandlers = (routeLoaders, routeActions, requestHandlers, rout
1099
1140
  }
1100
1141
  }
1101
1142
  };
1102
- function actionsMiddleware(routeActions, routeLoaders) {
1103
- return async (requestEv) => {
1143
+ function actionsMiddleware(routeActions) {
1144
+ return async (requestEvent) => {
1145
+ const requestEv = requestEvent;
1104
1146
  if (requestEv.headersSent) {
1105
1147
  requestEv.exit();
1106
1148
  return;
@@ -1135,7 +1177,7 @@ function actionsMiddleware(routeActions, routeLoaders) {
1135
1177
  } else {
1136
1178
  const actionResolved = isDev ? await measure(
1137
1179
  requestEv,
1138
- action.__qrl.getSymbol().split("_", 1)[0],
1180
+ action.__qrl.getHash(),
1139
1181
  () => action.__qrl.call(requestEv, result.data, requestEv)
1140
1182
  ) : await action.__qrl.call(requestEv, result.data, requestEv);
1141
1183
  if (isDev) {
@@ -1146,46 +1188,76 @@ function actionsMiddleware(routeActions, routeLoaders) {
1146
1188
  }
1147
1189
  }
1148
1190
  }
1191
+ };
1192
+ }
1193
+ function loadersMiddleware(routeLoaders) {
1194
+ return async (requestEvent) => {
1195
+ const requestEv = requestEvent;
1196
+ if (requestEv.headersSent) {
1197
+ requestEv.exit();
1198
+ return;
1199
+ }
1200
+ const loaders = getRequestLoaders(requestEv);
1201
+ const isDev = getRequestMode(requestEv) === "dev";
1202
+ const qwikSerializer = requestEv[RequestEvQwikSerializer];
1149
1203
  if (routeLoaders.length > 0) {
1150
- const resolvedLoadersPromises = routeLoaders.map((loader) => {
1151
- const loaderId = loader.__id;
1152
- loaders[loaderId] = runValidators(
1153
- requestEv,
1154
- loader.__validators,
1155
- void 0,
1156
- // data
1157
- isDev
1158
- ).then((res) => {
1159
- if (res.success) {
1160
- if (isDev) {
1161
- return measure(
1162
- requestEv,
1163
- loader.__qrl.getSymbol().split("_", 1)[0],
1164
- () => loader.__qrl.call(requestEv, requestEv)
1165
- );
1166
- } else {
1167
- return loader.__qrl.call(requestEv, requestEv);
1168
- }
1204
+ let currentLoaders = [];
1205
+ if (requestEv.query.has(QLOADER_KEY)) {
1206
+ const selectedLoaderIds = requestEv.query.getAll(QLOADER_KEY);
1207
+ for (const loader of routeLoaders) {
1208
+ if (selectedLoaderIds.includes(loader.__id)) {
1209
+ currentLoaders.push(loader);
1169
1210
  } else {
1170
- return requestEv.fail(res.status ?? 500, res.error);
1211
+ loaders[loader.__id] = import_internal4._UNINITIALIZED;
1171
1212
  }
1172
- }).then((resolvedLoader) => {
1173
- if (typeof resolvedLoader === "function") {
1174
- loaders[loaderId] = resolvedLoader();
1175
- } else {
1176
- if (isDev) {
1177
- verifySerializable(qwikSerializer, resolvedLoader, loader.__qrl);
1178
- }
1179
- loaders[loaderId] = resolvedLoader;
1180
- }
1181
- return resolvedLoader;
1182
- });
1183
- return loaders[loaderId];
1184
- });
1213
+ }
1214
+ } else {
1215
+ currentLoaders = routeLoaders;
1216
+ }
1217
+ const resolvedLoadersPromises = currentLoaders.map(
1218
+ (loader) => getRouteLoaderPromise(loader, loaders, requestEv, isDev, qwikSerializer)
1219
+ );
1185
1220
  await Promise.all(resolvedLoadersPromises);
1186
1221
  }
1187
1222
  };
1188
1223
  }
1224
+ async function getRouteLoaderPromise(loader, loaders, requestEv, isDev, qwikSerializer) {
1225
+ const loaderId = loader.__id;
1226
+ loaders[loaderId] = runValidators(
1227
+ requestEv,
1228
+ loader.__validators,
1229
+ void 0,
1230
+ // data
1231
+ isDev
1232
+ ).then((res) => {
1233
+ if (res.success) {
1234
+ if (isDev) {
1235
+ return measure(
1236
+ requestEv,
1237
+ loader.__qrl.getHash(),
1238
+ () => loader.__qrl.call(requestEv, requestEv)
1239
+ );
1240
+ } else {
1241
+ return loader.__qrl.call(requestEv, requestEv);
1242
+ }
1243
+ } else {
1244
+ return requestEv.fail(res.status ?? 500, res.error);
1245
+ }
1246
+ }).then((resolvedLoader) => {
1247
+ if (typeof resolvedLoader === "function") {
1248
+ loaders[loaderId] = resolvedLoader();
1249
+ } else {
1250
+ if (isDev) {
1251
+ verifySerializable(qwikSerializer, resolvedLoader, loader.__qrl);
1252
+ }
1253
+ loaders[loaderId] = resolvedLoader;
1254
+ }
1255
+ return resolvedLoader;
1256
+ });
1257
+ const loadersSerializationStrategy = getRequestLoaderSerializationStrategyMap(requestEv);
1258
+ loadersSerializationStrategy.set(loaderId, loader.__serializationStrategy);
1259
+ return loaders[loaderId];
1260
+ }
1189
1261
  async function runValidators(requestEv, validators, data, isDev) {
1190
1262
  let lastResult = {
1191
1263
  success: true,
@@ -1320,7 +1392,7 @@ function getPathname(url, trailingSlash) {
1320
1392
  url.pathname = url.pathname.slice(0, -1);
1321
1393
  }
1322
1394
  }
1323
- const search = url.search.slice(1).replaceAll(/&?q(action|data|func)=[^&]+/g, "");
1395
+ const search = url.search.slice(1).replaceAll(/&?q(action|data|func|loaders)=[^&]+/g, "");
1324
1396
  return `${url.pathname}${search ? `?${search}` : ""}${url.hash}`;
1325
1397
  }
1326
1398
  var encoder = /* @__PURE__ */ new TextEncoder();
@@ -1386,7 +1458,7 @@ function renderQwikMiddleware(render) {
1386
1458
  if (typeof result.html === "string") {
1387
1459
  await stream.write(result.html);
1388
1460
  }
1389
- requestEv.sharedMap.set("qData", qData);
1461
+ requestEv.sharedMap.set(RequestEvShareQData, qData);
1390
1462
  } finally {
1391
1463
  await stream.ready;
1392
1464
  await stream.close();
@@ -1411,10 +1483,10 @@ async function handleRedirect(requestEv) {
1411
1483
  return;
1412
1484
  }
1413
1485
  const status = requestEv.status();
1414
- const location = requestEv.headers.get("Location");
1415
- const isRedirect = status >= 301 && status <= 308 && location;
1486
+ const location2 = requestEv.headers.get("Location");
1487
+ const isRedirect = status >= 301 && status <= 308 && location2;
1416
1488
  if (isRedirect) {
1417
- const adaptedLocation = makeQDataPath(location);
1489
+ const adaptedLocation = makeQDataPath(location2);
1418
1490
  if (adaptedLocation) {
1419
1491
  requestEv.headers.set("Location", adaptedLocation);
1420
1492
  requestEv.getWritableStream().close();
@@ -1440,8 +1512,24 @@ async function renderQData(requestEv) {
1440
1512
  const requestHeaders = {};
1441
1513
  requestEv.request.headers.forEach((value, key) => requestHeaders[key] = value);
1442
1514
  requestEv.headers.set("Content-Type", "application/json; charset=utf-8");
1443
- const qData = {
1444
- loaders: getRequestLoaders(requestEv),
1515
+ let loaders = getRequestLoaders(requestEv);
1516
+ const selectedLoaderIds = requestEv.query.getAll(QLOADER_KEY);
1517
+ const hasCustomLoaders = selectedLoaderIds.length > 0;
1518
+ if (hasCustomLoaders) {
1519
+ const selectedLoaders = {};
1520
+ for (const loaderId of selectedLoaderIds) {
1521
+ const loader = loaders[loaderId];
1522
+ selectedLoaders[loaderId] = loader;
1523
+ }
1524
+ loaders = selectedLoaders;
1525
+ }
1526
+ const qData = hasCustomLoaders ? {
1527
+ // send minimal data to the client
1528
+ loaders,
1529
+ status: status !== 200 ? status : 200,
1530
+ href: getPathname(requestEv.url, trailingSlash)
1531
+ } : {
1532
+ loaders,
1445
1533
  action: requestEv.sharedMap.get(RequestEvSharedActionId),
1446
1534
  status: status !== 200 ? status : 200,
1447
1535
  href: getPathname(requestEv.url, trailingSlash),
@@ -1452,7 +1540,7 @@ async function renderQData(requestEv) {
1452
1540
  const qwikSerializer = requestEv[RequestEvQwikSerializer];
1453
1541
  const data = await qwikSerializer._serialize([qData]);
1454
1542
  writer.write(encoder.encode(data));
1455
- requestEv.sharedMap.set("qData", qData);
1543
+ requestEv.sharedMap.set(RequestEvShareQData, qData);
1456
1544
  writer.close();
1457
1545
  }
1458
1546
  function makeQDataPath(href) {
@@ -1474,9 +1562,9 @@ async function measure(requestEv, name, fn) {
1474
1562
  return await fn();
1475
1563
  } finally {
1476
1564
  const duration = now() - start;
1477
- let measurements = requestEv.sharedMap.get("@serverTiming");
1565
+ let measurements = requestEv.sharedMap.get(RequestEvShareServerTiming);
1478
1566
  if (!measurements) {
1479
- requestEv.sharedMap.set("@serverTiming", measurements = []);
1567
+ requestEv.sharedMap.set(RequestEvShareServerTiming, measurements = []);
1480
1568
  }
1481
1569
  measurements.push([name, duration]);
1482
1570
  }
@@ -1605,6 +1693,7 @@ var _TextEncoderStream_polyfill = class {
1605
1693
  0 && (module.exports = {
1606
1694
  AbortMessage,
1607
1695
  RedirectMessage,
1696
+ RequestEvShareQData,
1608
1697
  RewriteMessage,
1609
1698
  ServerError,
1610
1699
  _TextEncoderStream_polyfill,
@@ -11,6 +11,7 @@ import type { RenderOptions } from '@qwik.dev/core/server';
11
11
  import { RequestEvent as RequestEvent_2 } from '@qwik.dev/router/middleware/request-handler';
12
12
  import type { RequestHandler as RequestHandler_2 } from '@qwik.dev/router/middleware/request-handler';
13
13
  import type { ResolveSyncValue as ResolveSyncValue_2 } from '@qwik.dev/router/middleware/request-handler';
14
+ import { SerializationStrategy } from '@qwik.dev/core/internal';
14
15
  import type { _serialize } from '@qwik.dev/core/internal';
15
16
  import type { ValueOrPromise } from '@qwik.dev/core';
16
17
  import type { _verifySerializable } from '@qwik.dev/core/internal';
@@ -530,6 +531,7 @@ export declare interface RequestEventCommon<PLATFORM = QwikRouterPlatform> exten
530
531
 
531
532
  declare interface RequestEventInternal extends RequestEvent, RequestEventLoader {
532
533
  [RequestEvLoaders]: Record<string, ValueOrPromise<unknown> | undefined>;
534
+ [RequestEvLoaderSerializationStrategyMap]: Map<string, SerializationStrategy>;
533
535
  [RequestEvMode]: ServerRequestMode;
534
536
  [RequestEvTrailingSlash]: boolean;
535
537
  [RequestEvRoute]: LoadedRoute | null;
@@ -558,12 +560,17 @@ export declare interface RequestEventLoader<PLATFORM = QwikRouterPlatform> exten
558
560
 
559
561
  declare const RequestEvLoaders: unique symbol;
560
562
 
563
+ declare const RequestEvLoaderSerializationStrategyMap: unique symbol;
564
+
561
565
  declare const RequestEvMode: unique symbol;
562
566
 
563
567
  declare const RequestEvQwikSerializer: unique symbol;
564
568
 
565
569
  declare const RequestEvRoute: unique symbol;
566
570
 
571
+ /** @internal */
572
+ export declare const RequestEvShareQData = "qData";
573
+
567
574
  declare const RequestEvTrailingSlash: unique symbol;
568
575
 
569
576
  /** @public */