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

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 (159) hide show
  1. package/README.md +1 -1
  2. package/adapters/static/vite.d.ts +1 -1
  3. package/lib/adapters/azure-swa/vite/index-BqUeglYs.cjs +1 -0
  4. package/lib/adapters/azure-swa/vite/index-CBIchDYq.js +651 -0
  5. package/lib/adapters/azure-swa/vite/index-ClHGw5z1.js +6 -0
  6. package/lib/adapters/azure-swa/vite/index-CrwlB95_.js +22 -0
  7. package/lib/adapters/azure-swa/vite/index-DTIOTwZo.cjs +11 -0
  8. package/lib/adapters/azure-swa/vite/index-vQuPcef3.cjs +1 -0
  9. package/lib/adapters/azure-swa/vite/index.cjs +5 -96
  10. package/lib/adapters/azure-swa/vite/index.d.ts +13 -13
  11. package/lib/adapters/azure-swa/vite/index.mjs +201 -26
  12. package/lib/adapters/bun-server/vite/index-BqUeglYs.cjs +1 -0
  13. package/lib/adapters/bun-server/vite/index-CBIchDYq.js +651 -0
  14. package/lib/adapters/bun-server/vite/index-ClHGw5z1.js +6 -0
  15. package/lib/adapters/bun-server/vite/index-CrwlB95_.js +22 -0
  16. package/lib/adapters/bun-server/vite/index-DTIOTwZo.cjs +11 -0
  17. package/lib/adapters/bun-server/vite/index-vQuPcef3.cjs +1 -0
  18. package/lib/adapters/bun-server/vite/index.cjs +5 -50
  19. package/lib/adapters/bun-server/vite/index.d.ts +14 -14
  20. package/lib/adapters/bun-server/vite/index.mjs +196 -12
  21. package/lib/adapters/cloud-run/vite/index-BqUeglYs.cjs +1 -0
  22. package/lib/adapters/cloud-run/vite/index-CBIchDYq.js +651 -0
  23. package/lib/adapters/cloud-run/vite/index-ClHGw5z1.js +6 -0
  24. package/lib/adapters/cloud-run/vite/index-CrwlB95_.js +22 -0
  25. package/lib/adapters/cloud-run/vite/index-DTIOTwZo.cjs +11 -0
  26. package/lib/adapters/cloud-run/vite/index-vQuPcef3.cjs +1 -0
  27. package/lib/adapters/cloud-run/vite/index.cjs +5 -47
  28. package/lib/adapters/cloud-run/vite/index.d.ts +13 -13
  29. package/lib/adapters/cloud-run/vite/index.mjs +195 -11
  30. package/lib/adapters/cloudflare-pages/vite/index-BIeHg2Cj.cjs +5 -0
  31. package/lib/adapters/cloudflare-pages/vite/index-C455V8_A.cjs +1 -0
  32. package/lib/adapters/cloudflare-pages/vite/index-ClHGw5z1.js +6 -0
  33. package/lib/adapters/cloudflare-pages/vite/index-D3HITboM.js +645 -0
  34. package/lib/adapters/cloudflare-pages/vite/index-DKcVHRBy.cjs +11 -0
  35. package/lib/adapters/cloudflare-pages/vite/index-DwovcBp3.js +22 -0
  36. package/lib/adapters/cloudflare-pages/vite/index-bogwy7wh.js +250 -0
  37. package/lib/adapters/cloudflare-pages/vite/index-vQuPcef3.cjs +1 -0
  38. package/lib/adapters/cloudflare-pages/vite/index.cjs +1 -115
  39. package/lib/adapters/cloudflare-pages/vite/index.d.ts +27 -27
  40. package/lib/adapters/cloudflare-pages/vite/index.mjs +4 -78
  41. package/lib/adapters/deno-server/vite/index-BqUeglYs.cjs +1 -0
  42. package/lib/adapters/deno-server/vite/index-CBIchDYq.js +651 -0
  43. package/lib/adapters/deno-server/vite/index-ClHGw5z1.js +6 -0
  44. package/lib/adapters/deno-server/vite/index-CrwlB95_.js +22 -0
  45. package/lib/adapters/deno-server/vite/index-DTIOTwZo.cjs +11 -0
  46. package/lib/adapters/deno-server/vite/index-vQuPcef3.cjs +1 -0
  47. package/lib/adapters/deno-server/vite/index.cjs +5 -62
  48. package/lib/adapters/deno-server/vite/index.d.ts +14 -14
  49. package/lib/adapters/deno-server/vite/index.mjs +198 -14
  50. package/lib/adapters/netlify-edge/vite/index-BqUeglYs.cjs +1 -0
  51. package/lib/adapters/netlify-edge/vite/index-CBIchDYq.js +651 -0
  52. package/lib/adapters/netlify-edge/vite/index-ClHGw5z1.js +6 -0
  53. package/lib/adapters/netlify-edge/vite/index-CrwlB95_.js +22 -0
  54. package/lib/adapters/netlify-edge/vite/index-DTIOTwZo.cjs +11 -0
  55. package/lib/adapters/netlify-edge/vite/index-vQuPcef3.cjs +1 -0
  56. package/lib/adapters/netlify-edge/vite/index.cjs +6 -129
  57. package/lib/adapters/netlify-edge/vite/index.d.ts +44 -44
  58. package/lib/adapters/netlify-edge/vite/index.mjs +240 -60
  59. package/lib/adapters/node-server/vite/index-BqUeglYs.cjs +1 -0
  60. package/lib/adapters/node-server/vite/index-CBIchDYq.js +651 -0
  61. package/lib/adapters/node-server/vite/index-ClHGw5z1.js +6 -0
  62. package/lib/adapters/node-server/vite/index-CrwlB95_.js +22 -0
  63. package/lib/adapters/node-server/vite/index-DTIOTwZo.cjs +11 -0
  64. package/lib/adapters/node-server/vite/index-vQuPcef3.cjs +1 -0
  65. package/lib/adapters/node-server/vite/index.cjs +5 -50
  66. package/lib/adapters/node-server/vite/index.d.ts +14 -14
  67. package/lib/adapters/node-server/vite/index.mjs +196 -12
  68. package/lib/adapters/shared/vite/index-BqUeglYs.cjs +1 -0
  69. package/lib/adapters/shared/vite/index-CBIchDYq.js +651 -0
  70. package/lib/adapters/shared/vite/index-ClHGw5z1.js +6 -0
  71. package/lib/adapters/shared/vite/index-CrwlB95_.js +22 -0
  72. package/lib/adapters/shared/vite/index-DTIOTwZo.cjs +11 -0
  73. package/lib/adapters/shared/vite/index-vQuPcef3.cjs +1 -0
  74. package/lib/adapters/shared/vite/index.cjs +5 -371
  75. package/lib/adapters/shared/vite/index.d.ts +108 -114
  76. package/lib/adapters/shared/vite/index.mjs +158 -288
  77. package/lib/adapters/ssg/vite/index-BqUeglYs.cjs +1 -0
  78. package/lib/adapters/ssg/vite/index-CBIchDYq.js +651 -0
  79. package/lib/adapters/ssg/vite/index-ClHGw5z1.js +6 -0
  80. package/lib/adapters/ssg/vite/index-CrwlB95_.js +22 -0
  81. package/lib/adapters/ssg/vite/index-DTIOTwZo.cjs +11 -0
  82. package/lib/adapters/ssg/vite/index-vQuPcef3.cjs +1 -0
  83. package/lib/adapters/ssg/vite/index.cjs +5 -0
  84. package/lib/adapters/ssg/vite/index.d.ts +13 -0
  85. package/lib/adapters/ssg/vite/index.mjs +201 -0
  86. package/lib/adapters/vercel-edge/vite/index-BqUeglYs.cjs +1 -0
  87. package/lib/adapters/vercel-edge/vite/index-CBIchDYq.js +651 -0
  88. package/lib/adapters/vercel-edge/vite/index-ClHGw5z1.js +6 -0
  89. package/lib/adapters/vercel-edge/vite/index-CrwlB95_.js +22 -0
  90. package/lib/adapters/vercel-edge/vite/index-DTIOTwZo.cjs +11 -0
  91. package/lib/adapters/vercel-edge/vite/index-vQuPcef3.cjs +1 -0
  92. package/lib/adapters/vercel-edge/vite/index.cjs +5 -118
  93. package/lib/adapters/vercel-edge/vite/index.d.ts +45 -45
  94. package/lib/adapters/vercel-edge/vite/index.mjs +230 -51
  95. package/lib/index.d.ts +1000 -810
  96. package/lib/index.qwik.cjs +438 -203
  97. package/lib/index.qwik.mjs +440 -205
  98. package/lib/middleware/aws-lambda/index.cjs +1 -0
  99. package/lib/middleware/aws-lambda/index.d.ts +49 -48
  100. package/lib/middleware/aws-lambda/index.mjs +27 -41
  101. package/lib/middleware/azure-swa/index.cjs +1 -0
  102. package/lib/middleware/azure-swa/index.d.ts +28 -28
  103. package/lib/middleware/azure-swa/index.mjs +46 -269
  104. package/lib/middleware/bun/index.cjs +1 -0
  105. package/lib/middleware/bun/index.d.ts +35 -35
  106. package/lib/middleware/bun/index.mjs +68 -120
  107. package/lib/middleware/cloudflare-pages/index.cjs +1 -0
  108. package/lib/middleware/cloudflare-pages/index.d.ts +35 -35
  109. package/lib/middleware/cloudflare-pages/index.mjs +48 -80
  110. package/lib/middleware/deno/index.cjs +1 -0
  111. package/lib/middleware/deno/index.d.ts +47 -47
  112. package/lib/middleware/deno/index.mjs +63 -110
  113. package/lib/middleware/firebase/index.cjs +1 -0
  114. package/lib/middleware/firebase/index.d.ts +26 -26
  115. package/lib/middleware/firebase/index.mjs +16 -28
  116. package/lib/middleware/netlify-edge/index.cjs +1 -0
  117. package/lib/middleware/netlify-edge/index.d.ts +27 -27
  118. package/lib/middleware/netlify-edge/index.mjs +36 -64
  119. package/lib/middleware/node/index.cjs +1 -314
  120. package/lib/middleware/node/index.d.ts +64 -64
  121. package/lib/middleware/node/index.mjs +116 -198
  122. package/lib/middleware/request-handler/index.cjs +11 -1538
  123. package/lib/middleware/request-handler/index.d.ts +711 -676
  124. package/lib/middleware/request-handler/index.mjs +895 -1281
  125. package/lib/middleware/vercel-edge/index.cjs +1 -0
  126. package/lib/middleware/vercel-edge/index.d.ts +26 -26
  127. package/lib/middleware/vercel-edge/index.mjs +47 -82
  128. package/lib/modules.d.ts +4 -12
  129. package/lib/service-worker.cjs +1 -267
  130. package/lib/service-worker.d.ts +15 -4
  131. package/lib/service-worker.mjs +3 -263
  132. package/lib/ssg/deno.cjs +1 -0
  133. package/lib/ssg/deno.mjs +6 -0
  134. package/lib/ssg/index-CBIchDYq.js +651 -0
  135. package/lib/ssg/index-ClHGw5z1.js +6 -0
  136. package/lib/ssg/index-DTIOTwZo.cjs +11 -0
  137. package/lib/ssg/index-vQuPcef3.cjs +1 -0
  138. package/lib/ssg/index.cjs +1 -0
  139. package/lib/{static → ssg}/index.d.ts +96 -96
  140. package/lib/ssg/index.mjs +22 -0
  141. package/lib/ssg/node.cjs +11 -0
  142. package/lib/ssg/node.mjs +651 -0
  143. package/lib/vite/index.cjs +29 -27484
  144. package/lib/vite/index.d.ts +170 -154
  145. package/lib/vite/index.mjs +1422 -27288
  146. package/modules.d.ts +4 -12
  147. package/package.json +51 -40
  148. package/ssg.d.ts +2 -0
  149. package/static.d.ts +1 -1
  150. package/lib/adapters/static/vite/index.cjs +0 -361
  151. package/lib/adapters/static/vite/index.d.ts +0 -10
  152. package/lib/adapters/static/vite/index.mjs +0 -324
  153. package/lib/static/deno.mjs +0 -8
  154. package/lib/static/index.cjs +0 -67
  155. package/lib/static/index.mjs +0 -48
  156. package/lib/static/node.cjs +0 -1124
  157. package/lib/static/node.mjs +0 -1086
  158. package/middleware/request-handler/generated/not-found-paths.ts +0 -7
  159. package/middleware/request-handler/generated/static-paths.ts +0 -35
