@qwik.dev/router 2.0.0-beta.2 → 2.0.0-beta.4

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,10 +491,10 @@ 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
  };
@@ -659,12 +674,17 @@ var RequestEvLoaders = Symbol("RequestEvLoaders");
659
674
  var RequestEvMode = Symbol("RequestEvMode");
660
675
  var RequestEvRoute = Symbol("RequestEvRoute");
661
676
  var RequestEvQwikSerializer = Symbol("RequestEvQwikSerializer");
677
+ var RequestEvLoaderSerializationStrategyMap = Symbol(
678
+ "RequestEvLoaderSerializationStrategyMap"
679
+ );
662
680
  var RequestEvTrailingSlash = Symbol("RequestEvTrailingSlash");
663
681
  var RequestRouteName = "@routeName";
664
682
  var RequestEvSharedActionId = "@actionId";
665
683
  var RequestEvSharedActionFormData = "@actionFormData";
666
684
  var RequestEvSharedNonce = "@nonce";
667
685
  var RequestEvIsRewrite = "@rewrite";
686
+ var RequestEvShareServerTiming = "@serverTiming";
687
+ var RequestEvShareQData = "qData";
668
688
  function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trailingSlash, basePathname, qwikSerializer, resolved) {
669
689
  const { request, platform, env } = serverRequestEv;
670
690
  const sharedMap = /* @__PURE__ */ new Map();
@@ -748,6 +768,7 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trail
748
768
  const loaders = {};
749
769
  const requestEv = {
750
770
  [RequestEvLoaders]: loaders,
771
+ [RequestEvLoaderSerializationStrategyMap]: /* @__PURE__ */ new Map(),
751
772
  [RequestEvMode]: serverRequestEv.mode,
752
773
  [RequestEvTrailingSlash]: trailingSlash,
753
774
  get [RequestEvRoute]() {
@@ -761,7 +782,7 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trail
761
782
  signal: request.signal,
762
783
  originalUrl: new URL(url),
763
784
  get params() {
764
- return (loadedRoute == null ? void 0 : loadedRoute[1]) ?? {};
785
+ return (loadedRoute == null ? void 0 : loadedRoute[1 /* Params */]) ?? {};
765
786
  },
766
787
  get pathname() {
767
788
  return url.pathname;
@@ -879,9 +900,12 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trail
879
900
  getWritableStream: () => {
880
901
  if (writableStream === null) {
881
902
  if (serverRequestEv.mode === "dev") {
882
- const serverTiming = sharedMap.get("@serverTiming");
903
+ const serverTiming = sharedMap.get(RequestEvShareServerTiming);
883
904
  if (serverTiming) {
884
- headers.set("Server-Timing", serverTiming.map((a) => `${a[0]};dur=${a[1]}`).join(","));
905
+ headers.set(
906
+ "Server-Timing",
907
+ serverTiming.map(([name, duration]) => `${name};dur=${duration}`).join(",")
908
+ );
885
909
  }
886
910
  }
887
911
  writableStream = serverRequestEv.getWritableStream(
@@ -900,6 +924,9 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trail
900
924
  function getRequestLoaders(requestEv) {
901
925
  return requestEv[RequestEvLoaders];
902
926
  }
927
+ function getRequestLoaderSerializationStrategyMap(requestEv) {
928
+ return requestEv[RequestEvLoaderSerializationStrategyMap];
929
+ }
903
930
  function getRequestTrailingSlash(requestEv) {
904
931
  return requestEv[RequestEvTrailingSlash];
905
932
  }
@@ -972,13 +999,15 @@ function getQwikRouterServerData(requestEv) {
972
999
  if (protocol) {
973
1000
  reconstructedUrl.protocol = protocol;
974
1001
  }
1002
+ const loaders = getRequestLoaders(requestEv);
1003
+ const loadersSerializationStrategy = getRequestLoaderSerializationStrategyMap(requestEv);
975
1004
  return {
976
1005
  url: reconstructedUrl.href,
977
1006
  requestHeaders,
978
1007
  locale: locale(),
979
1008
  nonce,
980
1009
  containerAttributes: {
981
- "q:route": routeName
1010
+ [Q_ROUTE]: routeName
982
1011
  },
983
1012
  qwikrouter: {
984
1013
  routeName,
@@ -987,7 +1016,8 @@ function getQwikRouterServerData(requestEv) {
987
1016
  loadedRoute: getRequestRoute(requestEv),
988
1017
  response: {
989
1018
  status: status(),
990
- loaders: getRequestLoaders(requestEv),
1019
+ loaders,
1020
+ loadersSerializationStrategy,
991
1021
  action,
992
1022
  formData
993
1023
  }
@@ -1000,7 +1030,7 @@ var resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderH
1000
1030
  const routeLoaders = [];
1001
1031
  const routeActions = [];
1002
1032
  const requestHandlers = [];
1003
- const isPageRoute = !!(route && isLastModulePageRoute(route[2]));
1033
+ const isPageRoute = !!(route && isLastModulePageRoute(route[2 /* Mods */]));
1004
1034
  if (serverPlugins) {
1005
1035
  _resolveRequestHandlers(
1006
1036
  routeLoaders,
@@ -1012,7 +1042,7 @@ var resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderH
1012
1042
  );
1013
1043
  }
1014
1044
  if (route) {
1015
- const routeName = route[0];
1045
+ const routeName = route[0 /* RouteName */];
1016
1046
  if (checkOrigin && (method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE")) {
1017
1047
  requestHandlers.unshift(csrfCheckMiddleware);
1018
1048
  }
@@ -1023,7 +1053,7 @@ var resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderH
1023
1053
  requestHandlers.push(fixTrailingSlash);
1024
1054
  requestHandlers.push(renderQData);
1025
1055
  }
1026
- const routeModules = route[2];
1056
+ const routeModules = route[2 /* Mods */];
1027
1057
  requestHandlers.push(handleRedirect);
1028
1058
  _resolveRequestHandlers(
1029
1059
  routeLoaders,
@@ -1037,7 +1067,8 @@ var resolveRequestHandlers = (serverPlugins, route, method, checkOrigin, renderH
1037
1067
  requestHandlers.push((ev) => {
1038
1068
  ev.sharedMap.set(RequestRouteName, routeName);
1039
1069
  });
1040
- requestHandlers.push(actionsMiddleware(routeActions, routeLoaders));
1070
+ requestHandlers.push(actionsMiddleware(routeActions));
1071
+ requestHandlers.push(loadersMiddleware(routeLoaders));
1041
1072
  requestHandlers.push(renderHandler);
1042
1073
  }
1043
1074
  }
@@ -1099,8 +1130,9 @@ var _resolveRequestHandlers = (routeLoaders, routeActions, requestHandlers, rout
1099
1130
  }
1100
1131
  }
1101
1132
  };
1102
- function actionsMiddleware(routeActions, routeLoaders) {
1103
- return async (requestEv) => {
1133
+ function actionsMiddleware(routeActions) {
1134
+ return async (requestEvent) => {
1135
+ const requestEv = requestEvent;
1104
1136
  if (requestEv.headersSent) {
1105
1137
  requestEv.exit();
1106
1138
  return;
@@ -1135,7 +1167,7 @@ function actionsMiddleware(routeActions, routeLoaders) {
1135
1167
  } else {
1136
1168
  const actionResolved = isDev ? await measure(
1137
1169
  requestEv,
1138
- action.__qrl.getSymbol().split("_", 1)[0],
1170
+ action.__qrl.getHash(),
1139
1171
  () => action.__qrl.call(requestEv, result.data, requestEv)
1140
1172
  ) : await action.__qrl.call(requestEv, result.data, requestEv);
1141
1173
  if (isDev) {
@@ -1146,46 +1178,74 @@ function actionsMiddleware(routeActions, routeLoaders) {
1146
1178
  }
1147
1179
  }
1148
1180
  }
1181
+ };
1182
+ }
1183
+ function loadersMiddleware(routeLoaders) {
1184
+ return async (requestEvent) => {
1185
+ const requestEv = requestEvent;
1186
+ if (requestEv.headersSent) {
1187
+ requestEv.exit();
1188
+ return;
1189
+ }
1190
+ const loaders = getRequestLoaders(requestEv);
1191
+ const isDev = getRequestMode(requestEv) === "dev";
1192
+ const qwikSerializer = requestEv[RequestEvQwikSerializer];
1149
1193
  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
- }
1169
- } else {
1170
- return requestEv.fail(res.status ?? 500, res.error);
1194
+ let currentLoaders = [];
1195
+ if (requestEv.query.has(QLOADER_KEY)) {
1196
+ const selectedLoaderIds = requestEv.query.getAll(QLOADER_KEY);
1197
+ for (const loader of routeLoaders) {
1198
+ if (selectedLoaderIds.includes(loader.__id)) {
1199
+ currentLoaders.push(loader);
1171
1200
  }
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
- });
1201
+ }
1202
+ } else {
1203
+ currentLoaders = routeLoaders;
1204
+ }
1205
+ const resolvedLoadersPromises = currentLoaders.map(
1206
+ (loader) => getRouteLoaderPromise(loader, loaders, requestEv, isDev, qwikSerializer)
1207
+ );
1185
1208
  await Promise.all(resolvedLoadersPromises);
1186
1209
  }
1187
1210
  };
1188
1211
  }
1212
+ async function getRouteLoaderPromise(loader, loaders, requestEv, isDev, qwikSerializer) {
1213
+ const loaderId = loader.__id;
1214
+ loaders[loaderId] = runValidators(
1215
+ requestEv,
1216
+ loader.__validators,
1217
+ void 0,
1218
+ // data
1219
+ isDev
1220
+ ).then((res) => {
1221
+ if (res.success) {
1222
+ if (isDev) {
1223
+ return measure(
1224
+ requestEv,
1225
+ loader.__qrl.getHash(),
1226
+ () => loader.__qrl.call(requestEv, requestEv)
1227
+ );
1228
+ } else {
1229
+ return loader.__qrl.call(requestEv, requestEv);
1230
+ }
1231
+ } else {
1232
+ return requestEv.fail(res.status ?? 500, res.error);
1233
+ }
1234
+ }).then((resolvedLoader) => {
1235
+ if (typeof resolvedLoader === "function") {
1236
+ loaders[loaderId] = resolvedLoader();
1237
+ } else {
1238
+ if (isDev) {
1239
+ verifySerializable(qwikSerializer, resolvedLoader, loader.__qrl);
1240
+ }
1241
+ loaders[loaderId] = resolvedLoader;
1242
+ }
1243
+ return resolvedLoader;
1244
+ });
1245
+ const loadersSerializationStrategy = getRequestLoaderSerializationStrategyMap(requestEv);
1246
+ loadersSerializationStrategy.set(loaderId, loader.__serializationStrategy);
1247
+ return loaders[loaderId];
1248
+ }
1189
1249
  async function runValidators(requestEv, validators, data, isDev) {
1190
1250
  let lastResult = {
1191
1251
  success: true,
@@ -1320,7 +1380,7 @@ function getPathname(url, trailingSlash) {
1320
1380
  url.pathname = url.pathname.slice(0, -1);
1321
1381
  }
1322
1382
  }
1323
- const search = url.search.slice(1).replaceAll(/&?q(action|data|func)=[^&]+/g, "");
1383
+ const search = url.search.slice(1).replaceAll(/&?q(action|data|func|loaders)=[^&]+/g, "");
1324
1384
  return `${url.pathname}${search ? `?${search}` : ""}${url.hash}`;
1325
1385
  }
1326
1386
  var encoder = /* @__PURE__ */ new TextEncoder();
@@ -1386,7 +1446,7 @@ function renderQwikMiddleware(render) {
1386
1446
  if (typeof result.html === "string") {
1387
1447
  await stream.write(result.html);
1388
1448
  }
1389
- requestEv.sharedMap.set("qData", qData);
1449
+ requestEv.sharedMap.set(RequestEvShareQData, qData);
1390
1450
  } finally {
1391
1451
  await stream.ready;
1392
1452
  await stream.close();
@@ -1411,10 +1471,10 @@ async function handleRedirect(requestEv) {
1411
1471
  return;
1412
1472
  }
1413
1473
  const status = requestEv.status();
1414
- const location = requestEv.headers.get("Location");
1415
- const isRedirect = status >= 301 && status <= 308 && location;
1474
+ const location2 = requestEv.headers.get("Location");
1475
+ const isRedirect = status >= 301 && status <= 308 && location2;
1416
1476
  if (isRedirect) {
1417
- const adaptedLocation = makeQDataPath(location);
1477
+ const adaptedLocation = makeQDataPath(location2);
1418
1478
  if (adaptedLocation) {
1419
1479
  requestEv.headers.set("Location", adaptedLocation);
1420
1480
  requestEv.getWritableStream().close();
@@ -1440,8 +1500,24 @@ async function renderQData(requestEv) {
1440
1500
  const requestHeaders = {};
1441
1501
  requestEv.request.headers.forEach((value, key) => requestHeaders[key] = value);
1442
1502
  requestEv.headers.set("Content-Type", "application/json; charset=utf-8");
1443
- const qData = {
1444
- loaders: getRequestLoaders(requestEv),
1503
+ let loaders = getRequestLoaders(requestEv);
1504
+ const selectedLoaderIds = requestEv.query.getAll(QLOADER_KEY);
1505
+ const hasCustomLoaders = selectedLoaderIds.length > 0;
1506
+ if (hasCustomLoaders) {
1507
+ const selectedLoaders = {};
1508
+ for (const loaderId of selectedLoaderIds) {
1509
+ const loader = loaders[loaderId];
1510
+ selectedLoaders[loaderId] = loader;
1511
+ }
1512
+ loaders = selectedLoaders;
1513
+ }
1514
+ const qData = hasCustomLoaders ? {
1515
+ // send minimal data to the client
1516
+ loaders,
1517
+ status: status !== 200 ? status : 200,
1518
+ href: getPathname(requestEv.url, trailingSlash)
1519
+ } : {
1520
+ loaders,
1445
1521
  action: requestEv.sharedMap.get(RequestEvSharedActionId),
1446
1522
  status: status !== 200 ? status : 200,
1447
1523
  href: getPathname(requestEv.url, trailingSlash),
@@ -1452,7 +1528,7 @@ async function renderQData(requestEv) {
1452
1528
  const qwikSerializer = requestEv[RequestEvQwikSerializer];
1453
1529
  const data = await qwikSerializer._serialize([qData]);
1454
1530
  writer.write(encoder.encode(data));
1455
- requestEv.sharedMap.set("qData", qData);
1531
+ requestEv.sharedMap.set(RequestEvShareQData, qData);
1456
1532
  writer.close();
1457
1533
  }
1458
1534
  function makeQDataPath(href) {
@@ -1474,9 +1550,9 @@ async function measure(requestEv, name, fn) {
1474
1550
  return await fn();
1475
1551
  } finally {
1476
1552
  const duration = now() - start;
1477
- let measurements = requestEv.sharedMap.get("@serverTiming");
1553
+ let measurements = requestEv.sharedMap.get(RequestEvShareServerTiming);
1478
1554
  if (!measurements) {
1479
- requestEv.sharedMap.set("@serverTiming", measurements = []);
1555
+ requestEv.sharedMap.set(RequestEvShareServerTiming, measurements = []);
1480
1556
  }
1481
1557
  measurements.push([name, duration]);
1482
1558
  }
@@ -1605,6 +1681,7 @@ var _TextEncoderStream_polyfill = class {
1605
1681
  0 && (module.exports = {
1606
1682
  AbortMessage,
1607
1683
  RedirectMessage,
1684
+ RequestEvShareQData,
1608
1685
  RewriteMessage,
1609
1686
  ServerError,
1610
1687
  _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 type { 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 */