@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
@@ -2,10 +2,12 @@
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");
8
9
  const swRegister = require("@qwik-router-sw-register");
10
+ const server = require("@qwik.dev/core/server");
9
11
  function _interopNamespaceDefault(e) {
10
12
  const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
11
13
  if (e) {
@@ -37,132 +39,38 @@ const ErrorBoundary = core.component$((props) => {
37
39
  });
38
40
  const MODULE_CACHE = /* @__PURE__ */ new WeakMap();
39
41
  const CLIENT_DATA_CACHE = /* @__PURE__ */ new Map();
40
- const PREFETCHED_NAVIGATE_PATHS = /* @__PURE__ */ new Set();
41
42
  const QACTION_KEY = "qaction";
43
+ const QLOADER_KEY = "qloaders";
42
44
  const QFN_KEY = "qfunc";
43
45
  const QDATA_KEY = "qdata";
44
- const toPath = (url) => url.pathname + url.search + url.hash;
45
- const toUrl = (url, baseUrl) => new URL(url, baseUrl.href);
46
- const isSameOrigin = (a, b) => a.origin === b.origin;
47
- const withSlash = (path) => path.endsWith("/") ? path : path + "/";
48
- const isSamePathname = ({ pathname: a }, { pathname: b }) => {
49
- const lDiff = Math.abs(a.length - b.length);
50
- return lDiff === 0 ? a === b : lDiff === 1 && withSlash(a) === withSlash(b);
51
- };
52
- const isSameSearchQuery = (a, b) => a.search === b.search;
53
- const isSamePath = (a, b) => isSameSearchQuery(a, b) && isSamePathname(a, b);
54
- const getClientDataPath = (pathname, pageSearch, action) => {
55
- let search = pageSearch ?? "";
56
- if (action) {
57
- search += (search ? "&" : "?") + QACTION_KEY + "=" + encodeURIComponent(action.id);
58
- }
59
- return pathname + (pathname.endsWith("/") ? "" : "/") + "q-data.json" + search;
60
- };
61
- const getClientNavPath = (props, baseUrl) => {
62
- const href = props.href;
63
- if (typeof href === "string" && typeof props.target !== "string" && !props.reload) {
64
- try {
65
- const linkUrl = toUrl(href.trim(), baseUrl.url);
66
- const currentUrl = toUrl("", baseUrl.url);
67
- if (isSameOrigin(linkUrl, currentUrl)) {
68
- return toPath(linkUrl);
69
- }
70
- } catch (e) {
71
- console.error(e);
72
- }
73
- } else if (props.reload) {
74
- return toPath(toUrl("", baseUrl.url));
75
- }
76
- return null;
77
- };
78
- const shouldPrefetchData = (clientNavPath, currentLoc) => {
79
- if (clientNavPath) {
80
- const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
81
- const currentUrl = toUrl("", currentLoc.url);
82
- return !isSamePath(prefetchUrl, currentUrl);
83
- }
84
- return false;
85
- };
86
- const shouldPrefetchSymbols = (clientNavPath, currentLoc) => {
87
- if (clientNavPath) {
88
- const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
89
- const currentUrl = toUrl("", currentLoc.url);
90
- return !isSamePathname(prefetchUrl, currentUrl);
91
- }
92
- return false;
93
- };
94
- const isPromise = (value) => {
95
- return value && typeof value.then === "function";
96
- };
97
- const deepFreeze = (obj) => {
98
- if (obj == null) {
99
- return obj;
100
- }
101
- Object.getOwnPropertyNames(obj).forEach((prop) => {
102
- const value = obj[prop];
103
- if (value && typeof value === "object" && !Object.isFrozen(value)) {
104
- deepFreeze(value);
105
- }
106
- });
107
- return Object.freeze(obj);
108
- };
109
- const clientNavigate = (win, navType, fromURL, toURL, replaceState = false) => {
110
- if (navType !== "popstate") {
111
- const samePath = isSamePath(fromURL, toURL);
112
- const sameHash = fromURL.hash === toURL.hash;
113
- if (!samePath || !sameHash) {
114
- const newState = {
115
- _qRouterScroll: newScrollState()
116
- };
117
- if (replaceState) {
118
- win.history.replaceState(newState, "", toPath(toURL));
119
- } else {
120
- win.history.pushState(newState, "", toPath(toURL));
121
- }
122
- }
123
- }
124
- };
125
- const newScrollState = () => {
126
- return {
127
- x: 0,
128
- y: 0,
129
- w: 0,
130
- h: 0
131
- };
132
- };
133
- const prefetchSymbols = (path) => {
134
- if (core.isBrowser) {
135
- path = path.endsWith("/") ? path : path + "/";
136
- if (!PREFETCHED_NAVIGATE_PATHS.has(path)) {
137
- PREFETCHED_NAVIGATE_PATHS.add(path);
138
- document.dispatchEvent(new CustomEvent("qprefetch", {
139
- detail: {
140
- links: [
141
- path
142
- ]
143
- }
144
- }));
145
- }
146
- }
147
- };
148
- const loadClientData = async (url, element, opts) => {
46
+ const Q_ROUTE = "q:route";
47
+ const DEFAULT_LOADERS_SERIALIZATION_STRATEGY = globalThis.__DEFAULT_LOADERS_SERIALIZATION_STRATEGY__ || "never";
48
+ const MAX_Q_DATA_RETRY_COUNT = 3;
49
+ const loadClientData = async (url, element, opts, retryCount = 0) => {
149
50
  const pagePathname = url.pathname;
150
51
  const pageSearch = url.search;
151
- const clientDataPath = getClientDataPath(pagePathname, pageSearch, opts?.action);
52
+ const clientDataPath = getClientDataPath(pagePathname, pageSearch, {
53
+ actionId: opts?.action?.id,
54
+ loaderIds: opts?.loaderIds
55
+ });
152
56
  let qData;
153
57
  if (!opts?.action) {
154
58
  qData = CLIENT_DATA_CACHE.get(clientDataPath);
155
59
  }
156
- if (opts?.prefetchSymbols !== false) {
157
- prefetchSymbols(pagePathname);
60
+ if (opts?.preloadRouteBundles !== false) {
61
+ preloadRouteBundles(pagePathname, 0.8);
158
62
  }
159
63
  let resolveFn;
160
64
  if (!qData) {
161
- const fetchOptions = getFetchOptions(opts?.action);
65
+ const fetchOptions = getFetchOptions(opts?.action, opts?.clearCache);
162
66
  if (opts?.action) {
163
67
  opts.action.data = void 0;
164
68
  }
165
69
  qData = fetch(clientDataPath, fetchOptions).then((rsp) => {
70
+ if (rsp.status === 404 && opts?.loaderIds && retryCount < MAX_Q_DATA_RETRY_COUNT) {
71
+ opts.loaderIds = void 0;
72
+ return loadClientData(url, element, opts, retryCount + 1);
73
+ }
166
74
  if (rsp.redirected) {
167
75
  const redirectedURL = new URL(rsp.url);
168
76
  const isQData = redirectedURL.pathname.endsWith("/q-data.json");
@@ -214,16 +122,19 @@ const loadClientData = async (url, element, opts) => {
214
122
  return v;
215
123
  });
216
124
  };
217
- const getFetchOptions = (action) => {
125
+ const getFetchOptions = (action, noCache) => {
218
126
  const actionData = action?.data;
219
127
  if (!actionData) {
220
- return {
221
- cache: "no-cache",
222
- headers: {
223
- "Cache-Control": "no-cache",
224
- Pragma: "no-cache"
225
- }
226
- };
128
+ if (noCache) {
129
+ return {
130
+ cache: "no-cache",
131
+ headers: {
132
+ "Cache-Control": "no-cache",
133
+ Pragma: "no-cache"
134
+ }
135
+ };
136
+ }
137
+ return void 0;
227
138
  }
228
139
  if (actionData instanceof FormData) {
229
140
  return {
@@ -235,11 +146,108 @@ const getFetchOptions = (action) => {
235
146
  method: "POST",
236
147
  body: JSON.stringify(actionData),
237
148
  headers: {
238
- "Content-Type": "application/json, charset=UTF-8"
149
+ "Content-Type": "application/json; charset=UTF-8"
239
150
  }
240
151
  };
241
152
  }
242
153
  };
154
+ const toPath = (url) => url.pathname + url.search + url.hash;
155
+ const toUrl = (url, baseUrl) => new URL(url, baseUrl.href);
156
+ const isSameOrigin = (a, b) => a.origin === b.origin;
157
+ const withSlash = (path) => path.endsWith("/") ? path : path + "/";
158
+ const isSamePathname = ({ pathname: a }, { pathname: b }) => {
159
+ const lDiff = Math.abs(a.length - b.length);
160
+ return lDiff === 0 ? a === b : lDiff === 1 && withSlash(a) === withSlash(b);
161
+ };
162
+ const isSameSearchQuery = (a, b) => a.search === b.search;
163
+ const isSamePath = (a, b) => isSameSearchQuery(a, b) && isSamePathname(a, b);
164
+ const getClientDataPath = (pathname, pageSearch, options) => {
165
+ let search = pageSearch ?? "";
166
+ if (options?.actionId) {
167
+ search += (search ? "&" : "?") + QACTION_KEY + "=" + encodeURIComponent(options.actionId);
168
+ }
169
+ if (options?.loaderIds) {
170
+ for (const loaderId of options.loaderIds) {
171
+ search += (search ? "&" : "?") + QLOADER_KEY + "=" + encodeURIComponent(loaderId);
172
+ }
173
+ }
174
+ return pathname + (pathname.endsWith("/") ? "" : "/") + "q-data.json" + search;
175
+ };
176
+ const getClientNavPath = (props, baseUrl) => {
177
+ const href = props.href;
178
+ if (typeof href === "string" && typeof props.target !== "string" && !props.reload) {
179
+ try {
180
+ const linkUrl = toUrl(href.trim(), baseUrl.url);
181
+ const currentUrl = toUrl("", baseUrl.url);
182
+ if (isSameOrigin(linkUrl, currentUrl)) {
183
+ return toPath(linkUrl);
184
+ }
185
+ } catch (e) {
186
+ console.error(e);
187
+ }
188
+ } else if (props.reload) {
189
+ return toPath(toUrl("", baseUrl.url));
190
+ }
191
+ return null;
192
+ };
193
+ const shouldPreload = (clientNavPath, currentLoc) => {
194
+ if (clientNavPath) {
195
+ const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
196
+ const currentUrl = toUrl("", currentLoc.url);
197
+ return !isSamePathname(prefetchUrl, currentUrl);
198
+ }
199
+ return false;
200
+ };
201
+ const isPromise = (value) => {
202
+ return value && typeof value.then === "function";
203
+ };
204
+ const createLoaderSignal = (loadersObject, loaderId, url, serializationStrategy, container) => {
205
+ return core.createAsyncComputed$(async () => {
206
+ if (core.isBrowser && loadersObject[loaderId] === internal._UNINITIALIZED) {
207
+ const data = await loadClientData(url, void 0, {
208
+ loaderIds: [
209
+ loaderId
210
+ ]
211
+ });
212
+ loadersObject[loaderId] = data?.loaders[loaderId] ?? internal._UNINITIALIZED;
213
+ }
214
+ return loadersObject[loaderId];
215
+ }, {
216
+ container,
217
+ serializationStrategy
218
+ });
219
+ };
220
+ const clientNavigate = (win, navType, fromURL, toURL, replaceState = false) => {
221
+ if (navType !== "popstate") {
222
+ const samePath = isSamePath(fromURL, toURL);
223
+ const sameHash = fromURL.hash === toURL.hash;
224
+ if (!samePath || !sameHash) {
225
+ const newState = {
226
+ _qRouterScroll: newScrollState()
227
+ };
228
+ if (replaceState) {
229
+ win.history.replaceState(newState, "", toPath(toURL));
230
+ } else {
231
+ win.history.pushState(newState, "", toPath(toURL));
232
+ }
233
+ }
234
+ }
235
+ };
236
+ const newScrollState = () => {
237
+ return {
238
+ x: 0,
239
+ y: 0,
240
+ w: 0,
241
+ h: 0
242
+ };
243
+ };
244
+ const preloadRouteBundles = (path, probability = 0.8) => {
245
+ if (core.isBrowser) {
246
+ path = path.endsWith("/") ? path : path + "/";
247
+ path = path.length > 1 && path.startsWith("/") ? path.slice(1) : path;
248
+ preloader.p(path, probability);
249
+ }
250
+ };
243
251
  const RouteStateContext = /* @__PURE__ */ core.createContextId("qc-s");
244
252
  const ContentContext = /* @__PURE__ */ core.createContextId("qc-c");
245
253
  const ContentInternalContext = /* @__PURE__ */ core.createContextId("qc-ic");
@@ -267,54 +275,77 @@ const Link = core.component$((props) => {
267
275
  const nav = useNavigate();
268
276
  const loc = useLocation();
269
277
  const originalHref = props.href;
278
+ const anchorRef = core.useSignal();
270
279
  const { onClick$, prefetch: prefetchProp, reload, replaceState, scroll, ...linkProps } = /* @__PURE__ */ (() => props)();
271
280
  const clientNavPath = core.untrack(() => getClientNavPath({
272
281
  ...linkProps,
273
282
  reload
274
283
  }, loc));
275
284
  linkProps.href = clientNavPath || originalHref;
276
- const prefetchData = core.untrack(() => !!clientNavPath && prefetchProp !== false && prefetchProp !== "js" && shouldPrefetchData(clientNavPath, loc) || void 0);
277
- const prefetch = core.untrack(() => prefetchData || !!clientNavPath && prefetchProp !== false && shouldPrefetchSymbols(clientNavPath, loc));
285
+ const prefetchData = core.untrack(() => !!clientNavPath && prefetchProp !== false && prefetchProp !== "js" || void 0);
286
+ const prefetch = core.untrack(() => prefetchData || !!clientNavPath && prefetchProp !== false && shouldPreload(clientNavPath, loc));
278
287
  const handlePrefetch = prefetch ? core.$((_, elm) => {
279
288
  if (navigator.connection?.saveData) {
280
289
  return;
281
290
  }
282
291
  if (elm && elm.href) {
283
292
  const url = new URL(elm.href);
284
- prefetchSymbols(url.pathname);
293
+ preloadRouteBundles(url.pathname);
285
294
  if (elm.hasAttribute("data-prefetch")) {
286
295
  loadClientData(url, elm, {
287
- prefetchSymbols: false,
296
+ preloadRouteBundles: false,
288
297
  isPrefetch: true
289
298
  });
290
299
  }
291
300
  }
292
301
  }) : void 0;
293
- const preventDefault = clientNavPath ? core.sync$((event, target) => {
302
+ const preventDefault = clientNavPath ? core.sync$((event) => {
294
303
  if (!(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) {
295
304
  event.preventDefault();
296
305
  }
297
306
  }) : void 0;
298
- const handleClick = clientNavPath ? core.$(async (event, elm) => {
307
+ const handleClientSideNavigation = clientNavPath ? core.$((event, elm) => {
299
308
  if (event.defaultPrevented) {
300
309
  if (elm.href) {
301
310
  elm.setAttribute("aria-pressed", "true");
302
- await nav(elm.href, {
311
+ nav(elm.href, {
303
312
  forceReload: reload,
304
313
  replaceState,
305
314
  scroll
315
+ }).then(() => {
316
+ elm.removeAttribute("aria-pressed");
306
317
  });
307
- elm.removeAttribute("aria-pressed");
308
318
  }
309
319
  }
310
320
  }) : void 0;
321
+ const handlePreload = core.$((_, elm) => {
322
+ const url = new URL(elm.href);
323
+ preloadRouteBundles(url.pathname, 1);
324
+ });
325
+ core.useVisibleTask$(({ track }) => {
326
+ track(() => loc.url.pathname);
327
+ const handler = linkProps.onQVisible$;
328
+ if (handler) {
329
+ const event = new CustomEvent("qvisible");
330
+ if (Array.isArray(handler)) {
331
+ handler.flat(10).forEach((handler2) => handler2?.(event, anchorRef.value));
332
+ } else {
333
+ handler?.(event, anchorRef.value);
334
+ }
335
+ }
336
+ if (!core.isDev && anchorRef.value) {
337
+ handlePrefetch?.(void 0, anchorRef.value);
338
+ }
339
+ });
311
340
  return /* @__PURE__ */ jsxRuntime.jsx("a", {
341
+ ref: anchorRef,
312
342
  "q:link": !!clientNavPath,
313
343
  ...linkProps,
314
344
  onClick$: [
315
345
  preventDefault,
346
+ handlePreload,
316
347
  onClick$,
317
- handleClick
348
+ handleClientSideNavigation
318
349
  ],
319
350
  "data-prefetch": prefetchData,
320
351
  onMouseOver$: [
@@ -325,16 +356,13 @@ const Link = core.component$((props) => {
325
356
  linkProps.onFocus$,
326
357
  handlePrefetch
327
358
  ],
328
- // Don't prefetch on visible in dev mode
329
- onQVisible$: [
330
- linkProps.onQVisible$,
331
- !core.isDev ? handlePrefetch : void 0
332
- ],
359
+ // We need to prevent the onQVisible$ from being called twice since it is handled in the visible task
360
+ onQVisible$: [],
333
361
  children: /* @__PURE__ */ jsxRuntime.jsx(core.Slot, {})
334
362
  });
335
363
  });
336
- const resolveHead = (endpoint, routeLocation, contentModules, locale) => {
337
- const head = createDocumentHead();
364
+ const resolveHead = (endpoint, routeLocation, contentModules, locale, defaults) => {
365
+ const head = createDocumentHead(defaults);
338
366
  const getData = (loaderOrAction) => {
339
367
  const id = loaderOrAction.__id;
340
368
  if (loaderOrAction.__brand === "server_loader") {
@@ -390,13 +418,23 @@ const mergeArray = (existingArr, newArr) => {
390
418
  }
391
419
  }
392
420
  };
393
- const createDocumentHead = () => ({
394
- title: "",
395
- meta: [],
396
- links: [],
397
- styles: [],
398
- scripts: [],
399
- frontmatter: {}
421
+ const createDocumentHead = (defaults) => ({
422
+ title: defaults?.title || "",
423
+ meta: [
424
+ ...defaults?.meta || []
425
+ ],
426
+ links: [
427
+ ...defaults?.links || []
428
+ ],
429
+ styles: [
430
+ ...defaults?.styles || []
431
+ ],
432
+ scripts: [
433
+ ...defaults?.scripts || []
434
+ ],
435
+ frontmatter: {
436
+ ...defaults?.frontmatter
437
+ }
400
438
  });
401
439
  function matchRoute(route, path) {
402
440
  const routeIdx = startIdxSkipSlash(route);
@@ -406,6 +444,9 @@ function matchRoute(route, path) {
406
444
  return matchRoutePart(route, routeIdx, routeLength, path, pathIdx, pathLength);
407
445
  }
408
446
  function matchRoutePart(route, routeIdx, routeLength, path, pathIdx, pathLength) {
447
+ if (path.startsWith("/build/")) {
448
+ return null;
449
+ }
409
450
  let params = null;
410
451
  while (routeIdx < routeLength) {
411
452
  const routeCh = route.charCodeAt(routeIdx++);
@@ -507,18 +548,42 @@ function lastIndexOf(text, start, match, searchIdx, notFoundIdx) {
507
548
  }
508
549
  return idx > start ? idx : notFoundIdx;
509
550
  }
551
+ var RouteDataProp = /* @__PURE__ */ (function(RouteDataProp2) {
552
+ RouteDataProp2[RouteDataProp2["RouteName"] = 0] = "RouteName";
553
+ RouteDataProp2[RouteDataProp2["Loaders"] = 1] = "Loaders";
554
+ RouteDataProp2[RouteDataProp2["OriginalPathname"] = 2] = "OriginalPathname";
555
+ RouteDataProp2[RouteDataProp2["RouteBundleNames"] = 3] = "RouteBundleNames";
556
+ return RouteDataProp2;
557
+ })({});
558
+ var MenuDataProp = /* @__PURE__ */ (function(MenuDataProp2) {
559
+ MenuDataProp2[MenuDataProp2["Pathname"] = 0] = "Pathname";
560
+ MenuDataProp2[MenuDataProp2["MenuLoader"] = 1] = "MenuLoader";
561
+ return MenuDataProp2;
562
+ })({});
563
+ const deepFreeze = (obj) => {
564
+ if (obj == null) {
565
+ return obj;
566
+ }
567
+ Object.getOwnPropertyNames(obj).forEach((prop) => {
568
+ const value = obj[prop];
569
+ if (value && typeof value === "object" && !Object.isFrozen(value)) {
570
+ deepFreeze(value);
571
+ }
572
+ });
573
+ return Object.freeze(obj);
574
+ };
510
575
  const loadRoute = async (routes, menus, cacheModules, pathname) => {
511
576
  if (!Array.isArray(routes)) {
512
577
  return null;
513
578
  }
514
579
  for (const routeData of routes) {
515
- const routeName = routeData[0];
580
+ const routeName = routeData[RouteDataProp.RouteName];
516
581
  const params = matchRoute(routeName, pathname);
517
582
  if (!params) {
518
583
  continue;
519
584
  }
520
- const loaders = routeData[1];
521
- const routeBundleNames = routeData[3];
585
+ const loaders = routeData[RouteDataProp.Loaders];
586
+ const routeBundleNames = routeData[RouteDataProp.RouteBundleNames];
522
587
  const modules = new Array(loaders.length);
523
588
  const pendingLoads = [];
524
589
  loaders.forEach((moduleLoader, i) => {
@@ -563,9 +628,9 @@ const loadModule = (moduleLoader, pendingLoads, moduleSetter, cacheModules) => {
563
628
  const getMenuLoader = (menus, pathname) => {
564
629
  if (menus) {
565
630
  pathname = pathname.endsWith("/") ? pathname : pathname + "/";
566
- const menu = menus.find((m) => m[0] === pathname || pathname.startsWith(m[0] + (pathname.endsWith("/") ? "" : "/")));
631
+ const menu = menus.find((m) => m[MenuDataProp.Pathname] === pathname || pathname.startsWith(m[MenuDataProp.Pathname] + (pathname.endsWith("/") ? "" : "/")));
567
632
  if (menu) {
568
- return menu[1];
633
+ return menu[MenuDataProp.MenuLoader];
569
634
  }
570
635
  }
571
636
  };
@@ -757,8 +822,8 @@ const spaInit = core.event$((_, el) => {
757
822
  };
758
823
  win[scrollEnabled] = true;
759
824
  setTimeout(() => {
760
- addEventListener("popstate", win[initPopstate]);
761
- addEventListener("scroll", win[initScroll], {
825
+ win.addEventListener("popstate", win[initPopstate]);
826
+ win.addEventListener("scroll", win[initScroll], {
762
827
  passive: true
763
828
  });
764
829
  document.body.addEventListener("click", win[initAnchors]);
@@ -770,14 +835,45 @@ const spaInit = core.event$((_, el) => {
770
835
  }, 0);
771
836
  }
772
837
  });
838
+ const startViewTransition = (params) => {
839
+ if (!params.update) {
840
+ return;
841
+ }
842
+ if ("startViewTransition" in document) {
843
+ let transition;
844
+ try {
845
+ transition = document.startViewTransition(params);
846
+ } catch {
847
+ transition = document.startViewTransition(params.update);
848
+ }
849
+ const event = new CustomEvent("qviewtransition", {
850
+ detail: transition
851
+ });
852
+ document.dispatchEvent(event);
853
+ return transition;
854
+ } else {
855
+ params.update?.();
856
+ }
857
+ };
773
858
  const QWIK_CITY_SCROLLER = "_qCityScroller";
774
859
  const QWIK_ROUTER_SCROLLER = "_qRouterScroller";
775
860
  const preventNav = {};
776
861
  const internalState = {
777
862
  navCount: 0
778
863
  };
779
- const QwikRouterProvider = core.component$((props) => {
780
- core.useStyles$(`:root{view-transition-name:none}`);
864
+ const useQwikRouter = (props) => {
865
+ core.useStyles$(`
866
+ @layer qwik {
867
+ @supports selector(html:active-view-transition-type(type)) {
868
+ html:active-view-transition-type(qwik-navigation) {
869
+ :root{view-transition-name:none}
870
+ }
871
+ }
872
+ @supports not selector(html:active-view-transition-type(type)) {
873
+ :root{view-transition-name:none}
874
+ }
875
+ }
876
+ `);
781
877
  const env = useQwikRouterEnv();
782
878
  if (!env?.params) {
783
879
  throw new Error(`Missing Qwik Router Env Data for help visit https://github.com/QwikDev/qwik/issues/6237`);
@@ -786,19 +882,40 @@ const QwikRouterProvider = core.component$((props) => {
786
882
  if (!urlEnv) {
787
883
  throw new Error(`Missing Qwik URL Env Data`);
788
884
  }
885
+ const serverHead = core.useServerData("documentHead");
886
+ if (core.isServer) {
887
+ if (env.ev.originalUrl.pathname !== env.ev.url.pathname && !__EXPERIMENTAL__.enableRequestRewrite) {
888
+ 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.`);
889
+ }
890
+ }
789
891
  const url = new URL(urlEnv);
790
- const routeLocation = core.useStore({
892
+ const routeLocationTarget = {
791
893
  url,
792
894
  params: env.params,
793
895
  isNavigating: false,
794
896
  prevUrl: void 0
795
- }, {
897
+ };
898
+ const routeLocation = core.useStore(routeLocationTarget, {
796
899
  deep: false
797
900
  });
798
901
  const navResolver = {};
799
- const loaderState = internal._weakSerialize(core.useStore(env.response.loaders, {
800
- deep: false
801
- }));
902
+ const container = internal._getContextContainer();
903
+ const getSerializationStrategy = (loaderId) => {
904
+ return env.response.loadersSerializationStrategy.get(loaderId) || DEFAULT_LOADERS_SERIALIZATION_STRATEGY;
905
+ };
906
+ const loadersObject = {};
907
+ const loaderState = {};
908
+ for (const [key, value] of Object.entries(env.response.loaders)) {
909
+ loadersObject[key] = value;
910
+ loaderState[key] = createLoaderSignal(loadersObject, key, url, getSerializationStrategy(key), container);
911
+ }
912
+ loadersObject[internal.SerializerSymbol] = (obj) => {
913
+ const loadersSerializationObject = {};
914
+ for (const [k, v] of Object.entries(obj)) {
915
+ loadersSerializationObject[k] = getSerializationStrategy(k) === "always" ? v : internal._UNINITIALIZED;
916
+ }
917
+ return loadersSerializationObject;
918
+ };
802
919
  const routeInternal = core.useSignal({
803
920
  type: "initial",
804
921
  dest: url,
@@ -806,7 +923,7 @@ const QwikRouterProvider = core.component$((props) => {
806
923
  replaceState: false,
807
924
  scroll: true
808
925
  });
809
- const documentHead = core.useStore(createDocumentHead);
926
+ const documentHead = core.useStore(() => createDocumentHead(serverHead));
810
927
  const content = core.useStore({
811
928
  headings: void 0,
812
929
  menu: void 0
@@ -891,7 +1008,7 @@ const QwikRouterProvider = core.component$((props) => {
891
1008
  let scroller = document.getElementById(QWIK_ROUTER_SCROLLER);
892
1009
  if (!scroller) {
893
1010
  scroller = document.getElementById(QWIK_CITY_SCROLLER);
894
- if (scroller) {
1011
+ if (scroller && core.isDev) {
895
1012
  console.warn(`Please update your scroller ID to "${QWIK_ROUTER_SCROLLER}" as "${QWIK_CITY_SCROLLER}" is deprecated and will be removed in V3`);
896
1013
  }
897
1014
  }
@@ -952,10 +1069,10 @@ const QwikRouterProvider = core.component$((props) => {
952
1069
  } else {
953
1070
  trackUrl = new URL(navigation.dest, location);
954
1071
  if (trackUrl.pathname.endsWith("/")) {
955
- if (!qwikRouterConfig__namespace.trailingSlash) {
1072
+ if (globalThis.__NO_TRAILING_SLASH__) {
956
1073
  trackUrl.pathname = trackUrl.pathname.slice(0, -1);
957
1074
  }
958
- } else if (qwikRouterConfig__namespace.trailingSlash) {
1075
+ } else if (!globalThis.__NO_TRAILING_SLASH__) {
959
1076
  trackUrl.pathname += "/";
960
1077
  }
961
1078
  let loadRoutePromise = loadRoute(qwikRouterConfig__namespace.routes, qwikRouterConfig__namespace.menus, qwikRouterConfig__namespace.cacheModules, trackUrl.pathname);
@@ -974,12 +1091,21 @@ const QwikRouterProvider = core.component$((props) => {
974
1091
  const newHref = pageData.href;
975
1092
  const newURL = new URL(newHref, trackUrl);
976
1093
  if (!isSamePath(newURL, trackUrl)) {
977
- trackUrl = newURL;
978
- loadRoutePromise = loadRoute(qwikRouterConfig__namespace.routes, qwikRouterConfig__namespace.menus, qwikRouterConfig__namespace.cacheModules, trackUrl.pathname);
1094
+ if (!pageData.isRewrite) {
1095
+ trackUrl = newURL;
1096
+ }
1097
+ loadRoutePromise = loadRoute(
1098
+ qwikRouterConfig__namespace.routes,
1099
+ qwikRouterConfig__namespace.menus,
1100
+ qwikRouterConfig__namespace.cacheModules,
1101
+ newURL.pathname
1102
+ // Load the actual required path.
1103
+ );
979
1104
  }
980
1105
  try {
981
1106
  loadedRoute = await loadRoutePromise;
982
1107
  } catch (e) {
1108
+ console.error(e);
983
1109
  window.location.href = newHref;
984
1110
  return;
985
1111
  }
@@ -988,25 +1114,38 @@ const QwikRouterProvider = core.component$((props) => {
988
1114
  const [routeName, params, mods, menu] = loadedRoute;
989
1115
  const contentModules = mods;
990
1116
  const pageModule = contentModules[contentModules.length - 1];
991
- const isRedirect = navType === "form" && !isSamePath(trackUrl, prevUrl);
992
- if (navigation.dest.search && !isRedirect) {
1117
+ if (navigation.dest.search && !!isSamePath(trackUrl, prevUrl)) {
993
1118
  trackUrl.search = navigation.dest.search;
994
1119
  }
1120
+ let shouldForcePrevUrl = false;
1121
+ let shouldForceUrl = false;
1122
+ let shouldForceParams = false;
995
1123
  if (!isSamePath(trackUrl, prevUrl)) {
996
- routeLocation.prevUrl = prevUrl;
1124
+ if (internal._hasStoreEffects(routeLocation, "prevUrl")) {
1125
+ shouldForcePrevUrl = true;
1126
+ }
1127
+ routeLocationTarget.prevUrl = prevUrl;
1128
+ }
1129
+ if (routeLocationTarget.url !== trackUrl) {
1130
+ if (internal._hasStoreEffects(routeLocation, "url")) {
1131
+ shouldForceUrl = true;
1132
+ }
1133
+ routeLocationTarget.url = trackUrl;
1134
+ }
1135
+ if (routeLocationTarget.params !== params) {
1136
+ if (internal._hasStoreEffects(routeLocation, "params")) {
1137
+ shouldForceParams = true;
1138
+ }
1139
+ routeLocationTarget.params = params;
997
1140
  }
998
- routeLocation.url = trackUrl;
999
- routeLocation.params = {
1000
- ...params
1001
- };
1002
1141
  routeInternal.untrackedValue = {
1003
1142
  type: navType,
1004
1143
  dest: trackUrl
1005
1144
  };
1006
- const resolvedHead = resolveHead(clientPageData, routeLocation, contentModules, locale);
1145
+ const resolvedHead = resolveHead(clientPageData, routeLocation, contentModules, locale, serverHead);
1007
1146
  content.headings = pageModule.headings;
1008
1147
  content.menu = menu;
1009
- contentInternal.value = core.noSerialize(contentModules);
1148
+ contentInternal.untrackedValue = core.noSerialize(contentModules);
1010
1149
  documentHead.links = resolvedHead.links;
1011
1150
  documentHead.meta = resolvedHead.meta;
1012
1151
  documentHead.styles = resolvedHead.styles;
@@ -1014,23 +1153,30 @@ const QwikRouterProvider = core.component$((props) => {
1014
1153
  documentHead.title = resolvedHead.title;
1015
1154
  documentHead.frontmatter = resolvedHead.frontmatter;
1016
1155
  if (core.isBrowser) {
1017
- if (props.viewTransition !== false) {
1018
- document.__q_view_transition__ = true;
1019
- }
1020
1156
  let scrollState;
1021
1157
  if (navType === "popstate") {
1022
1158
  scrollState = getScrollHistory();
1023
1159
  }
1024
1160
  const scroller = document.getElementById(QWIK_ROUTER_SCROLLER) ?? document.documentElement;
1025
- if (navigation.scroll && (!navigation.forceReload || !isSamePath(trackUrl, prevUrl)) && (navType === "link" || navType === "popstate") || isRedirect) {
1161
+ if (navigation.scroll && (!navigation.forceReload || !isSamePath(trackUrl, prevUrl)) && (navType === "link" || navType === "popstate") || navType === "form" && !isSamePath(trackUrl, prevUrl)) {
1026
1162
  document.__q_scroll_restore__ = () => restoreScroll(navType, trackUrl, prevUrl, scroller, scrollState);
1027
1163
  }
1028
1164
  const loaders = clientPageData?.loaders;
1029
- const win = window;
1030
1165
  if (loaders) {
1031
- Object.assign(loaderState, loaders);
1166
+ const container2 = internal._getContextContainer();
1167
+ for (const [key, value] of Object.entries(loaders)) {
1168
+ const signal = loaderState[key];
1169
+ const awaitedValue = await value;
1170
+ loadersObject[key] = awaitedValue;
1171
+ if (!signal) {
1172
+ loaderState[key] = createLoaderSignal(loadersObject, key, trackUrl, DEFAULT_LOADERS_SERIALIZATION_STRATEGY, container2);
1173
+ } else {
1174
+ signal.invalidate();
1175
+ }
1176
+ }
1032
1177
  }
1033
1178
  CLIENT_DATA_CACHE.clear();
1179
+ const win = window;
1034
1180
  if (!win._qRouterSPA) {
1035
1181
  win._qRouterSPA = true;
1036
1182
  history.scrollRestoration = "manual";
@@ -1139,33 +1285,64 @@ const QwikRouterProvider = core.component$((props) => {
1139
1285
  const scrollState2 = currentScrollState(scroller);
1140
1286
  saveScrollHistory(scrollState2);
1141
1287
  }
1142
- clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1143
- internal._waitUntilRendered(elm).then(() => {
1144
- const container = internal._getQContainerElement(elm);
1145
- container.setAttribute("q:route", routeName);
1288
+ const navigate = () => {
1289
+ clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1290
+ contentInternal.force();
1291
+ return internal._waitUntilRendered(elm);
1292
+ };
1293
+ const _waitNextPage = () => {
1294
+ if (core.isServer || props?.viewTransition === false) {
1295
+ return navigate();
1296
+ } else {
1297
+ const viewTransition = startViewTransition({
1298
+ update: navigate,
1299
+ types: [
1300
+ "qwik-navigation"
1301
+ ]
1302
+ });
1303
+ if (!viewTransition) {
1304
+ return Promise.resolve();
1305
+ }
1306
+ return viewTransition.ready;
1307
+ }
1308
+ };
1309
+ _waitNextPage().then(() => {
1310
+ const container2 = internal._getQContainerElement(elm);
1311
+ container2.setAttribute(Q_ROUTE, routeName);
1146
1312
  const scrollState2 = currentScrollState(scroller);
1147
1313
  saveScrollHistory(scrollState2);
1148
1314
  win._qRouterScrollEnabled = true;
1149
1315
  if (core.isBrowser) {
1150
1316
  callRestoreScrollOnDocument();
1151
1317
  }
1318
+ if (shouldForcePrevUrl) {
1319
+ internal.forceStoreEffects(routeLocation, "prevUrl");
1320
+ }
1321
+ if (shouldForceUrl) {
1322
+ internal.forceStoreEffects(routeLocation, "url");
1323
+ }
1324
+ if (shouldForceParams) {
1325
+ internal.forceStoreEffects(routeLocation, "params");
1326
+ }
1152
1327
  routeLocation.isNavigating = false;
1153
1328
  navResolver.r?.();
1154
1329
  });
1155
1330
  }
1156
1331
  }
1157
1332
  }
1158
- const promise = run();
1159
1333
  if (core.isServer) {
1160
- return promise;
1334
+ return run();
1161
1335
  } else {
1162
- return;
1336
+ run();
1163
1337
  }
1164
1338
  });
1339
+ };
1340
+ const QwikRouterProvider = core.component$((props) => {
1341
+ useQwikRouter(props);
1165
1342
  return /* @__PURE__ */ jsxRuntime.jsx(core.Slot, {});
1166
1343
  });
1167
1344
  const QwikCityProvider = QwikRouterProvider;
1168
- const QwikRouterMockProvider = core.component$((props) => {
1345
+ const useQwikMockRouter = (props) => {
1169
1346
  const urlEnv = props.url ?? "http://localhost/";
1170
1347
  const url = new URL(urlEnv);
1171
1348
  const routeLocation = core.useStore({
@@ -1176,7 +1353,7 @@ const QwikRouterMockProvider = core.component$((props) => {
1176
1353
  }, {
1177
1354
  deep: false
1178
1355
  });
1179
- const loaderState = core.useSignal({});
1356
+ const loaderState = {};
1180
1357
  const routeInternal = core.useSignal({
1181
1358
  type: "initial",
1182
1359
  dest: url
@@ -1203,6 +1380,9 @@ const QwikRouterMockProvider = core.component$((props) => {
1203
1380
  core.useContextProvider(RouteStateContext, loaderState);
1204
1381
  core.useContextProvider(RouteActionContext, actionState);
1205
1382
  core.useContextProvider(RouteInternalContext, routeInternal);
1383
+ };
1384
+ const QwikRouterMockProvider = core.component$((props) => {
1385
+ useQwikMockRouter(props);
1206
1386
  return /* @__PURE__ */ jsxRuntime.jsx(core.Slot, {});
1207
1387
  });
1208
1388
  const QwikCityMockProvider = QwikRouterMockProvider;
@@ -1211,13 +1391,14 @@ const RouterOutlet = core.component$(() => {
1211
1391
  if (!serverData) {
1212
1392
  throw new Error("PrefetchServiceWorker component must be rendered on the server.");
1213
1393
  }
1214
- const { value } = core.useContext(ContentInternalContext);
1215
- if (value && value.length > 0) {
1216
- const contentsLen = value.length;
1394
+ const internalContext = core.useContext(ContentInternalContext);
1395
+ const contents = internalContext.value;
1396
+ if (contents && contents.length > 0) {
1397
+ const contentsLen = contents.length;
1217
1398
  let cmp = null;
1218
1399
  for (let i = contentsLen - 1; i >= 0; i--) {
1219
- if (value[i].default) {
1220
- cmp = core.jsx(value[i].default, {
1400
+ if (contents[i].default) {
1401
+ cmp = core.jsx(contents[i].default, {
1221
1402
  children: cmp
1222
1403
  });
1223
1404
  }
@@ -1421,24 +1602,25 @@ const globalActionQrl = (actionQrl, ...rest) => {
1421
1602
  const routeAction$ = /* @__PURE__ */ core.implicit$FirstArg(routeActionQrl);
1422
1603
  const globalAction$ = /* @__PURE__ */ core.implicit$FirstArg(globalActionQrl);
1423
1604
  const routeLoaderQrl = (loaderQrl, ...rest) => {
1424
- const { id, validators } = getValidators(rest, loaderQrl);
1605
+ const { id, validators, serializationStrategy } = getValidators(rest, loaderQrl);
1425
1606
  function loader() {
1426
- return core.useContext(RouteStateContext, (state) => {
1427
- if (!(id in state)) {
1428
- throw new Error(`routeLoader$ "${loaderQrl.getSymbol()}" was invoked in a route where it was not declared.
1607
+ const state = internal._resolveContextWithoutSequentialScope(RouteStateContext);
1608
+ if (!(id in state)) {
1609
+ throw new Error(`routeLoader$ "${loaderQrl.getSymbol()}" was invoked in a route where it was not declared.
1429
1610
  This is because the routeLoader$ was not exported in a 'layout.tsx' or 'index.tsx' file of the existing route.
1430
1611
  For more information check: https://qwik.dev/docs/route-loader/
1431
1612
 
1432
1613
  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.
1433
1614
  For more information check: https://qwik.dev/docs/re-exporting-loaders/`);
1434
- }
1435
- return internal._wrapStore(state, id);
1436
- });
1615
+ }
1616
+ core.untrack(() => state[id].value);
1617
+ return state[id];
1437
1618
  }
1438
1619
  loader.__brand = "server_loader";
1439
1620
  loader.__qrl = loaderQrl;
1440
1621
  loader.__validators = validators;
1441
1622
  loader.__id = id;
1623
+ loader.__serializationStrategy = serializationStrategy;
1442
1624
  Object.freeze(loader);
1443
1625
  return loader;
1444
1626
  };
@@ -1543,7 +1725,7 @@ const zodQrl = (qrl) => {
1543
1725
  }
1544
1726
  });
1545
1727
  const data = inputData ?? await ev.parseBody();
1546
- const result = await schema.safeParseAsync(data);
1728
+ const result = await core.withLocale(ev.locale(), () => schema.safeParseAsync(data));
1547
1729
  if (result.success) {
1548
1730
  return result;
1549
1731
  } else {
@@ -1628,7 +1810,7 @@ const serverQrl = (qrl, options) => {
1628
1810
  const res = await fetch(`${origin}?${QFN_KEY}=${qrlHash}${query}`, config);
1629
1811
  const contentType = res.headers.get("Content-Type");
1630
1812
  if (res.ok && contentType === "text/qwik-json-stream" && res.body) {
1631
- return async function* () {
1813
+ return (async function* () {
1632
1814
  try {
1633
1815
  for await (const result of deserializeStream(res.body, ctxElm ?? document.documentElement, abortSignal)) {
1634
1816
  yield result;
@@ -1638,7 +1820,7 @@ const serverQrl = (qrl, options) => {
1638
1820
  await res.body.cancel();
1639
1821
  }
1640
1822
  }
1641
- }();
1823
+ })();
1642
1824
  } else if (contentType === "application/qwik-json") {
1643
1825
  const str = await res.text();
1644
1826
  const [obj] = internal._deserialize(str, ctxElm ?? document.documentElement);
@@ -1667,6 +1849,7 @@ const serverQrl = (qrl, options) => {
1667
1849
  const server$ = /* @__PURE__ */ core.implicit$FirstArg(serverQrl);
1668
1850
  const getValidators = (rest, qrl) => {
1669
1851
  let id;
1852
+ let serializationStrategy = DEFAULT_LOADERS_SERIALIZATION_STRATEGY;
1670
1853
  const validators = [];
1671
1854
  if (rest.length === 1) {
1672
1855
  const options = rest[0];
@@ -1675,6 +1858,9 @@ const getValidators = (rest, qrl) => {
1675
1858
  validators.push(options);
1676
1859
  } else {
1677
1860
  id = options.id;
1861
+ if (options.serializationStrategy) {
1862
+ serializationStrategy = options.serializationStrategy;
1863
+ }
1678
1864
  if (options.validation) {
1679
1865
  validators.push(...options.validation);
1680
1866
  }
@@ -1695,7 +1881,8 @@ const getValidators = (rest, qrl) => {
1695
1881
  }
1696
1882
  return {
1697
1883
  validators: validators.reverse(),
1698
- id
1884
+ id,
1885
+ serializationStrategy
1699
1886
  };
1700
1887
  };
1701
1888
  const deserializeStream = async function* (stream, ctxElm, abortSignal) {
@@ -1722,7 +1909,8 @@ const deserializeStream = async function* (stream, ctxElm, abortSignal) {
1722
1909
  reader.releaseLock();
1723
1910
  }
1724
1911
  };
1725
- const ServiceWorkerRegister = (props) => core.jsx("script", {
1912
+ const ServiceWorkerRegister = (props) => /* @__PURE__ */ jsxRuntime.jsx("script", {
1913
+ type: "module",
1726
1914
  dangerouslySetInnerHTML: swRegister,
1727
1915
  nonce: props.nonce
1728
1916
  });
@@ -1846,10 +2034,55 @@ function omitProps(obj, keys) {
1846
2034
  }
1847
2035
  return omittedObj;
1848
2036
  }
2037
+ const createRenderer = (getOptions) => {
2038
+ return (opts) => {
2039
+ const { jsx, options } = getOptions(opts);
2040
+ return server.renderToStream(jsx, options);
2041
+ };
2042
+ };
2043
+ const DocumentHeadTags = core.component$((props) => {
2044
+ let head = useDocumentHead();
2045
+ if (props) {
2046
+ head = {
2047
+ ...head,
2048
+ ...props
2049
+ };
2050
+ }
2051
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, {
2052
+ children: [
2053
+ head.title && /* @__PURE__ */ jsxRuntime.jsx("title", {
2054
+ children: head.title
2055
+ }),
2056
+ head.meta.map((m) => /* @__PURE__ */ jsxRuntime.jsx("meta", {
2057
+ ...m
2058
+ })),
2059
+ head.links.map((l) => /* @__PURE__ */ jsxRuntime.jsx("link", {
2060
+ ...l
2061
+ })),
2062
+ head.styles.map((s) => {
2063
+ const props2 = s.props || s;
2064
+ return /* @__PURE__ */ core.createElement("style", {
2065
+ ...props2,
2066
+ dangerouslySetInnerHTML: s.style || props2.dangerouslySetInnerHTML,
2067
+ key: s.key
2068
+ });
2069
+ }),
2070
+ head.scripts.map((s) => {
2071
+ const props2 = s.props || s;
2072
+ return /* @__PURE__ */ core.createElement("script", {
2073
+ ...props2,
2074
+ dangerouslySetInnerHTML: s.script || props2.dangerouslySetInnerHTML,
2075
+ key: s.key
2076
+ });
2077
+ })
2078
+ ]
2079
+ });
2080
+ });
1849
2081
  Object.defineProperty(exports, "z", {
1850
2082
  enumerable: true,
1851
2083
  get: () => zod.z
1852
2084
  });
2085
+ exports.DocumentHeadTags = DocumentHeadTags;
1853
2086
  exports.ErrorBoundary = ErrorBoundary;
1854
2087
  exports.Form = Form;
1855
2088
  exports.Link = Link;
@@ -1861,6 +2094,7 @@ exports.QwikRouterMockProvider = QwikRouterMockProvider;
1861
2094
  exports.QwikRouterProvider = QwikRouterProvider;
1862
2095
  exports.RouterOutlet = RouterOutlet;
1863
2096
  exports.ServiceWorkerRegister = ServiceWorkerRegister;
2097
+ exports.createRenderer = createRenderer;
1864
2098
  exports.globalAction$ = globalAction$;
1865
2099
  exports.globalActionQrl = globalActionQrl;
1866
2100
  exports.omitProps = omitProps;
@@ -1877,6 +2111,7 @@ exports.useLocation = useLocation;
1877
2111
  exports.useNavigate = useNavigate;
1878
2112
  exports.usePreventNavigate$ = usePreventNavigate$;
1879
2113
  exports.usePreventNavigateQrl = usePreventNavigateQrl;
2114
+ exports.useQwikRouter = useQwikRouter;
1880
2115
  exports.valibot$ = valibot$;
1881
2116
  exports.valibotQrl = valibotQrl;
1882
2117
  exports.validator$ = validator$;