@qwik.dev/router 2.0.0-beta.1 → 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 (149) hide show
  1. package/adapters/static/vite.d.ts +1 -1
  2. package/lib/adapters/azure-swa/vite/index-BqUeglYs.cjs +1 -0
  3. package/lib/adapters/azure-swa/vite/index-CBIchDYq.js +651 -0
  4. package/lib/adapters/azure-swa/vite/index-ClHGw5z1.js +6 -0
  5. package/lib/adapters/azure-swa/vite/index-CrwlB95_.js +22 -0
  6. package/lib/adapters/azure-swa/vite/index-DTIOTwZo.cjs +11 -0
  7. package/lib/adapters/azure-swa/vite/index-vQuPcef3.cjs +1 -0
  8. package/lib/adapters/azure-swa/vite/index.cjs +5 -96
  9. package/lib/adapters/azure-swa/vite/index.d.ts +2 -2
  10. package/lib/adapters/azure-swa/vite/index.mjs +201 -26
  11. package/lib/adapters/bun-server/vite/index-BqUeglYs.cjs +1 -0
  12. package/lib/adapters/bun-server/vite/index-CBIchDYq.js +651 -0
  13. package/lib/adapters/bun-server/vite/index-ClHGw5z1.js +6 -0
  14. package/lib/adapters/bun-server/vite/index-CrwlB95_.js +22 -0
  15. package/lib/adapters/bun-server/vite/index-DTIOTwZo.cjs +11 -0
  16. package/lib/adapters/bun-server/vite/index-vQuPcef3.cjs +1 -0
  17. package/lib/adapters/bun-server/vite/index.cjs +5 -50
  18. package/lib/adapters/bun-server/vite/index.d.ts +2 -2
  19. package/lib/adapters/bun-server/vite/index.mjs +196 -12
  20. package/lib/adapters/cloud-run/vite/index-BqUeglYs.cjs +1 -0
  21. package/lib/adapters/cloud-run/vite/index-CBIchDYq.js +651 -0
  22. package/lib/adapters/cloud-run/vite/index-ClHGw5z1.js +6 -0
  23. package/lib/adapters/cloud-run/vite/index-CrwlB95_.js +22 -0
  24. package/lib/adapters/cloud-run/vite/index-DTIOTwZo.cjs +11 -0
  25. package/lib/adapters/cloud-run/vite/index-vQuPcef3.cjs +1 -0
  26. package/lib/adapters/cloud-run/vite/index.cjs +5 -47
  27. package/lib/adapters/cloud-run/vite/index.d.ts +2 -2
  28. package/lib/adapters/cloud-run/vite/index.mjs +195 -11
  29. package/lib/adapters/cloudflare-pages/vite/index-BIeHg2Cj.cjs +5 -0
  30. package/lib/adapters/cloudflare-pages/vite/index-C455V8_A.cjs +1 -0
  31. package/lib/adapters/cloudflare-pages/vite/index-ClHGw5z1.js +6 -0
  32. package/lib/adapters/cloudflare-pages/vite/index-D3HITboM.js +645 -0
  33. package/lib/adapters/cloudflare-pages/vite/index-DKcVHRBy.cjs +11 -0
  34. package/lib/adapters/cloudflare-pages/vite/index-DwovcBp3.js +22 -0
  35. package/lib/adapters/cloudflare-pages/vite/index-bogwy7wh.js +250 -0
  36. package/lib/adapters/cloudflare-pages/vite/index-vQuPcef3.cjs +1 -0
  37. package/lib/adapters/cloudflare-pages/vite/index.cjs +1 -115
  38. package/lib/adapters/cloudflare-pages/vite/index.d.ts +2 -2
  39. package/lib/adapters/cloudflare-pages/vite/index.mjs +4 -78
  40. package/lib/adapters/deno-server/vite/index-BqUeglYs.cjs +1 -0
  41. package/lib/adapters/deno-server/vite/index-CBIchDYq.js +651 -0
  42. package/lib/adapters/deno-server/vite/index-ClHGw5z1.js +6 -0
  43. package/lib/adapters/deno-server/vite/index-CrwlB95_.js +22 -0
  44. package/lib/adapters/deno-server/vite/index-DTIOTwZo.cjs +11 -0
  45. package/lib/adapters/deno-server/vite/index-vQuPcef3.cjs +1 -0
  46. package/lib/adapters/deno-server/vite/index.cjs +5 -62
  47. package/lib/adapters/deno-server/vite/index.d.ts +2 -2
  48. package/lib/adapters/deno-server/vite/index.mjs +198 -14
  49. package/lib/adapters/netlify-edge/vite/index-BqUeglYs.cjs +1 -0
  50. package/lib/adapters/netlify-edge/vite/index-CBIchDYq.js +651 -0
  51. package/lib/adapters/netlify-edge/vite/index-ClHGw5z1.js +6 -0
  52. package/lib/adapters/netlify-edge/vite/index-CrwlB95_.js +22 -0
  53. package/lib/adapters/netlify-edge/vite/index-DTIOTwZo.cjs +11 -0
  54. package/lib/adapters/netlify-edge/vite/index-vQuPcef3.cjs +1 -0
  55. package/lib/adapters/netlify-edge/vite/index.cjs +6 -129
  56. package/lib/adapters/netlify-edge/vite/index.d.ts +2 -2
  57. package/lib/adapters/netlify-edge/vite/index.mjs +240 -60
  58. package/lib/adapters/node-server/vite/index-BqUeglYs.cjs +1 -0
  59. package/lib/adapters/node-server/vite/index-CBIchDYq.js +651 -0
  60. package/lib/adapters/node-server/vite/index-ClHGw5z1.js +6 -0
  61. package/lib/adapters/node-server/vite/index-CrwlB95_.js +22 -0
  62. package/lib/adapters/node-server/vite/index-DTIOTwZo.cjs +11 -0
  63. package/lib/adapters/node-server/vite/index-vQuPcef3.cjs +1 -0
  64. package/lib/adapters/node-server/vite/index.cjs +5 -50
  65. package/lib/adapters/node-server/vite/index.d.ts +2 -2
  66. package/lib/adapters/node-server/vite/index.mjs +196 -12
  67. package/lib/adapters/shared/vite/index-BqUeglYs.cjs +1 -0
  68. package/lib/adapters/shared/vite/index-CBIchDYq.js +651 -0
  69. package/lib/adapters/shared/vite/index-ClHGw5z1.js +6 -0
  70. package/lib/adapters/shared/vite/index-CrwlB95_.js +22 -0
  71. package/lib/adapters/shared/vite/index-DTIOTwZo.cjs +11 -0
  72. package/lib/adapters/shared/vite/index-vQuPcef3.cjs +1 -0
  73. package/lib/adapters/shared/vite/index.cjs +2 -375
  74. package/lib/adapters/shared/vite/index.d.ts +9 -15
  75. package/lib/adapters/shared/vite/index.mjs +155 -292
  76. package/lib/adapters/ssg/vite/index-BqUeglYs.cjs +1 -0
  77. package/lib/adapters/ssg/vite/index-CBIchDYq.js +651 -0
  78. package/lib/adapters/ssg/vite/index-ClHGw5z1.js +6 -0
  79. package/lib/adapters/ssg/vite/index-CrwlB95_.js +22 -0
  80. package/lib/adapters/ssg/vite/index-DTIOTwZo.cjs +11 -0
  81. package/lib/adapters/ssg/vite/index-vQuPcef3.cjs +1 -0
  82. package/lib/adapters/ssg/vite/index.cjs +5 -0
  83. package/lib/adapters/ssg/vite/index.d.ts +13 -0
  84. package/lib/adapters/ssg/vite/index.mjs +201 -0
  85. package/lib/adapters/vercel-edge/vite/index-BqUeglYs.cjs +1 -0
  86. package/lib/adapters/vercel-edge/vite/index-CBIchDYq.js +651 -0
  87. package/lib/adapters/vercel-edge/vite/index-ClHGw5z1.js +6 -0
  88. package/lib/adapters/vercel-edge/vite/index-CrwlB95_.js +22 -0
  89. package/lib/adapters/vercel-edge/vite/index-DTIOTwZo.cjs +11 -0
  90. package/lib/adapters/vercel-edge/vite/index-vQuPcef3.cjs +1 -0
  91. package/lib/adapters/vercel-edge/vite/index.cjs +5 -118
  92. package/lib/adapters/vercel-edge/vite/index.d.ts +2 -2
  93. package/lib/adapters/vercel-edge/vite/index.mjs +230 -51
  94. package/lib/index.d.ts +172 -50
  95. package/lib/index.qwik.cjs +333 -160
  96. package/lib/index.qwik.mjs +335 -162
  97. package/lib/middleware/aws-lambda/index.cjs +1 -0
  98. package/lib/middleware/aws-lambda/index.d.ts +3 -2
  99. package/lib/middleware/aws-lambda/index.mjs +27 -41
  100. package/lib/middleware/azure-swa/index.cjs +1 -0
  101. package/lib/middleware/azure-swa/index.mjs +46 -269
  102. package/lib/middleware/bun/index.cjs +1 -0
  103. package/lib/middleware/bun/index.mjs +68 -120
  104. package/lib/middleware/cloudflare-pages/index.cjs +1 -0
  105. package/lib/middleware/cloudflare-pages/index.mjs +48 -80
  106. package/lib/middleware/deno/index.cjs +1 -0
  107. package/lib/middleware/deno/index.mjs +63 -110
  108. package/lib/middleware/firebase/index.cjs +1 -0
  109. package/lib/middleware/firebase/index.mjs +16 -28
  110. package/lib/middleware/netlify-edge/index.cjs +1 -0
  111. package/lib/middleware/netlify-edge/index.mjs +36 -64
  112. package/lib/middleware/node/index.cjs +1 -314
  113. package/lib/middleware/node/index.mjs +116 -198
  114. package/lib/middleware/request-handler/index.cjs +11 -1607
  115. package/lib/middleware/request-handler/index.d.ts +63 -62
  116. package/lib/middleware/request-handler/index.mjs +879 -1333
  117. package/lib/middleware/vercel-edge/index.cjs +1 -0
  118. package/lib/middleware/vercel-edge/index.mjs +47 -82
  119. package/lib/modules.d.ts +4 -12
  120. package/lib/service-worker.cjs +1 -17
  121. package/lib/service-worker.mjs +5 -15
  122. package/lib/ssg/deno.cjs +1 -0
  123. package/lib/ssg/deno.mjs +6 -0
  124. package/lib/ssg/index-CBIchDYq.js +651 -0
  125. package/lib/ssg/index-ClHGw5z1.js +6 -0
  126. package/lib/ssg/index-DTIOTwZo.cjs +11 -0
  127. package/lib/ssg/index-vQuPcef3.cjs +1 -0
  128. package/lib/ssg/index.cjs +1 -0
  129. package/lib/{static → ssg}/index.d.ts +17 -17
  130. package/lib/ssg/index.mjs +22 -0
  131. package/lib/ssg/node.cjs +11 -0
  132. package/lib/ssg/node.mjs +651 -0
  133. package/lib/vite/index.cjs +28 -27431
  134. package/lib/vite/index.d.ts +16 -0
  135. package/lib/vite/index.mjs +1413 -27227
  136. package/modules.d.ts +4 -12
  137. package/package.json +50 -39
  138. package/ssg.d.ts +2 -0
  139. package/static.d.ts +1 -1
  140. package/lib/adapters/static/vite/index.cjs +0 -368
  141. package/lib/adapters/static/vite/index.d.ts +0 -10
  142. package/lib/adapters/static/vite/index.mjs +0 -331
  143. package/lib/static/deno.mjs +0 -8
  144. package/lib/static/index.cjs +0 -67
  145. package/lib/static/index.mjs +0 -48
  146. package/lib/static/node.cjs +0 -1124
  147. package/lib/static/node.mjs +0 -1086
  148. package/middleware/request-handler/generated/not-found-paths.ts +0 -7
  149. package/middleware/request-handler/generated/static-paths.ts +0 -35
