@qwik.dev/router 2.0.0-alpha.9 → 2.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +1 -1
  2. package/lib/adapters/azure-swa/vite/index.cjs +3 -3
  3. package/lib/adapters/azure-swa/vite/index.d.ts +13 -13
  4. package/lib/adapters/bun-server/vite/index.cjs +3 -3
  5. package/lib/adapters/bun-server/vite/index.d.ts +14 -14
  6. package/lib/adapters/cloud-run/vite/index.cjs +3 -3
  7. package/lib/adapters/cloud-run/vite/index.d.ts +13 -13
  8. package/lib/adapters/cloudflare-pages/vite/index.cjs +3 -3
  9. package/lib/adapters/cloudflare-pages/vite/index.d.ts +27 -27
  10. package/lib/adapters/deno-server/vite/index.cjs +3 -3
  11. package/lib/adapters/deno-server/vite/index.d.ts +14 -14
  12. package/lib/adapters/netlify-edge/vite/index.cjs +3 -3
  13. package/lib/adapters/netlify-edge/vite/index.d.ts +44 -44
  14. package/lib/adapters/node-server/vite/index.cjs +3 -3
  15. package/lib/adapters/node-server/vite/index.d.ts +14 -14
  16. package/lib/adapters/shared/vite/index.cjs +10 -3
  17. package/lib/adapters/shared/vite/index.d.ts +114 -114
  18. package/lib/adapters/shared/vite/index.mjs +7 -0
  19. package/lib/adapters/static/vite/index.cjs +10 -3
  20. package/lib/adapters/static/vite/index.d.ts +10 -10
  21. package/lib/adapters/static/vite/index.mjs +7 -0
  22. package/lib/adapters/vercel-edge/vite/index.cjs +3 -3
  23. package/lib/adapters/vercel-edge/vite/index.d.ts +45 -45
  24. package/lib/index.d.ts +878 -810
  25. package/lib/index.qwik.cjs +110 -48
  26. package/lib/index.qwik.mjs +112 -50
  27. package/lib/middleware/aws-lambda/index.d.ts +48 -48
  28. package/lib/middleware/azure-swa/index.d.ts +28 -28
  29. package/lib/middleware/bun/index.d.ts +35 -35
  30. package/lib/middleware/cloudflare-pages/index.d.ts +35 -35
  31. package/lib/middleware/deno/index.d.ts +47 -47
  32. package/lib/middleware/firebase/index.d.ts +26 -26
  33. package/lib/middleware/netlify-edge/index.d.ts +27 -27
  34. package/lib/middleware/node/index.cjs +3 -3
  35. package/lib/middleware/node/index.d.ts +64 -64
  36. package/lib/middleware/request-handler/index.cjs +142 -73
  37. package/lib/middleware/request-handler/index.d.ts +710 -676
  38. package/lib/middleware/request-handler/index.mjs +138 -70
  39. package/lib/middleware/vercel-edge/index.d.ts +26 -26
  40. package/lib/service-worker.cjs +13 -263
  41. package/lib/service-worker.d.ts +15 -4
  42. package/lib/service-worker.mjs +13 -263
  43. package/lib/static/index.cjs +3 -3
  44. package/lib/static/index.d.ts +96 -96
  45. package/lib/static/node.cjs +3 -3
  46. package/lib/vite/index.cjs +209 -261
  47. package/lib/vite/index.d.ts +154 -154
  48. package/lib/vite/index.mjs +207 -259
  49. package/package.json +7 -7
