@qwik.dev/router 2.0.0-alpha.8 → 2.0.0-beta.1

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 -801
  25. package/lib/index.qwik.cjs +127 -51
  26. package/lib/index.qwik.mjs +130 -54
  27. package/lib/middleware/aws-lambda/index.d.ts +48 -50
  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 -66
  36. package/lib/middleware/request-handler/index.cjs +133 -75
  37. package/lib/middleware/request-handler/index.d.ts +710 -681
  38. package/lib/middleware/request-handler/index.mjs +129 -72
  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 -98
  45. package/lib/static/node.cjs +3 -3
  46. package/lib/vite/index.cjs +199 -262
  47. package/lib/vite/index.d.ts +154 -154
  48. package/lib/vite/index.mjs +197 -260
  49. package/package.json +8 -8
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("@qwik.dev/core/jsx-runtime");
4
4
  const core = require("@qwik.dev/core");
5
+ const preloader = require("@qwik.dev/core/preloader");
5
6
  const internal = require("@qwik.dev/core/internal");
6
7
  const qwikRouterConfig = require("@qwik-router-config");
7
8
  const zod = require("zod");
@@ -23,9 +24,20 @@ function _interopNamespaceDefault(e) {
23
24
  return Object.freeze(n);
24
25
  }
25
26
  const qwikRouterConfig__namespace = /* @__PURE__ */ _interopNamespaceDefault(qwikRouterConfig);
27
+ const ErrorBoundary = core.component$((props) => {
28
+ const store2 = core.useErrorBoundary();
29
+ core.useOnWindow("qerror", core.$((e) => {
30
+ store2.error = e.detail.error;
31
+ }));
32
+ if (store2.error && props.fallback$) {
33
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {
34
+ children: props.fallback$(store2.error)
35
+ });
36
+ }
37
+ return /* @__PURE__ */ jsxRuntime.jsx(core.Slot, {});
38
+ });
26
39
  const MODULE_CACHE = /* @__PURE__ */ new WeakMap();
27
40
  const CLIENT_DATA_CACHE = /* @__PURE__ */ new Map();
28
- const PREFETCHED_NAVIGATE_PATHS = /* @__PURE__ */ new Set();
29
41
  const QACTION_KEY = "qaction";
30
42
  const QFN_KEY = "qfunc";
31
43
  const QDATA_KEY = "qdata";
@@ -63,15 +75,7 @@ const getClientNavPath = (props, baseUrl) => {
63
75
  }
64
76
  return null;
65
77
  };