@@ -1,11 +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, useSignal, untrack, sync$, isDev, withLocale, event$, useStyles$, isServer, useStore, useContextProvider, useTask$, getLocale, jsx as jsx$1, SkipRender } from "@qwik.dev/core";
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
3
  import { p } from "@qwik.dev/core/preloader";
4
- import { _deserialize, _weakSerialize, _getContextElement, _getQContainerElement, _waitUntilRendered, _wrapStore, _getContextEvent, _serialize } from "@qwik.dev/core/internal";
4
+ import { _deserialize, _UNINITIALIZED, _getContextContainer, SerializerSymbol, _getContextElement, _hasStoreEffects, _getQContainerElement, forceStoreEffects, _waitUntilRendered, _resolveContextWithoutSequentialScope, _getContextEvent, _serialize } from "@qwik.dev/core/internal";
5
5
  import * as qwikRouterConfig from "@qwik-router-config";
6
6
  import { z } from "zod";
7
7
  import { z as z2 } from "zod";
8
8
  import swRegister from "@qwik-router-sw-register";
9
+ import { renderToStream } from "@qwik.dev/core/server";
9
10
  const ErrorBoundary = component$((props) => {
10
11
  const store2 = useErrorBoundary();
11
12
  useOnWindow("qerror", $((e) => {
@@ -21,106 +22,25 @@ const ErrorBoundary = component$((props) => {
21
22
  const MODULE_CACHE = /* @__PURE__ */ new WeakMap();
22
23
  const CLIENT_DATA_CACHE = /* @__PURE__ */ new Map();
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 shouldPreload = (clientNavPath, currentLoc) => {
61
- if (clientNavPath) {
62
- const prefetchUrl = toUrl(clientNavPath, currentLoc.url);
63
- const currentUrl = toUrl("", currentLoc.url);
64
- return !isSamePathname(prefetchUrl, currentUrl);
65
- }
66
- return false;
67
- };
68
- const isPromise = (value) => {
69
- return value && typeof value.then === "function";
70
- };
71
- const deepFreeze = (obj) => {
72
- if (obj == null) {
73
- return obj;
74
- }
75
- Object.getOwnPropertyNames(obj).forEach((prop) => {
76
- const value = obj[prop];
77
- if (value && typeof value === "object" && !Object.isFrozen(value)) {
78
- deepFreeze(value);
79
- }
80
- });
81
- return Object.freeze(obj);
82
- };
83
- const clientNavigate = (win, navType, fromURL, toURL, replaceState = false) => {
84
- if (navType !== "popstate") {
85
- const samePath = isSamePath(fromURL, toURL);
86
- const sameHash = fromURL.hash === toURL.hash;
87
- if (!samePath || !sameHash) {
88
- const newState = {
89
- _qRouterScroll: newScrollState()
90
- };
91
- if (replaceState) {
92
- win.history.replaceState(newState, "", toPath(toURL));
93
- } else {
94
- win.history.pushState(newState, "", toPath(toURL));
95
- }
96
- }
97
- }
98
- };
99
- const newScrollState = () => {
100
- return {
101
- x: 0,
102
- y: 0,
103
- w: 0,
104
- h: 0
105
- };
106
- };
107
- const prefetchSymbols = (path) => {
108
- if (isBrowser) {
109
- path = path.endsWith("/") ? path : path + "/";
110
- path = path.length > 1 && path.startsWith("/") ? path.slice(1) : path;
111
- p(path, 0.8);
112
- }
113
- };
114
- 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) => {
115
32
  const pagePathname = url.pathname;
116
33
  const pageSearch = url.search;
117
- const clientDataPath = getClientDataPath(pagePathname, pageSearch, opts?.action);
34
+ const clientDataPath = getClientDataPath(pagePathname, pageSearch, {
35
+ actionId: opts?.action?.id,
36
+ loaderIds: opts?.loaderIds
37
+ });
118
38
  let qData;
119
39
  if (!opts?.action) {
120
40
  qData = CLIENT_DATA_CACHE.get(clientDataPath);
121
41
  }
122
- if (opts?.prefetchSymbols !== false) {
123
- prefetchSymbols(pagePathname);
42
+ if (opts?.preloadRouteBundles !== false) {
43
+ preloadRouteBundles(pagePathname, 0.8);
124
44
  }
125
45
  let resolveFn;
126
46
  if (!qData) {
@@ -129,6 +49,10 @@ const loadClientData = async (url, element, opts) => {
129
49
  opts.action.data = void 0;
130
50
  }
131
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
+ }
132
56
  if (rsp.redirected) {
133
57
  const redirectedURL = new URL(rsp.url);
134
58
  const isQData = redirectedURL.pathname.endsWith("/q-data.json");
@@ -204,11 +128,108 @@ const getFetchOptions = (action, noCache) => {
204
128
  method: "POST",
205
129
  body: JSON.stringify(actionData),
206
130
  headers: {
207
- "Content-Type": "application/json, charset=UTF-8"
131
+ "Content-Type": "application/json; charset=UTF-8"
208
132
  }
209
133
  };
210
134
  }
211
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
+ };
212
233
  const RouteStateContext = /* @__PURE__ */ createContextId("qc-s");
213
234
  const ContentContext = /* @__PURE__ */ createContextId("qc-c");
214
235
  const ContentInternalContext = /* @__PURE__ */ createContextId("qc-ic");
@@ -251,33 +272,38 @@ const Link = component$((props) => {
251
272
  }
252
273
  if (elm && elm.href) {
253
274
  const url = new URL(elm.href);
254
- prefetchSymbols(url.pathname);
275
+ preloadRouteBundles(url.pathname);
255
276
  if (elm.hasAttribute("data-prefetch")) {
256
277
  loadClientData(url, elm, {
257
- prefetchSymbols: false,
278
+ preloadRouteBundles: false,
258
279
  isPrefetch: true
259
280
  });
260
281
  }
261
282
  }
262
283
  }) : void 0;
263
- const preventDefault = clientNavPath ? sync$((event, target) => {
284
+ const preventDefault = clientNavPath ? sync$((event) => {
264
285
  if (!(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)) {
265
286
  event.preventDefault();
266
287
  }
267
288
  }) : void 0;
268
- const handleClick = clientNavPath ? $(async (event, elm) => {
289
+ const handleClientSideNavigation = clientNavPath ? $((event, elm) => {
269
290
  if (event.defaultPrevented) {
270
291
  if (elm.href) {
271
292
  elm.setAttribute("aria-pressed", "true");
272
- await nav(elm.href, {
293
+ nav(elm.href, {
273
294
  forceReload: reload,
274
295
  replaceState,
275
296
  scroll
297
+ }).then(() => {
298
+ elm.removeAttribute("aria-pressed");
276
299
  });
277
- elm.removeAttribute("aria-pressed");
278
300
  }
279
301
  }
280
302
  }) : void 0;
303
+ const handlePreload = $((_, elm) => {
304
+ const url = new URL(elm.href);
305
+ preloadRouteBundles(url.pathname, 1);
306
+ });
281
307
  useVisibleTask$(({ track }) => {
282
308
  track(() => loc.url.pathname);
283
309
  const handler = linkProps.onQVisible$;
@@ -299,8 +325,9 @@ const Link = component$((props) => {
299
325
  ...linkProps,
300
326
  onClick$: [
301
327
  preventDefault,
328
+ handlePreload,
302
329
  onClick$,
303
- handleClick
330
+ handleClientSideNavigation
304
331
  ],
305
332
  "data-prefetch": prefetchData,
306
333
  onMouseOver$: [
@@ -316,8 +343,8 @@ const Link = component$((props) => {
316
343
  children: /* @__PURE__ */ jsx(Slot, {})
317
344
  });
318
345
  });
319
- const resolveHead = (endpoint, routeLocation, contentModules, locale) => {
320
- const head = createDocumentHead();
346
+ const resolveHead = (endpoint, routeLocation, contentModules, locale, defaults) => {
347
+ const head = createDocumentHead(defaults);
321
348
  const getData = (loaderOrAction) => {
322
349
  const id = loaderOrAction.__id;
323
350
  if (loaderOrAction.__brand === "server_loader") {
@@ -373,13 +400,23 @@ const mergeArray = (existingArr, newArr) => {
373
400
  }
374
401
  }
375
402
  };
376
- const createDocumentHead = () => ({
377
- title: "",
378
- meta: [],
379
- links: [],
380
- styles: [],
381
- scripts: [],
382
- 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
+ }
383
420
  });
384
421
  function matchRoute(route, path) {
385
422
  const routeIdx = startIdxSkipSlash(route);
@@ -389,6 +426,9 @@ function matchRoute(route, path) {
389
426
  return matchRoutePart(route, routeIdx, routeLength, path, pathIdx, pathLength);
390
427
  }
391
428
  function matchRoutePart(route, routeIdx, routeLength, path, pathIdx, pathLength) {
429
+ if (path.startsWith("/build/")) {
430
+ return null;
431
+ }
392
432
  let params = null;
393
433
  while (routeIdx < routeLength) {
394
434
  const routeCh = route.charCodeAt(routeIdx++);
@@ -490,18 +530,42 @@ function lastIndexOf(text, start, match, searchIdx, notFoundIdx) {
490
530
  }
491
531
  return idx > start ? idx : notFoundIdx;
492
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
+ };
493
557
  const loadRoute = async (routes, menus, cacheModules, pathname) => {
494
558
  if (!Array.isArray(routes)) {
495
559
  return null;
496
560
  }
497
561
  for (const routeData of routes) {
498
- const routeName = routeData[0];
562
+ const routeName = routeData[RouteDataProp.RouteName];
499
563
  const params = matchRoute(routeName, pathname);
500
564
  if (!params) {
501
565
  continue;
502
566
  }
503
- const loaders = routeData[1];
504
- const routeBundleNames = routeData[3];
567
+ const loaders = routeData[RouteDataProp.Loaders];
568
+ const routeBundleNames = routeData[RouteDataProp.RouteBundleNames];
505
569
  const modules = new Array(loaders.length);
506
570
  const pendingLoads = [];
507
571
  loaders.forEach((moduleLoader, i) => {
@@ -546,9 +610,9 @@ const loadModule = (moduleLoader, pendingLoads, moduleSetter, cacheModules) => {
546
610
  const getMenuLoader = (menus, pathname) => {
547
611
  if (menus) {
548
612
  pathname = pathname.endsWith("/") ? pathname : pathname + "/";
549
- 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("/") ? "" : "/")));
550
614
  if (menu) {
551
- return menu[1];
615
+ return menu[MenuDataProp.MenuLoader];
552
616
  }
553
617
  }
554
618
  };
@@ -740,8 +804,8 @@ const spaInit = event$((_, el) => {
740
804
  };
741
805
  win[scrollEnabled] = true;
742
806
  setTimeout(() => {
743
- addEventListener("popstate", win[initPopstate]);
744
- addEventListener("scroll", win[initScroll], {
807
+ win.addEventListener("popstate", win[initPopstate]);
808
+ win.addEventListener("scroll", win[initScroll], {
745
809
  passive: true
746
810
  });
747
811
  document.body.addEventListener("click", win[initAnchors]);
@@ -779,11 +843,11 @@ const preventNav = {};
779
843
  const internalState = {
780
844
  navCount: 0
781
845
  };
782
- const QwikRouterProvider = component$((props) => {
846
+ const useQwikRouter = (props) => {
783
847
  useStyles$(`
784
848
  @layer qwik {
785
849
  @supports selector(html:active-view-transition-type(type)) {
786
- html:active-view-transition-type(qwik-router-spa) {
850
+ html:active-view-transition-type(qwik-navigation) {
787
851
  :root{view-transition-name:none}
788
852
  }
789
853
  }
@@ -800,24 +864,40 @@ const QwikRouterProvider = component$((props) => {
800
864
  if (!urlEnv) {
801
865
  throw new Error(`Missing Qwik URL Env Data`);
802
866
  }
867
+ const serverHead = useServerData("documentHead");
803
868
  if (isServer) {
804
869
  if (env.ev.originalUrl.pathname !== env.ev.url.pathname && !__EXPERIMENTAL__.enableRequestRewrite) {
805
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.`);
806
871
  }
807
872
  }
808
873
  const url = new URL(urlEnv);
809
- const routeLocation = useStore({
874
+ const routeLocationTarget = {
810
875
  url,
811
876
  params: env.params,
812
877
  isNavigating: false,
813
878
  prevUrl: void 0
814
- }, {
879
+ };
880
+ const routeLocation = useStore(routeLocationTarget, {
815
881
  deep: false
816
882
  });
817
883
  const navResolver = {};
818
- const loaderState = _weakSerialize(useStore(env.response.loaders, {
819
- deep: false
820
- }));
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
+ };
821
901
  const routeInternal = useSignal({
822
902
  type: "initial",
823
903
  dest: url,
@@ -825,7 +905,7 @@ const QwikRouterProvider = component$((props) => {
825
905
  replaceState: false,
826
906
  scroll: true
827
907
  });
828
- const documentHead = useStore(createDocumentHead);
908
+ const documentHead = useStore(() => createDocumentHead(serverHead));
829
909
  const content = useStore({
830
910
  headings: void 0,
831
911
  menu: void 0
@@ -910,7 +990,7 @@ const QwikRouterProvider = component$((props) => {
910
990
  let scroller = document.getElementById(QWIK_ROUTER_SCROLLER);
911
991
  if (!scroller) {
912
992
  scroller = document.getElementById(QWIK_CITY_SCROLLER);
913
- if (scroller) {
993
+ if (scroller && isDev) {
914
994
  console.warn(`Please update your scroller ID to "${QWIK_ROUTER_SCROLLER}" as "${QWIK_CITY_SCROLLER}" is deprecated and will be removed in V3`);
915
995
  }
916
996
  }
@@ -971,10 +1051,10 @@ const QwikRouterProvider = component$((props) => {
971
1051
  } else {
972
1052
  trackUrl = new URL(navigation.dest, location);
973
1053
  if (trackUrl.pathname.endsWith("/")) {
974
- if (!qwikRouterConfig.trailingSlash) {
1054
+ if (globalThis.__NO_TRAILING_SLASH__) {
975
1055
  trackUrl.pathname = trackUrl.pathname.slice(0, -1);
976
1056
  }
977
- } else if (qwikRouterConfig.trailingSlash) {
1057
+ } else if (!globalThis.__NO_TRAILING_SLASH__) {
978
1058
  trackUrl.pathname += "/";
979
1059
  }
980
1060
  let loadRoutePromise = loadRoute(qwikRouterConfig.routes, qwikRouterConfig.menus, qwikRouterConfig.cacheModules, trackUrl.pathname);
@@ -1016,25 +1096,38 @@ const QwikRouterProvider = component$((props) => {
1016
1096
  const [routeName, params, mods, menu] = loadedRoute;
1017
1097
  const contentModules = mods;
1018
1098
  const pageModule = contentModules[contentModules.length - 1];
1019
- const isRedirect = navType === "form" && !isSamePath(trackUrl, prevUrl);
1020
- if (navigation.dest.search && !isRedirect) {
1099
+ if (navigation.dest.search && !!isSamePath(trackUrl, prevUrl)) {
1021
1100
  trackUrl.search = navigation.dest.search;
1022
1101
  }
1102
+ let shouldForcePrevUrl = false;
1103
+ let shouldForceUrl = false;
1104
+ let shouldForceParams = false;
1023
1105
  if (!isSamePath(trackUrl, prevUrl)) {
1024
- 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;
1025
1122
  }
1026
- routeLocation.url = trackUrl;
1027
- routeLocation.params = {
1028
- ...params
1029
- };
1030
1123
  routeInternal.untrackedValue = {
1031
1124
  type: navType,
1032
1125
  dest: trackUrl
1033
1126
  };
1034
- const resolvedHead = resolveHead(clientPageData, routeLocation, contentModules, locale);
1127
+ const resolvedHead = resolveHead(clientPageData, routeLocation, contentModules, locale, serverHead);
1035
1128
  content.headings = pageModule.headings;
1036
1129
  content.menu = menu;
1037
- contentInternal.value = noSerialize(contentModules);
1130
+ contentInternal.untrackedValue = noSerialize(contentModules);
1038
1131
  documentHead.links = resolvedHead.links;
1039
1132
  documentHead.meta = resolvedHead.meta;
1040
1133
  documentHead.styles = resolvedHead.styles;
@@ -1047,15 +1140,25 @@ const QwikRouterProvider = component$((props) => {
1047
1140
  scrollState = getScrollHistory();
1048
1141
  }
1049
1142
  const scroller = document.getElementById(QWIK_ROUTER_SCROLLER) ?? document.documentElement;
1050
- 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)) {
1051
1144
  document.__q_scroll_restore__ = () => restoreScroll(navType, trackUrl, prevUrl, scroller, scrollState);
1052
1145
  }
1053
1146
  const loaders = clientPageData?.loaders;
1054
- const win = window;
1055
1147
  if (loaders) {
1056
- 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
+ }
1057
1159
  }
1058
1160
  CLIENT_DATA_CACHE.clear();
1161
+ const win = window;
1059
1162
  if (!win._qRouterSPA) {
1060
1163
  win._qRouterSPA = true;
1061
1164
  history.scrollRestoration = "manual";
@@ -1166,10 +1269,11 @@ const QwikRouterProvider = component$((props) => {
1166
1269
  }
1167
1270
  const navigate = () => {
1168
1271
  clientNavigate(window, navType, prevUrl, trackUrl, replaceState);
1272
+ contentInternal.force();
1169
1273
  return _waitUntilRendered(elm);
1170
1274
  };
1171
1275
  const _waitNextPage = () => {
1172
- if (isServer || props.viewTransition === false) {
1276
+ if (isServer || props?.viewTransition === false) {
1173
1277
  return navigate();
1174
1278
  } else {
1175
1279
  const viewTransition = startViewTransition({
@@ -1185,14 +1289,23 @@ const QwikRouterProvider = component$((props) => {
1185
1289
  }
1186
1290
  };
1187
1291
  _waitNextPage().then(() => {
1188
- const container = _getQContainerElement(elm);
1189
- container.setAttribute("q:route", routeName);
1292
+ const container2 = _getQContainerElement(elm);
1293
+ container2.setAttribute(Q_ROUTE, routeName);
1190
1294
  const scrollState2 = currentScrollState(scroller);
1191
1295
  saveScrollHistory(scrollState2);
1192
1296
  win._qRouterScrollEnabled = true;
1193
1297
  if (isBrowser) {
1194
1298
  callRestoreScrollOnDocument();
1195
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
+ }
1196
1309
  routeLocation.isNavigating = false;
1197
1310
  navResolver.r?.();
1198
1311
  });
@@ -1205,10 +1318,13 @@ const QwikRouterProvider = component$((props) => {
1205
1318
  run();
1206
1319
  }
1207
1320
  });
1321
+ };
1322
+ const QwikRouterProvider = component$((props) => {
1323
+ useQwikRouter(props);
1208
1324
  return /* @__PURE__ */ jsx(Slot, {});
1209
1325
  });
1210
1326
  const QwikCityProvider = QwikRouterProvider;
1211
- const QwikRouterMockProvider = component$((props) => {
1327
+ const useQwikMockRouter = (props) => {
1212
1328
  const urlEnv = props.url ?? "http://localhost/";
1213
1329
  const url = new URL(urlEnv);
1214
1330
  const routeLocation = useStore({
@@ -1219,7 +1335,7 @@ const QwikRouterMockProvider = component$((props) => {
1219
1335
  }, {
1220
1336
  deep: false
1221
1337
  });
1222
- const loaderState = useSignal({});
1338
+ const loaderState = {};
1223
1339
  const routeInternal = useSignal({
1224
1340
  type: "initial",
1225
1341
  dest: url
@@ -1246,6 +1362,9 @@ const QwikRouterMockProvider = component$((props) => {
1246
1362
  useContextProvider(RouteStateContext, loaderState);
1247
1363
  useContextProvider(RouteActionContext, actionState);
1248
1364
  useContextProvider(RouteInternalContext, routeInternal);
1365
+ };
1366
+ const QwikRouterMockProvider = component$((props) => {
1367
+ useQwikMockRouter(props);
1249
1368
  return /* @__PURE__ */ jsx(Slot, {});
1250
1369
  });
1251
1370
  const QwikCityMockProvider = QwikRouterMockProvider;
@@ -1254,13 +1373,14 @@ const RouterOutlet = component$(() => {
1254
1373
  if (!serverData) {
1255
1374
  throw new Error("PrefetchServiceWorker component must be rendered on the server.");
1256
1375
  }
1257
- const { value } = useContext(ContentInternalContext);
1258
- if (value && value.length > 0) {
1259
- 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;
1260
1380
  let cmp = null;
1261
1381
  for (let i = contentsLen - 1; i >= 0; i--) {
1262
- if (value[i].default) {
1263
- cmp = jsx$1(value[i].default, {
1382
+ if (contents[i].default) {
1383
+ cmp = jsx$1(contents[i].default, {
1264
1384
  children: cmp
1265
1385
  });
1266
1386
  }
@@ -1464,24 +1584,25 @@ const globalActionQrl = (actionQrl, ...rest) => {
1464
1584
  const routeAction$ = /* @__PURE__ */ implicit$FirstArg(routeActionQrl);
1465
1585
  const globalAction$ = /* @__PURE__ */ implicit$FirstArg(globalActionQrl);
1466
1586
  const routeLoaderQrl = (loaderQrl, ...rest) => {
1467
- const { id, validators } = getValidators(rest, loaderQrl);
1587
+ const { id, validators, serializationStrategy } = getValidators(rest, loaderQrl);
1468
1588
  function loader() {
1469
- return useContext(RouteStateContext, (state) => {
1470
- if (!(id in state)) {
1471
- 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.
1472
1592
  This is because the routeLoader$ was not exported in a 'layout.tsx' or 'index.tsx' file of the existing route.
1473
1593
  For more information check: https://qwik.dev/docs/route-loader/
1474
1594
 
1475
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.
1476
1596
  For more information check: https://qwik.dev/docs/re-exporting-loaders/`);
1477
- }
1478
- return _wrapStore(state, id);
1479
- });
1597
+ }
1598
+ untrack(() => state[id].value);
1599
+ return state[id];
1480
1600
  }
1481
1601
  loader.__brand = "server_loader";
1482
1602
  loader.__qrl = loaderQrl;
1483
1603
  loader.__validators = validators;
1484
1604
  loader.__id = id;
1605
+ loader.__serializationStrategy = serializationStrategy;
1485
1606
  Object.freeze(loader);
1486
1607
  return loader;
1487
1608
  };
@@ -1586,7 +1707,7 @@ const zodQrl = (qrl) => {
1586
1707
  }
1587
1708
  });
1588
1709
  const data = inputData ?? await ev.parseBody();
1589
- const result = await schema.safeParseAsync(data);
1710
+ const result = await withLocale(ev.locale(), () => schema.safeParseAsync(data));
1590
1711
  if (result.success) {
1591
1712
  return result;
1592
1713
  } else {
@@ -1671,7 +1792,7 @@ const serverQrl = (qrl, options) => {
1671
1792
  const res = await fetch(`${origin}?${QFN_KEY}=${qrlHash}${query}`, config);
1672
1793
  const contentType = res.headers.get("Content-Type");
1673
1794
  if (res.ok && contentType === "text/qwik-json-stream" && res.body) {
1674
- return async function* () {
1795
+ return (async function* () {
1675
1796
  try {
1676
1797
  for await (const result of deserializeStream(res.body, ctxElm ?? document.documentElement, abortSignal)) {
1677
1798
  yield result;
@@ -1681,7 +1802,7 @@ const serverQrl = (qrl, options) => {
1681
1802
  await res.body.cancel();
1682
1803
  }
1683
1804
  }
1684
- }();
1805
+ })();
1685
1806
  } else if (contentType === "application/qwik-json") {
1686
1807
  const str = await res.text();
1687
1808
  const [obj] = _deserialize(str, ctxElm ?? document.documentElement);
@@ -1710,6 +1831,7 @@ const serverQrl = (qrl, options) => {
1710
1831
  const server$ = /* @__PURE__ */ implicit$FirstArg(serverQrl);
1711
1832
  const getValidators = (rest, qrl) => {
1712
1833
  let id;
1834
+ let serializationStrategy = DEFAULT_LOADERS_SERIALIZATION_STRATEGY;
1713
1835
  const validators = [];
1714
1836
  if (rest.length === 1) {
1715
1837
  const options = rest[0];
@@ -1718,6 +1840,9 @@ const getValidators = (rest, qrl) => {
1718
1840
  validators.push(options);
1719
1841
  } else {
1720
1842
  id = options.id;
1843
+ if (options.serializationStrategy) {
1844
+ serializationStrategy = options.serializationStrategy;
1845
+ }
1721
1846
  if (options.validation) {
1722
1847
  validators.push(...options.validation);
1723
1848
  }
@@ -1738,7 +1863,8 @@ const getValidators = (rest, qrl) => {
1738
1863
  }
1739
1864
  return {
1740
1865
  validators: validators.reverse(),
1741
- id
1866
+ id,
1867
+ serializationStrategy
1742
1868
  };
1743
1869
  };
1744
1870
  const deserializeStream = async function* (stream, ctxElm, abortSignal) {
@@ -1890,7 +2016,52 @@ function omitProps(obj, keys) {
1890
2016
  }
1891
2017
  return omittedObj;
1892
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
+ });
1893
2063
  export {
2064
+ DocumentHeadTags,
1894
2065
  ErrorBoundary,
1895
2066
  Form,
1896
2067
  Link,
@@ -1902,6 +2073,7 @@ export {
1902
2073
  QwikRouterProvider,
1903
2074
  RouterOutlet,
1904
2075
  ServiceWorkerRegister,
2076
+ createRenderer,
1905
2077
  globalAction$,
1906
2078
  globalActionQrl,
1907
2079
  omitProps,
@@ -1918,6 +2090,7 @@ export {
1918
2090
  useNavigate,
1919
2091
  usePreventNavigate$,
1920
2092
  usePreventNavigateQrl,
2093
+ useQwikRouter,
1921
2094
  valibot$,
1922
2095
  valibotQrl,
1923
2096
  validator$,