@@ -218,6 +218,14 @@ var AbortMessage = class {
218
218
  var RedirectMessage = class extends AbortMessage {
219
219
  };
220
220
 
221
+ // packages/qwik-router/src/middleware/request-handler/rewrite-handler.ts
222
+ var RewriteMessage = class extends AbortMessage {
223
+ constructor(pathname) {
224
+ super();
225
+ this.pathname = pathname;
226
+ }
227
+ };
228
+
221
229
  // packages/qwik-router/src/runtime/src/constants.ts
222
230
  var MODULE_CACHE = /* @__PURE__ */ new WeakMap();
223
231
  var QACTION_KEY = "qaction";
@@ -453,8 +461,7 @@ function createCacheControl(cacheControl) {
453
461
  cacheControl = {
454
462
  public: true,
455
463
  immutable: true,
456
- maxAge: 60 * 60 * 24 * 365,
457
- staleWhileRevalidate: 60 * 60 * 24 * 365
464
+ maxAge: 60 * 60 * 24 * 365
458
465
  };
459
466
  } else if (cacheControl === "no-cache") {
460
467
  cacheControl = {
@@ -464,8 +471,7 @@ function createCacheControl(cacheControl) {
464
471
  if (typeof cacheControl === "number") {
465
472
  cacheControl = {
466
473
  maxAge: cacheControl,
467
- sMaxAge: cacheControl,
468
- staleWhileRevalidate: cacheControl
474
+ sMaxAge: cacheControl
469
475
  };
470
476
  }
471
477
  if (cacheControl.immutable) {
@@ -510,14 +516,13 @@ import("node:async_hooks").then((module) => {
510
516
  err
511
517
  );
512
518
  });
513
- function runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, manifest, trailingSlash = true, basePathname = "/", qwikSerializer) {
519
+ function runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, rebuildRouteInfo, trailingSlash = true, basePathname = "/", qwikSerializer) {
514
520
  let resolve;
515
521
  const responsePromise = new Promise((r) => resolve = r);
516
522
  const requestEv = createRequestEvent(
517
523
  serverRequestEv,
518
524
  loadedRoute,
519
525
  requestHandlers,
520
- manifest,
521
526
  trailingSlash,
522
527
  basePathname,
523
528
  qwikSerializer,
@@ -526,55 +531,71 @@ function runQwikRouter(serverRequestEv, loadedRoute, requestHandlers, manifest,
526
531
  return {
527
532
  response: responsePromise,
528
533
  requestEv,
529
- completion: asyncStore ? asyncStore.run(requestEv, runNext, requestEv, resolve) : runNext(requestEv, resolve)
534
+ completion: asyncStore ? asyncStore.run(requestEv, runNext, requestEv, rebuildRouteInfo, resolve) : runNext(requestEv, rebuildRouteInfo, resolve)
530
535
  };
531
536
  }
532
- async function runNext(requestEv, resolve) {
533
- try {
534
- await requestEv.next();
535
- } catch (e) {
536
- if (e instanceof RedirectMessage) {
537
- const stream = requestEv.getWritableStream();
538
- await stream.close();
539
- } else if (e instanceof ServerError) {
540
- if (!requestEv.headersSent) {
541
- const status = e.status;
542
- const accept = requestEv.request.headers.get("Accept");
543
- if (accept && !accept.includes("text/html")) {
544
- const qwikSerializer = requestEv[RequestEvQwikSerializer];
545
- requestEv.headers.set("Content-Type", "application/qwik-json");
546
- requestEv.send(status, await qwikSerializer._serialize([e.data]));
547
- } else {
548
- const html = getErrorHtml(e.status, e.data);
549
- requestEv.html(status, html);
537
+ async function runNext(requestEv, rebuildRouteInfo, resolve) {
538
+ let rewriteAttempt = 1;
539
+ async function _runNext() {
540
+ try {
541
+ await requestEv.next();
542
+ } catch (e) {
543
+ if (e instanceof RedirectMessage) {
544
+ const stream = requestEv.getWritableStream();
545
+ await stream.close();
546
+ } else if (e instanceof RewriteMessage) {
547
+ if (rewriteAttempt > 50) {
548
+ throw new Error(`Infinite rewrite loop`);
550
549
  }
551
- }
552
- } else if (!(e instanceof AbortMessage)) {
553
- if (getRequestMode(requestEv) !== "dev") {
554
- try {
555
- if (!requestEv.headersSent) {
556
- requestEv.headers.set("content-type", "text/html; charset=utf-8");
557
- requestEv.cacheControl({ noCache: true });
558
- requestEv.status(500);
550
+ rewriteAttempt += 1;
551
+ const url = new URL(requestEv.url);
552
+ url.pathname = e.pathname;
553
+ const { loadedRoute, requestHandlers } = await rebuildRouteInfo(url);
554
+ requestEv.resetRoute(loadedRoute, requestHandlers, url);
555
+ return await _runNext();
556
+ } else if (e instanceof ServerError) {
557
+ if (!requestEv.headersSent) {
558
+ const status = e.status;
559
+ const accept = requestEv.request.headers.get("Accept");
560
+ if (accept && !accept.includes("text/html")) {
561
+ const qwikSerializer = requestEv[RequestEvQwikSerializer];
562
+ requestEv.headers.set("Content-Type", "application/qwik-json");
563
+ requestEv.send(status, await qwikSerializer._serialize([e.data]));
564
+ } else {
565
+ const html = getErrorHtml(e.status, e.data);
566
+ requestEv.html(status, html);
559
567
  }
560
- const stream = requestEv.getWritableStream();
561
- if (!stream.locked) {
562
- const writer = stream.getWriter();
563
- await writer.write(encoder.encode(minimalHtmlResponse(500, "Internal Server Error")));
564
- await writer.close();
568
+ }
569
+ } else if (!(e instanceof AbortMessage)) {
570
+ if (getRequestMode(requestEv) !== "dev") {
571
+ try {
572
+ if (!requestEv.headersSent) {
573
+ requestEv.headers.set("content-type", "text/html; charset=utf-8");
574
+ requestEv.cacheControl({ noCache: true });
575
+ requestEv.status(500);
576
+ }
577
+ const stream = requestEv.getWritableStream();
578
+ if (!stream.locked) {
579
+ const writer = stream.getWriter();
580
+ await writer.write(encoder.encode(minimalHtmlResponse(500, "Internal Server Error")));
581
+ await writer.close();
582
+ }
583
+ } catch {
584
+ console.error("Unable to render error page");
565
585
  }
566
- } catch {
567
- console.error("Unable to render error page");
568
586
  }
587
+ return e;
569
588
  }
570
- return e;
571
589
  }
590
+ return void 0;
591
+ }
592
+ try {
593
+ return await _runNext();
572
594
  } finally {
573
595
  if (!requestEv.isDirty()) {
574
596
  resolve(null);
575
597
  }
576
598
  }
577
- return void 0;
578
599
  }
579
600
  function getRouteMatchPathname(pathname, trailingSlash) {
580
601
  if (pathname.endsWith(QDATA_JSON)) {
@@ -600,7 +621,8 @@ var RequestRouteName = "@routeName";
600
621
  var RequestEvSharedActionId = "@actionId";
601
622
  var RequestEvSharedActionFormData = "@actionFormData";
602
623
  var RequestEvSharedNonce = "@nonce";
603
- function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manifest, trailingSlash, basePathname, qwikSerializer, resolved) {
624
+ var RequestEvIsRewrite = "@rewrite";
625
+ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, trailingSlash, basePathname, qwikSerializer, resolved) {
604
626
  const { request, platform, env } = serverRequestEv;
605
627
  const sharedMap = /* @__PURE__ */ new Map();
606
628
  const cookie = new Cookie(request.headers.get("cookie"));
@@ -613,7 +635,6 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
613
635
  }
614
636
  sharedMap.set(IsQData, true);
615
637
  }
616
- sharedMap.set("@manifest", manifest);
617
638
  let routeModuleIndex = -1;
618
639
  let writableStream = null;
619
640
  let requestData = void 0;
@@ -631,6 +652,13 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
631
652
  routeModuleIndex++;
632
653
  }
633
654
  };
655
+ const resetRoute = (_loadedRoute, _requestHandlers, _url = url) => {
656
+ loadedRoute = _loadedRoute;
657
+ requestHandlers = _requestHandlers;
658
+ url.pathname = _url.pathname;
659
+ url.search = _url.search;
660
+ routeModuleIndex = -1;
661
+ };
634
662
  const check = () => {
635
663
  if (writableStream !== null) {
636
664
  throw new Error("Response already sent");
@@ -665,11 +693,7 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
665
693
  const writableStream2 = requestEv.getWritableStream();
666
694
  statusOrResponse.body.pipeTo(writableStream2);
667
695
  } else {
668
- if (status >= 300 && status < 400) {
669
- return new RedirectMessage();
670
- } else {
671
- requestEv.getWritableStream().getWriter().close();
672
- }
696
+ requestEv.getWritableStream().getWriter().close();
673
697
  }
674
698
  }
675
699
  return exit();
@@ -683,17 +707,26 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
683
707
  [RequestEvLoaders]: loaders,
684
708
  [RequestEvMode]: serverRequestEv.mode,
685
709
  [RequestEvTrailingSlash]: trailingSlash,
686
- [RequestEvRoute]: loadedRoute,
710
+ get [RequestEvRoute]() {
711
+ return loadedRoute;
712
+ },
687
713
  [RequestEvQwikSerializer]: qwikSerializer,
688
714
  cookie,
689
715
  headers,
690
716
  env,
691
717
  method: request.method,
692
718
  signal: request.signal,
693
- params: (loadedRoute == null ? void 0 : loadedRoute[1]) ?? {},
694
- pathname: url.pathname,
719
+ originalUrl: new URL(url),
720
+ get params() {
721
+ return (loadedRoute == null ? void 0 : loadedRoute[1]) ?? {};
722
+ },
723
+ get pathname() {
724
+ return url.pathname;
725
+ },
695
726
  platform,
696
- query: url.searchParams,
727
+ get query() {
728
+ return url.searchParams;
729
+ },
697
730
  request,
698
731
  url,
699
732
  basePathname,
@@ -708,6 +741,7 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
708
741
  return serverRequestEv.getClientConn();
709
742
  },
710
743
  next,
744
+ resetRoute,
711
745
  exit,
712
746
  cacheControl: (cacheControl, target = "Cache-Control") => {
713
747
  check();
@@ -758,6 +792,14 @@ function createRequestEvent(serverRequestEv, loadedRoute, requestHandlers, manif
758
792
  exit();
759
793
  return new RedirectMessage();
760
794
  },
795
+ rewrite: (pathname) => {
796
+ check();
797
+ if (pathname.startsWith("http")) {
798
+ throw new Error("Rewrite does not support absolute urls");
799
+ }
800
+ sharedMap.set(RequestEvIsRewrite, true);
801
+ return new RewriteMessage(pathname.replace(/\/+/g, "/"));
802
+ },
761
803
  defer: (returnData) => {
762
804
  return typeof returnData === "function" ? returnData : () => returnData;
763
805
  },
@@ -869,7 +911,7 @@ var formToObj = (formData) => {
869
911
 
870
912
  // packages/qwik-router/src/middleware/request-handler/response-page.ts
871
913
  function getQwikRouterServerData(requestEv) {
872
- const { url, params, request, status, locale } = requestEv;
914
+ const { params, request, status, locale, originalUrl } = requestEv;
873
915
  const requestHeaders = {};
874
916
  request.headers.forEach((value, key) => requestHeaders[key] = value);
875
917
  const action = requestEv.sharedMap.get(RequestEvSharedActionId);
@@ -877,7 +919,7 @@ function getQwikRouterServerData(requestEv) {
877
919
  const routeName = requestEv.sharedMap.get(RequestRouteName);
878
920
  const nonce = requestEv.sharedMap.get(RequestEvSharedNonce);
879
921
  const headers = requestEv.request.headers;
880
- const reconstructedUrl = new URL(url.pathname + url.search, url);
922
+ const reconstructedUrl = new URL(originalUrl.pathname + originalUrl.search, originalUrl);
881
923
  const host = headers.get("X-Forwarded-Host");
882
924
  const protocol = headers.get("X-Forwarded-Proto");
883
925
  if (host) {
@@ -1140,14 +1182,21 @@ async function pureServerFunction(ev) {
1140
1182
  const [qrl, ...args] = data;
1141
1183
  if (isQrl(qrl) && qrl.getHash() === fn) {
1142
1184
  let result;
1143
- if (isDev) {
1144
- result = await measure(
1145
- ev,
1146
- `server_${qrl.getSymbol()}`,
1147
- () => qrl.apply(ev, args)
1148
- );
1149
- } else {
1150
- result = await qrl.apply(ev, args);
1185
+ try {
1186
+ if (isDev) {
1187
+ result = await measure(
1188
+ ev,
1189
+ `server_${qrl.getSymbol()}`,
1190
+ () => qrl.apply(ev, args)
1191
+ );
1192
+ } else {
1193
+ result = await qrl.apply(ev, args);
1194
+ }
1195
+ } catch (err) {
1196
+ if (err instanceof ServerError) {
1197
+ throw ev.error(err.status, err.data);
1198
+ }
1199
+ throw ev.error(500, "Invalid request");
1151
1200
  }
1152
1201
  if (isAsyncIterator(result)) {
1153
1202
  ev.headers.set("Content-Type", "text/qwik-json-stream");
@@ -1179,18 +1228,19 @@ async function pureServerFunction(ev) {
1179
1228
  }
1180
1229
  function fixTrailingSlash(ev) {
1181
1230
  const trailingSlash = getRequestTrailingSlash(ev);
1182
- const { basePathname, pathname, url, sharedMap } = ev;
1231
+ const { basePathname, originalUrl, sharedMap } = ev;
1232
+ const { pathname, search } = originalUrl;
1183
1233
  const isQData = sharedMap.has(IsQData);
1184
1234
  if (!isQData && pathname !== basePathname && !pathname.endsWith(".html")) {
1185
1235
  if (trailingSlash) {
1186
1236
  if (!pathname.endsWith("/")) {
1187
- throw ev.redirect(301 /* MovedPermanently */, pathname + "/" + url.search);
1237
+ throw ev.redirect(301 /* MovedPermanently */, pathname + "/" + search);
1188
1238
  }
1189
1239
  } else {
1190
1240
  if (pathname.endsWith("/")) {
1191
1241
  throw ev.redirect(
1192
1242
  301 /* MovedPermanently */,
1193
- pathname.slice(0, pathname.length - 1) + url.search
1243
+ pathname.slice(0, pathname.length - 1) + search
1194
1244
  );
1195
1245
  }
1196
1246
  }
@@ -1342,7 +1392,7 @@ async function renderQData(requestEv) {
1342
1392
  return;
1343
1393
  }
1344
1394
  const status = requestEv.status();
1345
- const location = requestEv.headers.get("Location");
1395
+ const redirectLocation = requestEv.headers.get("Location");
1346
1396
  const trailingSlash = getRequestTrailingSlash(requestEv);
1347
1397
  const requestHeaders = {};
1348
1398
  requestEv.request.headers.forEach((value, key) => requestHeaders[key] = value);
@@ -1352,7 +1402,8 @@ async function renderQData(requestEv) {
1352
1402
  action: requestEv.sharedMap.get(RequestEvSharedActionId),
1353
1403
  status: status !== 200 ? status : 200,
1354
1404
  href: getPathname(requestEv.url, trailingSlash),
1355
- redirect: location ?? void 0
1405
+ redirect: redirectLocation ?? void 0,
1406
+ isRewrite: requestEv.sharedMap.get(RequestEvIsRewrite)
1356
1407
  };
1357
1408
  const writer = requestEv.getWritableStream().getWriter();
1358
1409
  const qwikSerializer = requestEv[RequestEvQwikSerializer];
@@ -1395,7 +1446,7 @@ function isContentType(headers, ...types) {
1395
1446
 
1396
1447
  // packages/qwik-router/src/middleware/request-handler/request-handler.ts
1397
1448
  async function requestHandler(serverRequestEv, opts, qwikSerializer) {
1398
- const { render, qwikRouterConfig, manifest, checkOrigin } = opts;
1449
+ const { render, qwikRouterConfig, checkOrigin } = opts;
1399
1450
  if (!qwikRouterConfig) {
1400
1451
  throw new Error("qwikRouterConfig is required.");
1401
1452
  }
@@ -1410,11 +1461,27 @@ async function requestHandler(serverRequestEv, opts, qwikSerializer) {
1410
1461
  );
1411
1462
  if (routeAndHandlers) {
1412
1463
  const [route, requestHandlers] = routeAndHandlers;
1464
+ const rebuildRouteInfo = async (url) => {
1465
+ const matchPathname2 = getRouteMatchPathname(url.pathname, qwikRouterConfig.trailingSlash);
1466
+ const routeAndHandlers2 = await loadRequestHandlers(
1467
+ qwikRouterConfig,
1468
+ matchPathname2,
1469
+ serverRequestEv.request.method,
1470
+ checkOrigin ?? true,
1471
+ render
1472
+ );
1473
+ if (routeAndHandlers2) {
1474
+ const [loadedRoute, requestHandlers2] = routeAndHandlers2;
1475
+ return { loadedRoute, requestHandlers: requestHandlers2 };
1476
+ } else {
1477
+ return { loadedRoute: null, requestHandlers: [] };
1478
+ }
1479
+ };
1413
1480
  return runQwikRouter(
1414
1481
  serverRequestEv,
1415
1482
  route,
1416
1483
  requestHandlers,
1417
- manifest,
1484
+ rebuildRouteInfo,
1418
1485
  qwikRouterConfig.trailingSlash,
1419
1486
  qwikRouterConfig.basePathname,
1420
1487
  qwikSerializer
@@ -1494,6 +1561,7 @@ var _TextEncoderStream_polyfill = class {
1494
1561
  export {
1495
1562
  AbortMessage,
1496
1563
  RedirectMessage,
1564
+ RewriteMessage,
1497
1565
  ServerError,
1498
1566
  _TextEncoderStream_polyfill,
1499
1567
  getErrorHtml,
@@ -1,26 +1,26 @@
1
- import type { ServerRenderOptions } from '@qwik.dev/router/middleware/request-handler';
2
-
3
- /**
4
- * @deprecated Use `createQwikRouter` instead. Will be removed in V3
5
- * @public
6
- */
7
- export declare const createQwikCity: typeof createQwikRouter;
8
-
9
- /** @public */
10
- export declare function createQwikRouter(opts: QwikRouterVercelEdgeOptions): (request: Request) => Promise<Response>;
11
-
12
- /** @public */
13
- export declare interface PlatformVercel {
14
- }
15
-
16
- /**
17
- * @deprecated Use `QwikRouterVercelEdgeOptions` instead. Will be removed in V3
18
- * @public
19
- */
20
- export declare type QwikCityVercelEdgeOptions = QwikRouterVercelEdgeOptions;
21
-
22
- /** @public */
23
- export declare interface QwikRouterVercelEdgeOptions extends ServerRenderOptions {
24
- }
25
-
26
- export { }
1
+ import type { ServerRenderOptions } from '@qwik.dev/router/middleware/request-handler';
2
+
3
+ /**
4
+ * @deprecated Use `createQwikRouter` instead. Will be removed in V3
5
+ * @public
6
+ */
7
+ export declare const createQwikCity: typeof createQwikRouter;
8
+
9
+ /** @public */
10
+ export declare function createQwikRouter(opts: QwikRouterVercelEdgeOptions): (request: Request) => Promise<Response>;
11
+
12
+ /** @public */
13
+ export declare interface PlatformVercel {
14
+ }
15
+
16
+ /**
17
+ * @deprecated Use `QwikRouterVercelEdgeOptions` instead. Will be removed in V3
18
+ * @public
19
+ */
20
+ export declare type QwikCityVercelEdgeOptions = QwikRouterVercelEdgeOptions;
21
+
22
+ /** @public */
23
+ export declare interface QwikRouterVercelEdgeOptions extends ServerRenderOptions {
24
+ }
25
+
26
+ export { }