66
- const shouldPrefetchData = (clientNavPath, currentLoc) => {
67
- if (clientNavPath) {
68
- const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
69
- const currentUrl = toUrl("", currentLoc.url);
70
- return !isSamePath(prefetchUrl, currentUrl);
71
- }
72
- return false;
73
- };
74
- const shouldPrefetchSymbols = (clientNavPath, currentLoc) => {
78
+ const shouldPreload = (clientNavPath, currentLoc) => {
75
79
  if (clientNavPath) {
76
80
  const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
77
81
  const currentUrl = toUrl("", currentLoc.url);
@@ -121,16 +125,8 @@ const newScrollState = () => {
121
125
  const prefetchSymbols = (path) => {
122
126
  if (core.isBrowser) {
123
127
  path = path.endsWith("/") ? path : path + "/";
124
- if (!PREFETCHED_NAVIGATE_PATHS.has(path)) {
125
- PREFETCHED_NAVIGATE_PATHS.add(path);
126
- document.dispatchEvent(new CustomEvent("qprefetch", {
127
- detail: {
128
- links: [
129
- path
130
- ]
131
- }
132
- }));
133
- }
128
+ path = path.length > 1 && path.startsWith("/") ? path.slice(1) : path;
129
+ preloader.p(path, 0.8);
134
130
  }
135
131
  };
136
132
  const loadClientData = async (url, element, opts) => {
@@ -146,7 +142,7 @@ const loadClientData = async (url, element, opts) => {
146
142
  }
147
143
  let resolveFn;
148
144
  if (!qData) {
149
- const fetchOptions = getFetchOptions(opts?.action);
145
+ const fetchOptions = getFetchOptions(opts?.action, opts?.clearCache);
150
146
  if (opts?.action) {
151
147
  opts.action.data = void 0;
152
148
  }
@@ -202,16 +198,19 @@ const loadClientData = async (url, element, opts) => {
202
198
  return v;
203
199
  });
204
200
  };
205
- const getFetchOptions = (action) => {
201
+ const getFetchOptions = (action, noCache) => {
206
202
  const actionData = action?.data;
207
203
  if (!actionData) {
208
- return {
209
- cache: "no-cache",
210
- headers: {
211
- "Cache-Control": "no-cache",
212
- Pragma: "no-cache"
213
- }
214
- };
204
+ if (noCache) {
205
+ return {
206
+ cache: "no-cache",
207
+ headers: {
208
+ "Cache-Control": "no-cache",
209
+ Pragma: "no-cache"
210
+ }
211
+ };
212
+ }
213
+ return void 0;
215
214
  }
216
215
  if (actionData instanceof FormData) {
217
216
  return {
@@ -255,14 +254,15 @@ const Link = core.component$((props) => {
255
254
  const nav = useNavigate();
256
255
  const loc = useLocation();
257
256
  const originalHref = props.href;
257
+ const anchorRef = core.useSignal();
258
258
  const { onClick$, prefetch: prefetchProp, reload, replaceState, scroll, ...linkProps } = /* @__PURE__ */ (() => props)();
259
259
  const clientNavPath = core.untrack(() => getClientNavPath({
260
260
  ...linkProps,
261
261
  reload
262
262
  }, loc));
263
263
  linkProps.href = clientNavPath || originalHref;
264
- const prefetchData = core.untrack(() => !!clientNavPath && prefetchProp !== false && prefetchProp !== "js" && shouldPrefetchData(clientNavPath, loc) || void 0);
265
- const prefetch = core.untrack(() => prefetchData || !!clientNavPath && prefetchProp !== false && shouldPrefetchSymbols(clientNavPath, loc));
264
+ const prefetchData = core.untrack(() => !!clientNavPath && prefetchProp !== false && prefetchProp !== "js" || void 0);
265
+ const prefetch = core.untrack(() => prefetchData || !!clientNavPath && prefetchProp !== false && shouldPreload(clientNavPath, loc));
266
266
  const handlePrefetch = prefetch ? core.$((_, elm) => {
267
267
  if (navigator.connection?.saveData) {
268
268
  return;
@@ -296,7 +296,23 @@ const Link = core.component$((props) => {
296
296
  }
297
297
  }
298
298
  }) : void 0;
299
+ core.useVisibleTask$(({ track }) => {
300
+ track(() => loc.url.pathname);
301
+ const handler = linkProps.onQVisible$;
302
+ if (handler) {
303
+ const event = new CustomEvent("qvisible");
304
+ if (Array.isArray(handler)) {
305
+ handler.flat(10).forEach((handler2) => handler2?.(event, anchorRef.value));
306
+ } else {
307
+ handler?.(event, anchorRef.value);
308
+ }
309
+ }
310
+ if (!core.isDev && anchorRef.value) {
311
+ handlePrefetch?.(void 0, anchorRef.value);
312
+ }
313
+ });
299
314
  return /* @__PURE__ */ jsxRuntime.jsx("a", {
315
+ ref: anchorRef,
300
316
  "q:link": !!clientNavPath,
301
317
  ...linkProps,
302
318
  onClick$: [
@@ -313,11 +329,8 @@ const Link = core.component$((props) => {
313
329
  linkProps.onFocus$,
314
330
  handlePrefetch
315
331
  ],
316
- // Don't prefetch on visible in dev mode
317
- onQVisible$: [
318
- linkProps.onQVisible$,
319
- !core.isDev ? handlePrefetch : void 0
320
- ],
332
+ // We need to prevent the onQVisible$ from being called twice since it is handled in the visible task
333
+ onQVisible$: [],
321
334
  children: /* @__PURE__ */ jsxRuntime.jsx(core.Slot, {})
322
335
  });
323
336
  });
@@ -758,6 +771,26 @@ const spaInit = core.event$((_, el) => {
758
771
  }, 0);
759
772
  }
760
773
  });
774
+ const startViewTransition = (params) => {
775
+ if (!params.update) {
776
+ return;
777
+ }
778
+ if ("startViewTransition" in document) {
779
+ let transition;
780
+ try {
781
+ transition = document.startViewTransition(params);
782
+ } catch {
783
+ transition = document.startViewTransition(params.update);
784
+ }
785
+ const event = new CustomEvent("qviewtransition", {
786
+ detail: transition
787
+ });
788
+ document.dispatchEvent(event);
789
+ return transition;
790
+ } else {
791
+ params.update?.();
792
+ }
793
+ };
761
794
  const QWIK_CITY_SCROLLER = "_qCityScroller";
762
795
  const QWIK_ROUTER_SCROLLER = "_qRouterScroller";
763
796
  const preventNav = {};
@@ -765,7 +798,18 @@ const internalState = {
765
798
  navCount: 0
766
799
  };
767
800
  const QwikRouterProvider = core.component$((props) => {
768
- core.useStyles$(`:root{view-transition-name:none}`);
801
+ core.useStyles$(`
802
+ @layer qwik {
803
+ @supports selector(html:active-view-transition-type(type)) {
804
+ html:active-view-transition-type(qwik-router-spa) {
805
+ :root{view-transition-name:none}
806
+ }
807
+ }
808
+ @supports not selector(html:active-view-transition-type(type)) {
809
+ :root{view-transition-name:none}
810
+ }
811
+ }
812
+ `);
769
813
  const env = useQwikRouterEnv();
770
814
  if (!env?.params) {
771
815
  throw new Error(`Missing Qwik Router Env Data for help visit https://github.com/QwikDev/qwik/issues/6237`);
@@ -774,6 +818,11 @@ const QwikRouterProvider = core.component$((props) => {
774
818
  if (!urlEnv) {
775
819
  throw new Error(`Missing Qwik URL Env Data`);
776
820
  }
821
+ if (core.isServer) {
822
+ if (env.ev.originalUrl.pathname !== env.ev.url.pathname && !__EXPERIMENTAL__.enableRequestRewrite) {
823
+ throw new Error(`enableRequestRewrite is an experimental feature and is not enabled. Please enable the feature flag by adding \`experimental: ["enableRequestRewrite"]\` to your qwikVite plugin options.`);
824
+ }
825
+ }
777
826
  const url = new URL(urlEnv);
778
827
  const routeLocation = core.useStore({
779
828
  url,
@@ -962,12 +1011,21 @@ const QwikRouterProvider = core.component$((props) => {
962
1011
  const newHref = pageData.href;
963
1012
  const newURL = new URL(newHref, trackUrl);
964
1013
  if (!isSamePath(newURL, trackUrl)) {
965
- trackUrl = newURL;
966
- loadRoutePromise = loadRoute(qwikRouterConfig__namespace.routes, qwikRouterConfig__namespace.menus, qwikRouterConfig__namespace.cacheModules, trackUrl.pathname);
1014
+ if (!pageData.isRewrite) {
1015
+ trackUrl = newURL;
1016
+ }
1017
+ loadRoutePromise = loadRoute(
1018
+ qwikRouterConfig__namespace.routes,
1019
+ qwikRouterConfig__namespace.menus,
1020
+ qwikRouterConfig__namespace.cacheModules,
1021
+ newURL.pathname
1022
+ // Load the actual required path.
1023
+ );
967
1024
  }
968
1025
  try {
969
1026
  loadedRoute = await loadRoutePromise;
970
1027
  } catch (e) {
1028
+ console.error(e);
971
1029
  window.location.href = newHref;
972
1030
  return;
973
1031
  }
@@ -1002,9 +1060,6 @@ const QwikRouterProvider = core.component$((props) => {
1002
1060
  documentHead.title = resolvedHead.title;
1003
1061
  documentHead.frontmatter = resolvedHead.frontmatter;
1004
1062
  if (core.isBrowser) {
1005
- if (props.viewTransition !== false) {
1006
- document.__q_view_transition__ = true;
1007
- }
1008
1063
  let scrollState;
1009
1064
  if (navType === "popstate") {
1010
1065
  scrollState = getScrollHistory();
@@ -1127,8 +1182,27 @@ const QwikRouterProvider = core.component$((props) => {
1127
1182
  const scrollState2 = currentScrollState(scroller);
1128
1183
  saveScrollHistory(scrollState2);
1129
1184
  }
1130
- clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1131
- internal._waitUntilRendered(elm).then(() => {
1185
+ const navigate = () => {
1186
+ clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1187
+ return internal._waitUntilRendered(elm);
1188
+ };
1189
+ const _waitNextPage = () => {
1190
+ if (core.isServer || props.viewTransition === false) {
1191
+ return navigate();
1192
+ } else {
1193
+ const viewTransition = startViewTransition({
1194
+ update: navigate,
1195
+ types: [
1196
+ "qwik-navigation"
1197
+ ]
1198
+ });
1199
+ if (!viewTransition) {
1200
+ return Promise.resolve();
1201
+ }
1202
+ return viewTransition.ready;
1203
+ }
1204
+ };
1205
+ _waitNextPage().then(() => {
1132
1206
  const container = internal._getQContainerElement(elm);
1133
1207
  container.setAttribute("q:route", routeName);
1134
1208
  const scrollState2 = currentScrollState(scroller);
@@ -1143,11 +1217,10 @@ const QwikRouterProvider = core.component$((props) => {
1143
1217
  }
1144
1218
  }
1145
1219
  }
1146
- const promise = run();
1147
1220
  if (core.isServer) {
1148
- return promise;
1221
+ return run();
1149
1222
  } else {
1150
- return;
1223
+ run();
1151
1224
  }
1152
1225
  });
1153
1226
  return /* @__PURE__ */ jsxRuntime.jsx(core.Slot, {});
@@ -1598,6 +1671,7 @@ const serverQrl = (qrl, options) => {
1598
1671
  headers: {
1599
1672
  ...headers,
1600
1673
  "Content-Type": "application/qwik-json",
1674
+ Accept: "application/json, application/qwik-json, text/qwik-json-stream, text/plain",
1601
1675
  // Required so we don't call accidentally
1602
1676
  "X-QRL": qrlHash
1603
1677
  },
@@ -1629,19 +1703,19 @@ const serverQrl = (qrl, options) => {
1629
1703
  } else if (contentType === "application/qwik-json") {
1630
1704
  const str = await res.text();
1631
1705
  const [obj] = internal._deserialize(str, ctxElm ?? document.documentElement);
1632
- if (res.status >= 500) {
1706
+ if (res.status >= 400) {
1633
1707
  throw obj;
1634
1708
  }
1635
1709
  return obj;
1636
1710
  } else if (contentType === "application/json") {
1637
1711
  const obj = await res.json();
1638
- if (res.status >= 500) {
1712
+ if (res.status >= 400) {
1639
1713
  throw obj;
1640
1714
  }
1641
1715
  return obj;
1642
1716
  } else if (contentType === "text/plain" || contentType === "text/html") {
1643
1717
  const str = await res.text();
1644
- if (res.status >= 500) {
1718
+ if (res.status >= 400) {
1645
1719
  throw str;
1646
1720
  }
1647
1721
  return str;
@@ -1709,7 +1783,8 @@ const deserializeStream = async function* (stream, ctxElm, abortSignal) {
1709
1783
  reader.releaseLock();
1710
1784
  }
1711
1785
  };
1712
- const ServiceWorkerRegister = (props) => core.jsx("script", {
1786
+ const ServiceWorkerRegister = (props) => /* @__PURE__ */ jsxRuntime.jsx("script", {
1787
+ type: "module",
1713
1788
  dangerouslySetInnerHTML: swRegister,
1714
1789
  nonce: props.nonce
1715
1790
  });
@@ -1837,6 +1912,7 @@ Object.defineProperty(exports, "z", {
1837
1912
  enumerable: true,
1838
1913
  get: () => zod.z
1839
1914
  });
1915
+ exports.ErrorBoundary = ErrorBoundary;
1840
1916
  exports.Form = Form;
1841
1917
  exports.Link = Link;
1842
1918
  exports.QWIK_CITY_SCROLLER = QWIK_CITY_SCROLLER;
@@ -1,13 +1,25 @@
1
- import { jsx, jsxs, Fragment } from "@qwik.dev/core/jsx-runtime";
2
- import { isBrowser, createContextId, implicit$FirstArg, useContext, useVisibleTask$, noSerialize, useServerData, component$, untrack, $, sync$, isDev, Slot, withLocale, event$, useStyles$, useStore, useSignal, useContextProvider, useTask$, isServer, getLocale, jsx as jsx$1, SkipRender } from "@qwik.dev/core";
3
- import { _deserialize, _weakSerialize, _getContextElement, _waitUntilRendered, _getQContainerElement, _wrapStore, _getContextEvent, _serialize } from "@qwik.dev/core/internal";
1
+ import { jsx, Fragment, jsxs } from "@qwik.dev/core/jsx-runtime";
2
+ import { component$, useErrorBoundary, useOnWindow, $, Slot, isBrowser, createContextId, implicit$FirstArg, useContext, useVisibleTask$, noSerialize, useServerData, useSignal, untrack, sync$, isDev, withLocale, event$, useStyles$, isServer, useStore, useContextProvider, useTask$, getLocale, jsx as jsx$1, SkipRender } from "@qwik.dev/core";
3
+ import { p } from "@qwik.dev/core/preloader";
4
+ import { _deserialize, _weakSerialize, _getContextElement, _getQContainerElement, _waitUntilRendered, _wrapStore, _getContextEvent, _serialize } from "@qwik.dev/core/internal";
4
5
  import * as qwikRouterConfig from "@qwik-router-config";
5
6
  import { z } from "zod";
6
7
  import { z as z2 } from "zod";
7
8
  import swRegister from "@qwik-router-sw-register";
9
+ const ErrorBoundary = component$((props) => {
10
+ const store2 = useErrorBoundary();
11
+ useOnWindow("qerror", $((e) => {
12
+ store2.error = e.detail.error;
13
+ }));
14
+ if (store2.error && props.fallback$) {
15
+ return /* @__PURE__ */ jsx(Fragment, {
16
+ children: props.fallback$(store2.error)
17
+ });
18
+ }
19
+ return /* @__PURE__ */ jsx(Slot, {});
20
+ });
8
21
  const MODULE_CACHE = /* @__PURE__ */ new WeakMap();
9
22
  const CLIENT_DATA_CACHE = /* @__PURE__ */ new Map();
10
- const PREFETCHED_NAVIGATE_PATHS = /* @__PURE__ */ new Set();
11
23
  const QACTION_KEY = "qaction";
12
24
  const QFN_KEY = "qfunc";
13
25
  const QDATA_KEY = "qdata";
@@ -45,15 +57,7 @@ const getClientNavPath = (props, baseUrl) => {
45
57
  }
46
58
  return null;
47
59
  };
48
- const shouldPrefetchData = (clientNavPath, currentLoc) => {
49
- if (clientNavPath) {
50
- const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
51
- const currentUrl = toUrl("", currentLoc.url);
52
- return !isSamePath(prefetchUrl, currentUrl);
53
- }
54
- return false;
55
- };
56
- const shouldPrefetchSymbols = (clientNavPath, currentLoc) => {
60
+ const shouldPreload = (clientNavPath, currentLoc) => {
57
61
  if (clientNavPath) {
58
62
  const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
59
63
  const currentUrl = toUrl("", currentLoc.url);
@@ -103,16 +107,8 @@ const newScrollState = () => {
103
107
  const prefetchSymbols = (path) => {
104
108
  if (isBrowser) {
105
109
  path = path.endsWith("/") ? path : path + "/";
106
- if (!PREFETCHED_NAVIGATE_PATHS.has(path)) {
107
- PREFETCHED_NAVIGATE_PATHS.add(path);
108
- document.dispatchEvent(new CustomEvent("qprefetch", {
109
- detail: {
110
- links: [
111
- path
112
- ]
113
- }
114
- }));
115
- }
110
+ path = path.length > 1 && path.startsWith("/") ? path.slice(1) : path;
111
+ p(path, 0.8);
116
112
  }
117
113
  };
118
114
  const loadClientData = async (url, element, opts) => {
@@ -128,7 +124,7 @@ const loadClientData = async (url, element, opts) => {
128
124
  }
129
125
  let resolveFn;
130
126
  if (!qData) {
131
- const fetchOptions = getFetchOptions(opts?.action);
127
+ const fetchOptions = getFetchOptions(opts?.action, opts?.clearCache);
132
128
  if (opts?.action) {
133
129
  opts.action.data = void 0;
134
130
  }
@@ -184,16 +180,19 @@ const loadClientData = async (url, element, opts) => {
184
180
  return v;
185
181
  });
186
182
  };
187
- const getFetchOptions = (action) => {
183
+ const getFetchOptions = (action, noCache) => {
188
184
  const actionData = action?.data;
189
185
  if (!actionData) {
190
- return {
191
- cache: "no-cache",
192
- headers: {
193
- "Cache-Control": "no-cache",
194
- Pragma: "no-cache"
195
- }
196
- };
186
+ if (noCache) {
187
+ return {
188
+ cache: "no-cache",
189
+ headers: {
190
+ "Cache-Control": "no-cache",
191
+ Pragma: "no-cache"
192
+ }
193
+ };
194
+ }
195
+ return void 0;
197
196
  }
198
197
  if (actionData instanceof FormData) {
199
198
  return {
@@ -237,14 +236,15 @@ const Link = component$((props) => {
237
236
  const nav = useNavigate();
238
237
  const loc = useLocation();
239
238
  const originalHref = props.href;
239
+ const anchorRef = useSignal();
240
240
  const { onClick$, prefetch: prefetchProp, reload, replaceState, scroll, ...linkProps } = /* @__PURE__ */ (() => props)();
241
241
  const clientNavPath = untrack(() => getClientNavPath({
242
242
  ...linkProps,
243
243
  reload
244
244
  }, loc));
245
245
  linkProps.href = clientNavPath || originalHref;
246
- const prefetchData = untrack(() => !!clientNavPath && prefetchProp !== false && prefetchProp !== "js" && shouldPrefetchData(clientNavPath, loc) || void 0);
247
- const prefetch = untrack(() => prefetchData || !!clientNavPath && prefetchProp !== false && shouldPrefetchSymbols(clientNavPath, loc));
246
+ const prefetchData = untrack(() => !!clientNavPath && prefetchProp !== false && prefetchProp !== "js" || void 0);
247
+ const prefetch = untrack(() => prefetchData || !!clientNavPath && prefetchProp !== false && shouldPreload(clientNavPath, loc));
248
248
  const handlePrefetch = prefetch ? $((_, elm) => {
249
249
  if (navigator.connection?.saveData) {
250
250
  return;
@@ -278,7 +278,23 @@ const Link = component$((props) => {
278
278
  }
279
279
  }
280
280
  }) : void 0;
281
+ useVisibleTask$(({ track }) => {
282
+ track(() => loc.url.pathname);
283
+ const handler = linkProps.onQVisible$;
284
+ if (handler) {
285
+ const event = new CustomEvent("qvisible");
286
+ if (Array.isArray(handler)) {
287
+ handler.flat(10).forEach((handler2) => handler2?.(event, anchorRef.value));
288
+ } else {
289
+ handler?.(event, anchorRef.value);
290
+ }
291
+ }
292
+ if (!isDev && anchorRef.value) {
293
+ handlePrefetch?.(void 0, anchorRef.value);
294
+ }
295
+ });
281
296
  return /* @__PURE__ */ jsx("a", {
297
+ ref: anchorRef,
282
298
  "q:link": !!clientNavPath,
283
299
  ...linkProps,
284
300
  onClick$: [
@@ -295,11 +311,8 @@ const Link = component$((props) => {
295
311
  linkProps.onFocus$,
296
312
  handlePrefetch
297
313
  ],
298
- // Don't prefetch on visible in dev mode
299
- onQVisible$: [
300
- linkProps.onQVisible$,
301
- !isDev ? handlePrefetch : void 0
302
- ],
314
+ // We need to prevent the onQVisible$ from being called twice since it is handled in the visible task
315
+ onQVisible$: [],
303
316
  children: /* @__PURE__ */ jsx(Slot, {})
304
317
  });
305
318
  });
@@ -740,6 +753,26 @@ const spaInit = event$((_, el) => {
740
753
  }, 0);
741
754
  }
742
755
  });
756
+ const startViewTransition = (params) => {
757
+ if (!params.update) {
758
+ return;
759
+ }
760
+ if ("startViewTransition" in document) {
761
+ let transition;
762
+ try {
763
+ transition = document.startViewTransition(params);
764
+ } catch {
765
+ transition = document.startViewTransition(params.update);
766
+ }
767
+ const event = new CustomEvent("qviewtransition", {
768
+ detail: transition
769
+ });
770
+ document.dispatchEvent(event);
771
+ return transition;
772
+ } else {
773
+ params.update?.();
774
+ }
775
+ };
743
776
  const QWIK_CITY_SCROLLER = "_qCityScroller";
744
777
  const QWIK_ROUTER_SCROLLER = "_qRouterScroller";
745
778
  const preventNav = {};
@@ -747,7 +780,18 @@ const internalState = {
747
780
  navCount: 0
748
781
  };
749
782
  const QwikRouterProvider = component$((props) => {
750
- useStyles$(`:root{view-transition-name:none}`);
783
+ useStyles$(`
784
+ @layer qwik {
785
+ @supports selector(html:active-view-transition-type(type)) {
786
+ html:active-view-transition-type(qwik-router-spa) {
787
+ :root{view-transition-name:none}
788
+ }
789
+ }
790
+ @supports not selector(html:active-view-transition-type(type)) {
791
+ :root{view-transition-name:none}
792
+ }
793
+ }
794
+ `);
751
795
  const env = useQwikRouterEnv();
752
796
  if (!env?.params) {
753
797
  throw new Error(`Missing Qwik Router Env Data for help visit https://github.com/QwikDev/qwik/issues/6237`);
@@ -756,6 +800,11 @@ const QwikRouterProvider = component$((props) => {
756
800
  if (!urlEnv) {
757
801
  throw new Error(`Missing Qwik URL Env Data`);
758
802
  }
803
+ if (isServer) {
804
+ if (env.ev.originalUrl.pathname !== env.ev.url.pathname && !__EXPERIMENTAL__.enableRequestRewrite) {
805
+ throw new Error(`enableRequestRewrite is an experimental feature and is not enabled. Please enable the feature flag by adding \`experimental: ["enableRequestRewrite"]\` to your qwikVite plugin options.`);
806
+ }
807
+ }
759
808
  const url = new URL(urlEnv);
760
809
  const routeLocation = useStore({
761
810
  url,
@@ -944,12 +993,21 @@ const QwikRouterProvider = component$((props) => {
944
993
  const newHref = pageData.href;
945
994
  const newURL = new URL(newHref, trackUrl);
946
995
  if (!isSamePath(newURL, trackUrl)) {
947
- trackUrl = newURL;
948
- loadRoutePromise = loadRoute(qwikRouterConfig.routes, qwikRouterConfig.menus, qwikRouterConfig.cacheModules, trackUrl.pathname);
996
+ if (!pageData.isRewrite) {
997
+ trackUrl = newURL;
998
+ }
999
+ loadRoutePromise = loadRoute(
1000
+ qwikRouterConfig.routes,
1001
+ qwikRouterConfig.menus,
1002
+ qwikRouterConfig.cacheModules,
1003
+ newURL.pathname
1004
+ // Load the actual required path.
1005
+ );
949
1006
  }
950
1007
  try {
951
1008
  loadedRoute = await loadRoutePromise;
952
1009
  } catch (e) {
1010
+ console.error(e);
953
1011
  window.location.href = newHref;
954
1012
  return;
955
1013
  }
@@ -984,9 +1042,6 @@ const QwikRouterProvider = component$((props) => {
984
1042
  documentHead.title = resolvedHead.title;
985
1043
  documentHead.frontmatter = resolvedHead.frontmatter;
986
1044
  if (isBrowser) {
987
- if (props.viewTransition !== false) {
988
- document.__q_view_transition__ = true;
989
- }
990
1045
  let scrollState;
991
1046
  if (navType === "popstate") {
992
1047
  scrollState = getScrollHistory();
@@ -1109,8 +1164,27 @@ const QwikRouterProvider = component$((props) => {
1109
1164
  const scrollState2 = currentScrollState(scroller);
1110
1165
  saveScrollHistory(scrollState2);
1111
1166
  }
1112
- clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1113
- _waitUntilRendered(elm).then(() => {
1167
+ const navigate = () => {
1168
+ clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1169
+ return _waitUntilRendered(elm);
1170
+ };
1171
+ const _waitNextPage = () => {
1172
+ if (isServer || props.viewTransition === false) {
1173
+ return navigate();
1174
+ } else {
1175
+ const viewTransition = startViewTransition({
1176
+ update: navigate,
1177
+ types: [
1178
+ "qwik-navigation"
1179
+ ]
1180
+ });
1181
+ if (!viewTransition) {
1182
+ return Promise.resolve();
1183
+ }
1184
+ return viewTransition.ready;
1185
+ }
1186
+ };
1187
+ _waitNextPage().then(() => {
1114
1188
  const container = _getQContainerElement(elm);
1115
1189
  container.setAttribute("q:route", routeName);
1116
1190
  const scrollState2 = currentScrollState(scroller);
@@ -1125,11 +1199,10 @@ const QwikRouterProvider = component$((props) => {
1125
1199
  }
1126
1200
  }
1127
1201
  }
1128
- const promise = run();
1129
1202
  if (isServer) {
1130
- return promise;
1203
+ return run();
1131
1204
  } else {
1132
- return;
1205
+ run();
1133
1206
  }
1134
1207
  });
1135
1208
  return /* @__PURE__ */ jsx(Slot, {});
@@ -1580,6 +1653,7 @@ const serverQrl = (qrl, options) => {
1580
1653
  headers: {
1581
1654
  ...headers,
1582
1655
  "Content-Type": "application/qwik-json",
1656
+ Accept: "application/json, application/qwik-json, text/qwik-json-stream, text/plain",
1583
1657
  // Required so we don't call accidentally
1584
1658
  "X-QRL": qrlHash
1585
1659
  },
@@ -1611,19 +1685,19 @@ const serverQrl = (qrl, options) => {
1611
1685
  } else if (contentType === "application/qwik-json") {
1612
1686
  const str = await res.text();
1613
1687
  const [obj] = _deserialize(str, ctxElm ?? document.documentElement);
1614
- if (res.status >= 500) {
1688
+ if (res.status >= 400) {
1615
1689
  throw obj;
1616
1690
  }
1617
1691
  return obj;
1618
1692
  } else if (contentType === "application/json") {
1619
1693
  const obj = await res.json();
1620
- if (res.status >= 500) {
1694
+ if (res.status >= 400) {
1621
1695
  throw obj;
1622
1696
  }
1623
1697
  return obj;
1624
1698
  } else if (contentType === "text/plain" || contentType === "text/html") {
1625
1699
  const str = await res.text();
1626
- if (res.status >= 500) {
1700
+ if (res.status >= 400) {
1627
1701
  throw str;
1628
1702
  }
1629
1703
  return str;
@@ -1691,7 +1765,8 @@ const deserializeStream = async function* (stream, ctxElm, abortSignal) {
1691
1765
  reader.releaseLock();
1692
1766
  }
1693
1767
  };
1694
- const ServiceWorkerRegister = (props) => jsx$1("script", {
1768
+ const ServiceWorkerRegister = (props) => /* @__PURE__ */ jsx("script", {
1769
+ type: "module",
1695
1770
  dangerouslySetInnerHTML: swRegister,
1696
1771
  nonce: props.nonce
1697
1772
  });
@@ -1816,6 +1891,7 @@ function omitProps(obj, keys) {
1816
1891
  return omittedObj;
1817
1892
  }
1818
1893
  export {
1894
+ ErrorBoundary,
1819
1895
  Form,
1820
1896
  Link,
1821
1897
  QWIK_CITY_SCROLLER,