@@ -1,10 +1,12 @@
1
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, untrack, sync$, isDev, 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";
2
+ import { component$, useErrorBoundary, useOnWindow, $, Slot, createAsyncComputed$, isBrowser, createContextId, useContext, implicit$FirstArg, noSerialize, useVisibleTask$, useServerData, useSignal, untrack, sync$, isDev, withLocale, event$, useStyles$, isServer, useStore, useContextProvider, useTask$, getLocale, jsx as jsx$1, SkipRender, createElement } from "@qwik.dev/core";
3
+ import { p } from "@qwik.dev/core/preloader";
4
+ import { _deserialize, _UNINITIALIZED, _getContextContainer, SerializerSymbol, _getContextElement, _hasStoreEffects, _getQContainerElement, forceStoreEffects, _waitUntilRendered, _resolveContextWithoutSequentialScope, _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
+ import { renderToStream } from "@qwik.dev/core/server";
8
10
  const ErrorBoundary = component$((props) => {
9
11
  const store2 = useErrorBoundary();
10
12
  useOnWindow("qerror", $((e) => {
@@ -19,132 +21,38 @@ const ErrorBoundary = component$((props) => {
19
21
  });
20
22
  const MODULE_CACHE = /* @__PURE__ */ new WeakMap();
21
23
  const CLIENT_DATA_CACHE = /* @__PURE__ */ new Map();
22
- const PREFETCHED_NAVIGATE_PATHS = /* @__PURE__ */ new Set();
23
24
  const QACTION_KEY = "qaction";
25
+ const QLOADER_KEY = "qloaders";
24
26
  const QFN_KEY = "qfunc";
25
27
  const QDATA_KEY = "qdata";
26
- const toPath = (url) => url.pathname + url.search + url.hash;
27
- const toUrl = (url, baseUrl) => new URL(url, baseUrl.href);
28
- const isSameOrigin = (a, b) => a.origin === b.origin;
29
- const withSlash = (path) => path.endsWith("/") ? path : path + "/";
30
- const isSamePathname = ({ pathname: a }, { pathname: b }) => {
31
- const lDiff = Math.abs(a.length - b.length);
32
- return lDiff === 0 ? a === b : lDiff === 1 && withSlash(a) === withSlash(b);
33
- };
34
- const isSameSearchQuery = (a, b) => a.search === b.search;
35
- const isSamePath = (a, b) => isSameSearchQuery(a, b) && isSamePathname(a, b);
36
- const getClientDataPath = (pathname, pageSearch, action) => {
37
- let search = pageSearch ?? "";
38
- if (action) {
39
- search += (search ? "&" : "?") + QACTION_KEY + "=" + encodeURIComponent(action.id);
40
- }
41
- return pathname + (pathname.endsWith("/") ? "" : "/") + "q-data.json" + search;
42
- };
43
- const getClientNavPath = (props, baseUrl) => {
44
- const href = props.href;
45
- if (typeof href === "string" && typeof props.target !== "string" && !props.reload) {
46
- try {
47
- const linkUrl = toUrl(href.trim(), baseUrl.url);
48
- const currentUrl = toUrl("", baseUrl.url);
49
- if (isSameOrigin(linkUrl, currentUrl)) {
50
- return toPath(linkUrl);
51
- }
52
- } catch (e) {
53
- console.error(e);
54
- }
55
- } else if (props.reload) {
56
- return toPath(toUrl("", baseUrl.url));
57
- }
58
- return null;
59
- };
60
- const shouldPrefetchData = (clientNavPath, currentLoc) => {
61
- if (clientNavPath) {
62
- const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
63
- const currentUrl = toUrl("", currentLoc.url);
64
- return !isSamePath(prefetchUrl, currentUrl);
65
- }
66
- return false;
67
- };
68
- const shouldPrefetchSymbols = (clientNavPath, currentLoc) => {
69
- if (clientNavPath) {
70
- const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
71
- const currentUrl = toUrl("", currentLoc.url);
72
- return !isSamePathname(prefetchUrl, currentUrl);
73
- }
74
- return false;
75
- };
76
- const isPromise = (value) => {
77
- return value && typeof value.then === "function";
78
- };
79
- const deepFreeze = (obj) => {
80
- if (obj == null) {
81
- return obj;
82
- }
83
- Object.getOwnPropertyNames(obj).forEach((prop) => {
84
- const value = obj[prop];
85
- if (value && typeof value === "object" && !Object.isFrozen(value)) {
86
- deepFreeze(value);
87
- }
88
- });
89
- return Object.freeze(obj);
90
- };
91
- const clientNavigate = (win, navType, fromURL, toURL, replaceState = false) => {
92
- if (navType !== "popstate") {
93
- const samePath = isSamePath(fromURL, toURL);
94
- const sameHash = fromURL.hash === toURL.hash;
95
- if (!samePath || !sameHash) {
96
- const newState = {
97
- _qRouterScroll: newScrollState()
98
- };
99
- if (replaceState) {
100
- win.history.replaceState(newState, "", toPath(toURL));
101
- } else {
102
- win.history.pushState(newState, "", toPath(toURL));
103
- }
104
- }
105
- }
106
- };
107
- const newScrollState = () => {
108
- return {
109
- x: 0,
110
- y: 0,
111
- w: 0,
112
- h: 0
113
- };
114
- };
115
- const prefetchSymbols = (path) => {
116
- if (isBrowser) {
117
- path = path.endsWith("/") ? path : path + "/";
118
- if (!PREFETCHED_NAVIGATE_PATHS.has(path)) {
119
- PREFETCHED_NAVIGATE_PATHS.add(path);
120
- document.dispatchEvent(new CustomEvent("qprefetch", {
121
- detail: {
122
- links: [
123
- path
124
- ]
125
- }
126
- }));
127
- }
128
- }
129
- };
130
- const loadClientData = async (url, element, opts) => {
28
+ const Q_ROUTE = "q:route";
29
+ const DEFAULT_LOADERS_SERIALIZATION_STRATEGY = globalThis.__DEFAULT_LOADERS_SERIALIZATION_STRATEGY__ || "never";
30
+ const MAX_Q_DATA_RETRY_COUNT = 3;
31
+ const loadClientData = async (url, element, opts, retryCount = 0) => {
131
32
  const pagePathname = url.pathname;
132
33
  const pageSearch = url.search;
133
- const clientDataPath = getClientDataPath(pagePathname, pageSearch, opts?.action);
34
+ const clientDataPath = getClientDataPath(pagePathname, pageSearch, {
35
+ actionId: opts?.action?.id,
36
+ loaderIds: opts?.loaderIds
37
+ });
134
38
  let qData;
135
39
  if (!opts?.action) {
136
40
  qData = CLIENT_DATA_CACHE.get(clientDataPath);
137
41
  }
138
- if (opts?.prefetchSymbols !== false) {
139
- prefetchSymbols(pagePathname);
42
+ if (opts?.preloadRouteBundles !== false) {
43
+ preloadRouteBundles(pagePathname, 0.8);
140
44
  }
141
45
  let resolveFn;
142
46
  if (!qData) {
143
- const fetchOptions = getFetchOptions(opts?.action);
47
+ const fetchOptions = getFetchOptions(opts?.action, opts?.clearCache);
144
48
  if (opts?.action) {
145
49
  opts.action.data = void 0;
146
50
  }
147
51
  qData = fetch(clientDataPath, fetchOptions).then((rsp) => {
52
+ if (rsp.status === 404 && opts?.loaderIds && retryCount < MAX_Q_DATA_RETRY_COUNT) {
53
+ opts.loaderIds = void 0;
54
+ return loadClientData(url, element, opts, retryCount + 1);
55
+ }
148
56
  if (rsp.redirected) {
149
57
  const redirectedURL = new URL(rsp.url);
150
58
  const isQData = redirectedURL.pathname.endsWith("/q-data.json");
@@ -196,16 +104,19 @@ const loadClientData = async (url, element, opts) => {
196
104
  return v;
197
105
  });
198
106
  };
199
- const getFetchOptions = (action) => {
107
+ const getFetchOptions = (action, noCache) => {
200
108
  const actionData = action?.data;
201
109
  if (!actionData) {
202
- return {
203
- cache: "no-cache",
204
- headers: {
205
- "Cache-Control": "no-cache",
206
- Pragma: "no-cache"
207
- }
208
- };
110
+ if (noCache) {
111
+ return {
112
+ cache: "no-cache",
113
+ headers: {
114
+ "Cache-Control": "no-cache",
115
+ Pragma: "no-cache"
116
+ }
117
+ };
118
+ }
119
+ return void 0;
209
120
  }
210
121
  if (actionData instanceof FormData) {
211
122
  return {
@@ -217,11 +128,108 @@ const getFetchOptions = (action) => {
217
128
  method: "POST",
218
129
  body: JSON.stringify(actionData),
219
130
  headers: {
220
- "Content-Type": "application/json, charset=UTF-8"
131
+ "Content-Type": "application/json; charset=UTF-8"
221
132
  }
222
133
  };
223
134
  }
224
135
  };
136
+ const toPath = (url) => url.pathname + url.search + url.hash;
137
+ const toUrl = (url, baseUrl) => new URL(url, baseUrl.href);
138
+ const isSameOrigin = (a, b) => a.origin === b.origin;
139
+ const withSlash = (path) => path.endsWith("/") ? path : path + "/";
140
+ const isSamePathname = ({ pathname: a }, { pathname: b }) => {
141
+ const lDiff = Math.abs(a.length - b.length);
142
+ return lDiff === 0 ? a === b : lDiff === 1 && withSlash(a) === withSlash(b);
143
+ };
144
+ const isSameSearchQuery = (a, b) => a.search === b.search;
145
+ const isSamePath = (a, b) => isSameSearchQuery(a, b) && isSamePathname(a, b);
146
+ const getClientDataPath = (pathname, pageSearch, options) => {
147
+ let search = pageSearch ?? "";
148
+ if (options?.actionId) {
149
+ search += (search ? "&" : "?") + QACTION_KEY + "=" + encodeURIComponent(options.actionId);
150
+ }
151
+ if (options?.loaderIds) {
152
+ for (const loaderId of options.loaderIds) {
153
+ search += (search ? "&" : "?") + QLOADER_KEY + "=" + encodeURIComponent(loaderId);
154
+ }
155
+ }
156
+ return pathname + (pathname.endsWith("/") ? "" : "/") + "q-data.json" + search;
157
+ };
158
+ const getClientNavPath = (props, baseUrl) => {
159
+ const href = props.href;
160
+ if (typeof href === "string" && typeof props.target !== "string" && !props.reload) {
161
+ try {
162
+ const linkUrl = toUrl(href.trim(), baseUrl.url);
163
+ const currentUrl = toUrl("", baseUrl.url);
164
+ if (isSameOrigin(linkUrl, currentUrl)) {
165
+ return toPath(linkUrl);
166
+ }
167
+ } catch (e) {
168
+ console.error(e);
169
+ }
170
+ } else if (props.reload) {
171
+ return toPath(toUrl("", baseUrl.url));
172
+ }
173
+ return null;
174
+ };
175
+ const shouldPreload = (clientNavPath, currentLoc) => {
176
+ if (clientNavPath) {
177
+ const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
178
+ const currentUrl = toUrl("", currentLoc.url);
179
+ return !isSamePathname(prefetchUrl, currentUrl);
180
+ }
181
+ return false;
182
+ };
183
+ const isPromise = (value) => {
184
+ return value && typeof value.then === "function";
185
+ };
186
+ const createLoaderSignal = (loadersObject, loaderId, url, serializationStrategy, container) => {
187
+ return createAsyncComputed$(async () => {
188
+ if (isBrowser && loadersObject[loaderId] === _UNINITIALIZED) {
189
+ const data = await loadClientData(url, void 0, {
190
+ loaderIds: [
191
+ loaderId
192
+ ]
193
+ });
194
+ loadersObject[loaderId] = data?.loaders[loaderId] ?? _UNINITIALIZED;
195
+ }
196
+ return loadersObject[loaderId];
197
+ }, {
198
+ container,
199
+ serializationStrategy
200
+ });
201
+ };
202
+ const clientNavigate = (win, navType, fromURL, toURL, replaceState = false) => {
203
+ if (navType !== "popstate") {
204
+ const samePath = isSamePath(fromURL, toURL);
205
+ const sameHash = fromURL.hash === toURL.hash;
206
+ if (!samePath || !sameHash) {
207
+ const newState = {
208
+ _qRouterScroll: newScrollState()
209
+ };
210
+ if (replaceState) {
211
+ win.history.replaceState(newState, "", toPath(toURL));
212
+ } else {
213
+ win.history.pushState(newState, "", toPath(toURL));
214
+ }
215
+ }
216
+ }
217
+ };
218
+ const newScrollState = () => {
219
+ return {
220
+ x: 0,
221
+ y: 0,
222
+ w: 0,
223
+ h: 0
224
+ };
225
+ };
226
+ const preloadRouteBundles = (path, probability = 0.8) => {
227
+ if (isBrowser) {
228
+ path = path.endsWith("/") ? path : path + "/";
229
+ path = path.length > 1 && path.startsWith("/") ? path.slice(1) : path;
230
+ p(path, probability);
231
+ }
232
+ };
225
233
  const RouteStateContext = /* @__PURE__ */ createContextId("qc-s");
226
234
  const ContentContext = /* @__PURE__ */ createContextId("qc-c");
227
235
  const ContentInternalContext = /* @__PURE__ */ createContextId("qc-ic");
@@ -249,54 +257,77 @@ const Link = component$((props) => {
249
257
  const nav = useNavigate();
250
258
  const loc = useLocation();
251
259
  const originalHref = props.href;
260
+ const anchorRef = useSignal();
252
261
  const { onClick$, prefetch: prefetchProp, reload, replaceState, scroll, ...linkProps } = /* @__PURE__ */ (() => props)();
253
262
  const clientNavPath = untrack(() => getClientNavPath({
254
263
  ...linkProps,
255
264
  reload
256
265
  }, loc));
257
266
  linkProps.href = clientNavPath || originalHref;
258
- const prefetchData = untrack(() => !!clientNavPath && prefetchProp !== false && prefetchProp !== "js" && shouldPrefetchData(clientNavPath, loc) || void 0);
259
- const prefetch = untrack(() => prefetchData || !!clientNavPath && prefetchProp !== false && shouldPrefetchSymbols(clientNavPath, loc));
267
+ const prefetchData = untrack(() => !!clientNavPath && prefetchProp !== false && prefetchProp !== "js" || void 0);
268
+ const prefetch = untrack(() => prefetchData || !!clientNavPath && prefetchProp !== false && shouldPreload(clientNavPath, loc));
260
269
  const handlePrefetch = prefetch ? $((_, elm) => {
261
270
  if (navigator.connection?.saveData) {
262
271
  return;
263
272
  }
264
273
  if (elm && elm.href) {
265
274
  const url = new URL(elm.href);
266
- prefetchSymbols(url.pathname);
275
+ preloadRouteBundles(url.pathname);
267
276
  if (elm.hasAttribute("data-prefetch")) {
268
277
  loadClientData(url, elm, {
269
- prefetchSymbols: false,
278
+ preloadRouteBundles: false,
270
279
  isPrefetch: true
271
280
  });
272
281
  }
273
282
  }
274
283
  }) : void 0;
275
- const preventDefault = clientNavPath ? sync$((event, target) => {
284
+ const preventDefault = clientNavPath ? sync$((event) => {
276
285
  if (!(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) {
277
286
  event.preventDefault();
278
287
  }
279
288
  }) : void 0;
280
- const handleClick = clientNavPath ? $(async (event, elm) => {
289
+ const handleClientSideNavigation = clientNavPath ? $((event, elm) => {
281
290
  if (event.defaultPrevented) {
282
291
  if (elm.href) {
283
292
  elm.setAttribute("aria-pressed", "true");
284
- await nav(elm.href, {
293
+ nav(elm.href, {
285
294
  forceReload: reload,
286
295
  replaceState,
287
296
  scroll
297
+ }).then(() => {
298
+ elm.removeAttribute("aria-pressed");
288
299
  });
289
- elm.removeAttribute("aria-pressed");
290
300
  }
291
301
  }
292
302
  }) : void 0;
303
+ const handlePreload = $((_, elm) => {
304
+ const url = new URL(elm.href);
305
+ preloadRouteBundles(url.pathname, 1);
306
+ });
307
+ useVisibleTask$(({ track }) => {
308
+ track(() => loc.url.pathname);
309
+ const handler = linkProps.onQVisible$;
310
+ if (handler) {
311
+ const event = new CustomEvent("qvisible");
312
+ if (Array.isArray(handler)) {
313
+ handler.flat(10).forEach((handler2) => handler2?.(event, anchorRef.value));
314
+ } else {
315
+ handler?.(event, anchorRef.value);
316
+ }
317
+ }
318
+ if (!isDev && anchorRef.value) {
319
+ handlePrefetch?.(void 0, anchorRef.value);
320
+ }
321
+ });
293
322
  return /* @__PURE__ */ jsx("a", {
323
+ ref: anchorRef,
294
324
  "q:link": !!clientNavPath,
295
325
  ...linkProps,
296
326
  onClick$: [
297
327
  preventDefault,
328
+ handlePreload,
298
329
  onClick$,
299
- handleClick
330
+ handleClientSideNavigation
300
331
  ],
301
332
  "data-prefetch": prefetchData,
302
333
  onMouseOver$: [
@@ -307,16 +338,13 @@ const Link = component$((props) => {
307
338
  linkProps.onFocus$,
308
339
  handlePrefetch
309
340
  ],
310
- // Don't prefetch on visible in dev mode
311
- onQVisible$: [
312
- linkProps.onQVisible$,
313
- !isDev ? handlePrefetch : void 0
314
- ],
341
+ // We need to prevent the onQVisible$ from being called twice since it is handled in the visible task
342
+ onQVisible$: [],
315
343
  children: /* @__PURE__ */ jsx(Slot, {})
316
344
  });
317
345
  });
318
- const resolveHead = (endpoint, routeLocation, contentModules, locale) => {
319
- const head = createDocumentHead();
346
+ const resolveHead = (endpoint, routeLocation, contentModules, locale, defaults) => {
347
+ const head = createDocumentHead(defaults);
320
348
  const getData = (loaderOrAction) => {
321
349
  const id = loaderOrAction.__id;
322
350
  if (loaderOrAction.__brand === "server_loader") {
@@ -372,13 +400,23 @@ const mergeArray = (existingArr, newArr) => {
372
400
  }
373
401
  }
374
402
  };
375
- const createDocumentHead = () => ({
376
- title: "",
377
- meta: [],
378
- links: [],
379
- styles: [],
380
- scripts: [],
381
- frontmatter: {}
403
+ const createDocumentHead = (defaults) => ({
404
+ title: defaults?.title || "",
405
+ meta: [
406
+ ...defaults?.meta || []
407
+ ],
408
+ links: [
409
+ ...defaults?.links || []
410
+ ],
411
+ styles: [
412
+ ...defaults?.styles || []
413
+ ],
414
+ scripts: [
415
+ ...defaults?.scripts || []
416
+ ],
417
+ frontmatter: {
418
+ ...defaults?.frontmatter
419
+ }
382
420
  });
383
421
  function matchRoute(route, path) {
384
422
  const routeIdx = startIdxSkipSlash(route);
@@ -388,6 +426,9 @@ function matchRoute(route, path) {
388
426
  return matchRoutePart(route, routeIdx, routeLength, path, pathIdx, pathLength);
389
427
  }
390
428
  function matchRoutePart(route, routeIdx, routeLength, path, pathIdx, pathLength) {
429
+ if (path.startsWith("/build/")) {
430
+ return null;
431
+ }
391
432
  let params = null;
392
433
  while (routeIdx < routeLength) {
393
434
  const routeCh = route.charCodeAt(routeIdx++);
@@ -489,18 +530,42 @@ function lastIndexOf(text, start, match, searchIdx, notFoundIdx) {
489
530
  }
490
531
  return idx > start ? idx : notFoundIdx;
491
532
  }
533
+ var RouteDataProp = /* @__PURE__ */ (function(RouteDataProp2) {
534
+ RouteDataProp2[RouteDataProp2["RouteName"] = 0] = "RouteName";
535
+ RouteDataProp2[RouteDataProp2["Loaders"] = 1] = "Loaders";
536
+ RouteDataProp2[RouteDataProp2["OriginalPathname"] = 2] = "OriginalPathname";
537
+ RouteDataProp2[RouteDataProp2["RouteBundleNames"] = 3] = "RouteBundleNames";
538
+ return RouteDataProp2;
539
+ })({});
540
+ var MenuDataProp = /* @__PURE__ */ (function(MenuDataProp2) {
541
+ MenuDataProp2[MenuDataProp2["Pathname"] = 0] = "Pathname";
542
+ MenuDataProp2[MenuDataProp2["MenuLoader"] = 1] = "MenuLoader";
543
+ return MenuDataProp2;
544
+ })({});
545
+ const deepFreeze = (obj) => {
546
+ if (obj == null) {
547
+ return obj;
548
+ }
549
+ Object.getOwnPropertyNames(obj).forEach((prop) => {
550
+ const value = obj[prop];
551
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
552
+ deepFreeze(value);
553
+ }
554
+ });
555
+ return Object.freeze(obj);
556
+ };
492
557
  const loadRoute = async (routes, menus, cacheModules, pathname) => {
493
558
  if (!Array.isArray(routes)) {
494
559
  return null;
495
560
  }
496
561
  for (const routeData of routes) {
497
- const routeName = routeData[0];
562
+ const routeName = routeData[RouteDataProp.RouteName];
498
563
  const params = matchRoute(routeName, pathname);
499
564
  if (!params) {
500
565
  continue;
501
566
  }
502
- const loaders = routeData[1];
503
- const routeBundleNames = routeData[3];
567
+ const loaders = routeData[RouteDataProp.Loaders];
568
+ const routeBundleNames = routeData[RouteDataProp.RouteBundleNames];
504
569
  const modules = new Array(loaders.length);
505
570
  const pendingLoads = [];
506
571
  loaders.forEach((moduleLoader, i) => {
@@ -545,9 +610,9 @@ const loadModule = (moduleLoader, pendingLoads, moduleSetter, cacheModules) => {
545
610
  const getMenuLoader = (menus, pathname) => {
546
611
  if (menus) {
547
612
  pathname = pathname.endsWith("/") ? pathname : pathname + "/";
548
- const menu = menus.find((m) => m[0] === pathname || pathname.startsWith(m[0] + (pathname.endsWith("/") ? "" : "/")));
613
+ const menu = menus.find((m) => m[MenuDataProp.Pathname] === pathname || pathname.startsWith(m[MenuDataProp.Pathname] + (pathname.endsWith("/") ? "" : "/")));
549
614
  if (menu) {
550
- return menu[1];
615
+ return menu[MenuDataProp.MenuLoader];
551
616
  }
552
617
  }
553
618
  };
@@ -739,8 +804,8 @@ const spaInit = event$((_, el) => {
739
804
  };
740
805
  win[scrollEnabled] = true;
741
806
  setTimeout(() => {
742
- addEventListener("popstate", win[initPopstate]);
743
- addEventListener("scroll", win[initScroll], {
807
+ win.addEventListener("popstate", win[initPopstate]);
808
+ win.addEventListener("scroll", win[initScroll], {
744
809
  passive: true
745
810
  });
746
811
  document.body.addEventListener("click", win[initAnchors]);
@@ -752,14 +817,45 @@ const spaInit = event$((_, el) => {
752
817
  }, 0);
753
818
  }
754
819
  });
820
+ const startViewTransition = (params) => {
821
+ if (!params.update) {
822
+ return;
823
+ }
824
+ if ("startViewTransition" in document) {
825
+ let transition;
826
+ try {
827
+ transition = document.startViewTransition(params);
828
+ } catch {
829
+ transition = document.startViewTransition(params.update);
830
+ }
831
+ const event = new CustomEvent("qviewtransition", {
832
+ detail: transition
833
+ });
834
+ document.dispatchEvent(event);
835
+ return transition;
836
+ } else {
837
+ params.update?.();
838
+ }
839
+ };
755
840
  const QWIK_CITY_SCROLLER = "_qCityScroller";
756
841
  const QWIK_ROUTER_SCROLLER = "_qRouterScroller";
757
842
  const preventNav = {};
758
843
  const internalState = {
759
844
  navCount: 0
760
845
  };
761
- const QwikRouterProvider = component$((props) => {
762
- useStyles$(`:root{view-transition-name:none}`);
846
+ const useQwikRouter = (props) => {
847
+ useStyles$(`
848
+ @layer qwik {
849
+ @supports selector(html:active-view-transition-type(type)) {
850
+ html:active-view-transition-type(qwik-navigation) {
851
+ :root{view-transition-name:none}
852
+ }
853
+ }
854
+ @supports not selector(html:active-view-transition-type(type)) {
855
+ :root{view-transition-name:none}
856
+ }
857
+ }
858
+ `);
763
859
  const env = useQwikRouterEnv();
764
860
  if (!env?.params) {
765
861
  throw new Error(`Missing Qwik Router Env Data for help visit https://github.com/QwikDev/qwik/issues/6237`);
@@ -768,19 +864,40 @@ const QwikRouterProvider = component$((props) => {
768
864
  if (!urlEnv) {
769
865
  throw new Error(`Missing Qwik URL Env Data`);
770
866
  }
867
+ const serverHead = useServerData("documentHead");
868
+ if (isServer) {
869
+ if (env.ev.originalUrl.pathname !== env.ev.url.pathname && !__EXPERIMENTAL__.enableRequestRewrite) {
870
+ 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.`);
871
+ }
872
+ }
771
873
  const url = new URL(urlEnv);
772
- const routeLocation = useStore({
874
+ const routeLocationTarget = {
773
875
  url,
774
876
  params: env.params,
775
877
  isNavigating: false,
776
878
  prevUrl: void 0
777
- }, {
879
+ };
880
+ const routeLocation = useStore(routeLocationTarget, {
778
881
  deep: false
779
882
  });
780
883
  const navResolver = {};
781
- const loaderState = _weakSerialize(useStore(env.response.loaders, {
782
- deep: false
783
- }));
884
+ const container = _getContextContainer();
885
+ const getSerializationStrategy = (loaderId) => {
886
+ return env.response.loadersSerializationStrategy.get(loaderId) || DEFAULT_LOADERS_SERIALIZATION_STRATEGY;
887
+ };
888
+ const loadersObject = {};
889
+ const loaderState = {};
890
+ for (const [key, value] of Object.entries(env.response.loaders)) {
891
+ loadersObject[key] = value;
892
+ loaderState[key] = createLoaderSignal(loadersObject, key, url, getSerializationStrategy(key), container);
893
+ }
894
+ loadersObject[SerializerSymbol] = (obj) => {
895
+ const loadersSerializationObject = {};
896
+ for (const [k, v] of Object.entries(obj)) {
897
+ loadersSerializationObject[k] = getSerializationStrategy(k) === "always" ? v : _UNINITIALIZED;
898
+ }
899
+ return loadersSerializationObject;
900
+ };
784
901
  const routeInternal = useSignal({
785
902
  type: "initial",
786
903
  dest: url,
@@ -788,7 +905,7 @@ const QwikRouterProvider = component$((props) => {
788
905
  replaceState: false,
789
906
  scroll: true
790
907
  });
791
- const documentHead = useStore(createDocumentHead);
908
+ const documentHead = useStore(() => createDocumentHead(serverHead));
792
909
  const content = useStore({
793
910
  headings: void 0,
794
911
  menu: void 0
@@ -873,7 +990,7 @@ const QwikRouterProvider = component$((props) => {
873
990
  let scroller = document.getElementById(QWIK_ROUTER_SCROLLER);
874
991
  if (!scroller) {
875
992
  scroller = document.getElementById(QWIK_CITY_SCROLLER);
876
- if (scroller) {
993
+ if (scroller && isDev) {
877
994
  console.warn(`Please update your scroller ID to "${QWIK_ROUTER_SCROLLER}" as "${QWIK_CITY_SCROLLER}" is deprecated and will be removed in V3`);
878
995
  }
879
996
  }
@@ -934,10 +1051,10 @@ const QwikRouterProvider = component$((props) => {
934
1051
  } else {
935
1052
  trackUrl = new URL(navigation.dest, location);
936
1053
  if (trackUrl.pathname.endsWith("/")) {
937
- if (!qwikRouterConfig.trailingSlash) {
1054
+ if (globalThis.__NO_TRAILING_SLASH__) {
938
1055
  trackUrl.pathname = trackUrl.pathname.slice(0, -1);
939
1056
  }
940
- } else if (qwikRouterConfig.trailingSlash) {
1057
+ } else if (!globalThis.__NO_TRAILING_SLASH__) {
941
1058
  trackUrl.pathname += "/";
942
1059
  }
943
1060
  let loadRoutePromise = loadRoute(qwikRouterConfig.routes, qwikRouterConfig.menus, qwikRouterConfig.cacheModules, trackUrl.pathname);
@@ -956,12 +1073,21 @@ const QwikRouterProvider = component$((props) => {
956
1073
  const newHref = pageData.href;
957
1074
  const newURL = new URL(newHref, trackUrl);
958
1075
  if (!isSamePath(newURL, trackUrl)) {
959
- trackUrl = newURL;
960
- loadRoutePromise = loadRoute(qwikRouterConfig.routes, qwikRouterConfig.menus, qwikRouterConfig.cacheModules, trackUrl.pathname);
1076
+ if (!pageData.isRewrite) {
1077
+ trackUrl = newURL;
1078
+ }
1079
+ loadRoutePromise = loadRoute(
1080
+ qwikRouterConfig.routes,
1081
+ qwikRouterConfig.menus,
1082
+ qwikRouterConfig.cacheModules,
1083
+ newURL.pathname
1084
+ // Load the actual required path.
1085
+ );
961
1086
  }
962
1087
  try {
963
1088
  loadedRoute = await loadRoutePromise;
964
1089
  } catch (e) {
1090
+ console.error(e);
965
1091
  window.location.href = newHref;
966
1092
  return;
967
1093
  }
@@ -970,25 +1096,38 @@ const QwikRouterProvider = component$((props) => {
970
1096
  const [routeName, params, mods, menu] = loadedRoute;
971
1097
  const contentModules = mods;
972
1098
  const pageModule = contentModules[contentModules.length - 1];
973
- const isRedirect = navType === "form" && !isSamePath(trackUrl, prevUrl);
974
- if (navigation.dest.search && !isRedirect) {
1099
+ if (navigation.dest.search && !!isSamePath(trackUrl, prevUrl)) {
975
1100
  trackUrl.search = navigation.dest.search;
976
1101
  }
1102
+ let shouldForcePrevUrl = false;
1103
+ let shouldForceUrl = false;
1104
+ let shouldForceParams = false;
977
1105
  if (!isSamePath(trackUrl, prevUrl)) {
978
- routeLocation.prevUrl = prevUrl;
1106
+ if (_hasStoreEffects(routeLocation, "prevUrl")) {
1107
+ shouldForcePrevUrl = true;
1108
+ }
1109
+ routeLocationTarget.prevUrl = prevUrl;
1110
+ }
1111
+ if (routeLocationTarget.url !== trackUrl) {
1112
+ if (_hasStoreEffects(routeLocation, "url")) {
1113
+ shouldForceUrl = true;
1114
+ }
1115
+ routeLocationTarget.url = trackUrl;
1116
+ }
1117
+ if (routeLocationTarget.params !== params) {
1118
+ if (_hasStoreEffects(routeLocation, "params")) {
1119
+ shouldForceParams = true;
1120
+ }
1121
+ routeLocationTarget.params = params;
979
1122
  }
980
- routeLocation.url = trackUrl;
981
- routeLocation.params = {
982
- ...params
983
- };
984
1123
  routeInternal.untrackedValue = {
985
1124
  type: navType,
986
1125
  dest: trackUrl
987
1126
  };
988
- const resolvedHead = resolveHead(clientPageData, routeLocation, contentModules, locale);
1127
+ const resolvedHead = resolveHead(clientPageData, routeLocation, contentModules, locale, serverHead);
989
1128
  content.headings = pageModule.headings;
990
1129
  content.menu = menu;
991
- contentInternal.value = noSerialize(contentModules);
1130
+ contentInternal.untrackedValue = noSerialize(contentModules);
992
1131
  documentHead.links = resolvedHead.links;
993
1132
  documentHead.meta = resolvedHead.meta;
994
1133
  documentHead.styles = resolvedHead.styles;
@@ -996,23 +1135,30 @@ const QwikRouterProvider = component$((props) => {
996
1135
  documentHead.title = resolvedHead.title;
997
1136
  documentHead.frontmatter = resolvedHead.frontmatter;
998
1137
  if (isBrowser) {
999
- if (props.viewTransition !== false) {
1000
- document.__q_view_transition__ = true;
1001
- }
1002
1138
  let scrollState;
1003
1139
  if (navType === "popstate") {
1004
1140
  scrollState = getScrollHistory();
1005
1141
  }
1006
1142
  const scroller = document.getElementById(QWIK_ROUTER_SCROLLER) ?? document.documentElement;
1007
- if (navigation.scroll && (!navigation.forceReload || !isSamePath(trackUrl, prevUrl)) && (navType === "link" || navType === "popstate") || isRedirect) {
1143
+ if (navigation.scroll && (!navigation.forceReload || !isSamePath(trackUrl, prevUrl)) && (navType === "link" || navType === "popstate") || navType === "form" && !isSamePath(trackUrl, prevUrl)) {
1008
1144
  document.__q_scroll_restore__ = () => restoreScroll(navType, trackUrl, prevUrl, scroller, scrollState);
1009
1145
  }
1010
1146
  const loaders = clientPageData?.loaders;
1011
- const win = window;
1012
1147
  if (loaders) {
1013
- Object.assign(loaderState, loaders);
1148
+ const container2 = _getContextContainer();
1149
+ for (const [key, value] of Object.entries(loaders)) {
1150
+ const signal = loaderState[key];
1151
+ const awaitedValue = await value;
1152
+ loadersObject[key] = awaitedValue;
1153
+ if (!signal) {
1154
+ loaderState[key] = createLoaderSignal(loadersObject, key, trackUrl, DEFAULT_LOADERS_SERIALIZATION_STRATEGY, container2);
1155
+ } else {
1156
+ signal.invalidate();
1157
+ }
1158
+ }
1014
1159
  }
1015
1160
  CLIENT_DATA_CACHE.clear();
1161
+ const win = window;
1016
1162
  if (!win._qRouterSPA) {
1017
1163
  win._qRouterSPA = true;
1018
1164
  history.scrollRestoration = "manual";
@@ -1121,33 +1267,64 @@ const QwikRouterProvider = component$((props) => {
1121
1267
  const scrollState2 = currentScrollState(scroller);
1122
1268
  saveScrollHistory(scrollState2);
1123
1269
  }
1124
- clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1125
- _waitUntilRendered(elm).then(() => {
1126
- const container = _getQContainerElement(elm);
1127
- container.setAttribute("q:route", routeName);
1270
+ const navigate = () => {
1271
+ clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1272
+ contentInternal.force();
1273
+ return _waitUntilRendered(elm);
1274
+ };
1275
+ const _waitNextPage = () => {
1276
+ if (isServer || props?.viewTransition === false) {
1277
+ return navigate();
1278
+ } else {
1279
+ const viewTransition = startViewTransition({
1280
+ update: navigate,
1281
+ types: [
1282
+ "qwik-navigation"
1283
+ ]
1284
+ });
1285
+ if (!viewTransition) {
1286
+ return Promise.resolve();
1287
+ }
1288
+ return viewTransition.ready;
1289
+ }
1290
+ };
1291
+ _waitNextPage().then(() => {
1292
+ const container2 = _getQContainerElement(elm);
1293
+ container2.setAttribute(Q_ROUTE, routeName);
1128
1294
  const scrollState2 = currentScrollState(scroller);
1129
1295
  saveScrollHistory(scrollState2);
1130
1296
  win._qRouterScrollEnabled = true;
1131
1297
  if (isBrowser) {
1132
1298
  callRestoreScrollOnDocument();
1133
1299
  }
1300
+ if (shouldForcePrevUrl) {
1301
+ forceStoreEffects(routeLocation, "prevUrl");
1302
+ }
1303
+ if (shouldForceUrl) {
1304
+ forceStoreEffects(routeLocation, "url");
1305
+ }
1306
+ if (shouldForceParams) {
1307
+ forceStoreEffects(routeLocation, "params");
1308
+ }
1134
1309
  routeLocation.isNavigating = false;
1135
1310
  navResolver.r?.();
1136
1311
  });
1137
1312
  }
1138
1313
  }
1139
1314
  }
1140
- const promise = run();
1141
1315
  if (isServer) {
1142
- return promise;
1316
+ return run();
1143
1317
  } else {
1144
- return;
1318
+ run();
1145
1319
  }
1146
1320
  });
1321
+ };
1322
+ const QwikRouterProvider = component$((props) => {
1323
+ useQwikRouter(props);
1147
1324
  return /* @__PURE__ */ jsx(Slot, {});
1148
1325
  });
1149
1326
  const QwikCityProvider = QwikRouterProvider;
1150
- const QwikRouterMockProvider = component$((props) => {
1327
+ const useQwikMockRouter = (props) => {
1151
1328
  const urlEnv = props.url ?? "http://localhost/";
1152
1329
  const url = new URL(urlEnv);
1153
1330
  const routeLocation = useStore({
@@ -1158,7 +1335,7 @@ const QwikRouterMockProvider = component$((props) => {
1158
1335
  }, {
1159
1336
  deep: false
1160
1337
  });
1161
- const loaderState = useSignal({});
1338
+ const loaderState = {};
1162
1339
  const routeInternal = useSignal({
1163
1340
  type: "initial",
1164
1341
  dest: url
@@ -1185,6 +1362,9 @@ const QwikRouterMockProvider = component$((props) => {
1185
1362
  useContextProvider(RouteStateContext, loaderState);
1186
1363
  useContextProvider(RouteActionContext, actionState);
1187
1364
  useContextProvider(RouteInternalContext, routeInternal);
1365
+ };
1366
+ const QwikRouterMockProvider = component$((props) => {
1367
+ useQwikMockRouter(props);
1188
1368
  return /* @__PURE__ */ jsx(Slot, {});
1189
1369
  });
1190
1370
  const QwikCityMockProvider = QwikRouterMockProvider;
@@ -1193,13 +1373,14 @@ const RouterOutlet = component$(() => {
1193
1373
  if (!serverData) {
1194
1374
  throw new Error("PrefetchServiceWorker component must be rendered on the server.");
1195
1375
  }
1196
- const { value } = useContext(ContentInternalContext);
1197
- if (value && value.length > 0) {
1198
- const contentsLen = value.length;
1376
+ const internalContext = useContext(ContentInternalContext);
1377
+ const contents = internalContext.value;
1378
+ if (contents && contents.length > 0) {
1379
+ const contentsLen = contents.length;
1199
1380
  let cmp = null;
1200
1381
  for (let i = contentsLen - 1; i >= 0; i--) {
1201
- if (value[i].default) {
1202
- cmp = jsx$1(value[i].default, {
1382
+ if (contents[i].default) {
1383
+ cmp = jsx$1(contents[i].default, {
1203
1384
  children: cmp
1204
1385
  });
1205
1386
  }
@@ -1403,24 +1584,25 @@ const globalActionQrl = (actionQrl, ...rest) => {
1403
1584
  const routeAction$ = /* @__PURE__ */ implicit$FirstArg(routeActionQrl);
1404
1585
  const globalAction$ = /* @__PURE__ */ implicit$FirstArg(globalActionQrl);
1405
1586
  const routeLoaderQrl = (loaderQrl, ...rest) => {
1406
- const { id, validators } = getValidators(rest, loaderQrl);
1587
+ const { id, validators, serializationStrategy } = getValidators(rest, loaderQrl);
1407
1588
  function loader() {
1408
- return useContext(RouteStateContext, (state) => {
1409
- if (!(id in state)) {
1410
- throw new Error(`routeLoader$ "${loaderQrl.getSymbol()}" was invoked in a route where it was not declared.
1589
+ const state = _resolveContextWithoutSequentialScope(RouteStateContext);
1590
+ if (!(id in state)) {
1591
+ throw new Error(`routeLoader$ "${loaderQrl.getSymbol()}" was invoked in a route where it was not declared.
1411
1592
  This is because the routeLoader$ was not exported in a 'layout.tsx' or 'index.tsx' file of the existing route.
1412
1593
  For more information check: https://qwik.dev/docs/route-loader/
1413
1594
 
1414
1595
  If your are managing reusable logic or a library it is essential that this function is re-exported from within 'layout.tsx' or 'index.tsx file of the existing route otherwise it will not run or throw exception.
1415
1596
  For more information check: https://qwik.dev/docs/re-exporting-loaders/`);
1416
- }
1417
- return _wrapStore(state, id);
1418
- });
1597
+ }
1598
+ untrack(() => state[id].value);
1599
+ return state[id];
1419
1600
  }
1420
1601
  loader.__brand = "server_loader";
1421
1602
  loader.__qrl = loaderQrl;
1422
1603
  loader.__validators = validators;
1423
1604
  loader.__id = id;
1605
+ loader.__serializationStrategy = serializationStrategy;
1424
1606
  Object.freeze(loader);
1425
1607
  return loader;
1426
1608
  };
@@ -1525,7 +1707,7 @@ const zodQrl = (qrl) => {
1525
1707
  }
1526
1708
  });
1527
1709
  const data = inputData ?? await ev.parseBody();
1528
- const result = await schema.safeParseAsync(data);
1710
+ const result = await withLocale(ev.locale(), () => schema.safeParseAsync(data));
1529
1711
  if (result.success) {
1530
1712
  return result;
1531
1713
  } else {
@@ -1610,7 +1792,7 @@ const serverQrl = (qrl, options) => {
1610
1792
  const res = await fetch(`${origin}?${QFN_KEY}=${qrlHash}${query}`, config);
1611
1793
  const contentType = res.headers.get("Content-Type");
1612
1794
  if (res.ok && contentType === "text/qwik-json-stream" && res.body) {
1613
- return async function* () {
1795
+ return (async function* () {
1614
1796
  try {
1615
1797
  for await (const result of deserializeStream(res.body, ctxElm ?? document.documentElement, abortSignal)) {
1616
1798
  yield result;
@@ -1620,7 +1802,7 @@ const serverQrl = (qrl, options) => {
1620
1802
  await res.body.cancel();
1621
1803
  }
1622
1804
  }
1623
- }();
1805
+ })();
1624
1806
  } else if (contentType === "application/qwik-json") {
1625
1807
  const str = await res.text();
1626
1808
  const [obj] = _deserialize(str, ctxElm ?? document.documentElement);
@@ -1649,6 +1831,7 @@ const serverQrl = (qrl, options) => {
1649
1831
  const server$ = /* @__PURE__ */ implicit$FirstArg(serverQrl);
1650
1832
  const getValidators = (rest, qrl) => {
1651
1833
  let id;
1834
+ let serializationStrategy = DEFAULT_LOADERS_SERIALIZATION_STRATEGY;
1652
1835
  const validators = [];
1653
1836
  if (rest.length === 1) {
1654
1837
  const options = rest[0];
@@ -1657,6 +1840,9 @@ const getValidators = (rest, qrl) => {
1657
1840
  validators.push(options);
1658
1841
  } else {
1659
1842
  id = options.id;
1843
+ if (options.serializationStrategy) {
1844
+ serializationStrategy = options.serializationStrategy;
1845
+ }
1660
1846
  if (options.validation) {
1661
1847
  validators.push(...options.validation);
1662
1848
  }
@@ -1677,7 +1863,8 @@ const getValidators = (rest, qrl) => {
1677
1863
  }
1678
1864
  return {
1679
1865
  validators: validators.reverse(),
1680
- id
1866
+ id,
1867
+ serializationStrategy
1681
1868
  };
1682
1869
  };
1683
1870
  const deserializeStream = async function* (stream, ctxElm, abortSignal) {
@@ -1704,7 +1891,8 @@ const deserializeStream = async function* (stream, ctxElm, abortSignal) {
1704
1891
  reader.releaseLock();
1705
1892
  }
1706
1893
  };
1707
- const ServiceWorkerRegister = (props) => jsx$1("script", {
1894
+ const ServiceWorkerRegister = (props) => /* @__PURE__ */ jsx("script", {
1895
+ type: "module",
1708
1896
  dangerouslySetInnerHTML: swRegister,
1709
1897
  nonce: props.nonce
1710
1898
  });
@@ -1828,7 +2016,52 @@ function omitProps(obj, keys) {
1828
2016
  }
1829
2017
  return omittedObj;
1830
2018
  }
2019
+ const createRenderer = (getOptions) => {
2020
+ return (opts) => {
2021
+ const { jsx: jsx2, options } = getOptions(opts);
2022
+ return renderToStream(jsx2, options);
2023
+ };
2024
+ };
2025
+ const DocumentHeadTags = component$((props) => {
2026
+ let head = useDocumentHead();
2027
+ if (props) {
2028
+ head = {
2029
+ ...head,
2030
+ ...props
2031
+ };
2032
+ }
2033
+ return /* @__PURE__ */ jsxs(Fragment, {
2034
+ children: [
2035
+ head.title && /* @__PURE__ */ jsx("title", {
2036
+ children: head.title
2037
+ }),
2038
+ head.meta.map((m) => /* @__PURE__ */ jsx("meta", {
2039
+ ...m
2040
+ })),
2041
+ head.links.map((l) => /* @__PURE__ */ jsx("link", {
2042
+ ...l
2043
+ })),
2044
+ head.styles.map((s) => {
2045
+ const props2 = s.props || s;
2046
+ return /* @__PURE__ */ createElement("style", {
2047
+ ...props2,
2048
+ dangerouslySetInnerHTML: s.style || props2.dangerouslySetInnerHTML,
2049
+ key: s.key
2050
+ });
2051
+ }),
2052
+ head.scripts.map((s) => {
2053
+ const props2 = s.props || s;
2054
+ return /* @__PURE__ */ createElement("script", {
2055
+ ...props2,
2056
+ dangerouslySetInnerHTML: s.script || props2.dangerouslySetInnerHTML,
2057
+ key: s.key
2058
+ });
2059
+ })
2060
+ ]
2061
+ });
2062
+ });
1831
2063
  export {
2064
+ DocumentHeadTags,
1832
2065
  ErrorBoundary,
1833
2066
  Form,
1834
2067
  Link,
@@ -1840,6 +2073,7 @@ export {
1840
2073
  QwikRouterProvider,
1841
2074
  RouterOutlet,
1842
2075
  ServiceWorkerRegister,
2076
+ createRenderer,
1843
2077
  globalAction$,
1844
2078
  globalActionQrl,
1845
2079
  omitProps,
@@ -1856,6 +2090,7 @@ export {
1856
2090
  useNavigate,
1857
2091
  usePreventNavigate$,
1858
2092
  usePreventNavigateQrl,
2093
+ useQwikRouter,
1859
2094
  valibot$,
1860
2095
  valibotQrl,
1861
2096
  validator$,