@bleedingdev/modern-js-renderer-solid 0.0.0-stage → 3.9.3-ultramodern.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 (301) hide show
  1. package/dist/esm/actions.js +282 -0
  2. package/dist/esm/application-router.js +30 -0
  3. package/dist/esm/client.js +49 -0
  4. package/dist/esm/entry-application.js +60 -0
  5. package/dist/esm/entry-client.js +24 -0
  6. package/dist/esm/federation-context.js +25 -0
  7. package/dist/esm/federation-ssr.js +92 -0
  8. package/dist/esm/federation.js +87 -0
  9. package/dist/esm/i18n/I18nProvider.js +33 -0
  10. package/dist/esm/i18n/LocalizedLink.js +52 -0
  11. package/dist/esm/i18n/context.js +3 -0
  12. package/dist/esm/i18n/index.js +8 -0
  13. package/dist/esm/i18n/languageSync.js +50 -0
  14. package/dist/esm/i18n/types.js +0 -0
  15. package/dist/esm/i18n/useI18n.js +74 -0
  16. package/dist/esm/index.js +58 -0
  17. package/dist/esm/manifest.js +150 -0
  18. package/dist/esm/route-completion.js +151 -0
  19. package/dist/esm/route-data-error.js +108 -0
  20. package/dist/esm/router-binding/Asset.js +202 -0
  21. package/dist/esm/router-binding/CatchBoundary.js +94 -0
  22. package/dist/esm/router-binding/ClientOnly.js +26 -0
  23. package/dist/esm/router-binding/HeadContent.js +8 -0
  24. package/dist/esm/router-binding/LICENSE +21 -0
  25. package/dist/esm/router-binding/Match.js +319 -0
  26. package/dist/esm/router-binding/Matches.js +124 -0
  27. package/dist/esm/router-binding/PROVENANCE.json +94 -0
  28. package/dist/esm/router-binding/RouterProvider.js +52 -0
  29. package/dist/esm/router-binding/SafeFragment.js +5 -0
  30. package/dist/esm/router-binding/ScriptOnce.js +15 -0
  31. package/dist/esm/router-binding/Scripts.js +30 -0
  32. package/dist/esm/router-binding/ScrollRestoration.js +16 -0
  33. package/dist/esm/router-binding/Transitioner.js +109 -0
  34. package/dist/esm/router-binding/awaited.js +48 -0
  35. package/dist/esm/router-binding/fileRoute.js +83 -0
  36. package/dist/esm/router-binding/flightData.js +23 -0
  37. package/dist/esm/router-binding/headContentUtils.js +168 -0
  38. package/dist/esm/router-binding/history.js +0 -0
  39. package/dist/esm/router-binding/index.js +35 -0
  40. package/dist/esm/router-binding/lazyRouteComponent.js +30 -0
  41. package/dist/esm/router-binding/link.js +387 -0
  42. package/dist/esm/router-binding/matchContext.js +7 -0
  43. package/dist/esm/router-binding/nonRouteComponentContext.js +13 -0
  44. package/dist/esm/router-binding/not-found.js +35 -0
  45. package/dist/esm/router-binding/publicMatchData.js +447 -0
  46. package/dist/esm/router-binding/registryTransfer.js +223 -0
  47. package/dist/esm/router-binding/renderRouteNotFound.js +23 -0
  48. package/dist/esm/router-binding/route.js +143 -0
  49. package/dist/esm/router-binding/router.js +14 -0
  50. package/dist/esm/router-binding/routerContext.js +3 -0
  51. package/dist/esm/router-binding/routerOptions.js +0 -0
  52. package/dist/esm/router-binding/routerStores.js +50 -0
  53. package/dist/esm/router-binding/scroll-restoration.js +13 -0
  54. package/dist/esm/router-binding/typePrimitives.js +0 -0
  55. package/dist/esm/router-binding/useBlocker.js +152 -0
  56. package/dist/esm/router-binding/useCanGoBack.js +7 -0
  57. package/dist/esm/router-binding/useLoaderData.js +8 -0
  58. package/dist/esm/router-binding/useLoaderDeps.js +8 -0
  59. package/dist/esm/router-binding/useLocation.js +14 -0
  60. package/dist/esm/router-binding/useMatch.js +28 -0
  61. package/dist/esm/router-binding/useNavigate.js +25 -0
  62. package/dist/esm/router-binding/useParams.js +11 -0
  63. package/dist/esm/router-binding/useRouteContext.js +8 -0
  64. package/dist/esm/router-binding/useRouter.js +10 -0
  65. package/dist/esm/router-binding/useRouterState.js +19 -0
  66. package/dist/esm/router-binding/useSearch.js +11 -0
  67. package/dist/esm/router-binding/utils.js +23 -0
  68. package/dist/esm/router.js +187 -0
  69. package/dist/esm-node/actions.js +263 -0
  70. package/dist/esm-node/application-router.js +30 -0
  71. package/dist/esm-node/client.js +49 -0
  72. package/dist/esm-node/entry-application.js +110 -0
  73. package/dist/esm-node/entry-client.js +24 -0
  74. package/dist/esm-node/entry-server.js +47 -0
  75. package/dist/esm-node/federation-context.js +25 -0
  76. package/dist/esm-node/federation-ssr.js +92 -0
  77. package/dist/esm-node/federation.js +87 -0
  78. package/dist/esm-node/i18n/I18nProvider.js +42 -0
  79. package/dist/esm-node/i18n/LocalizedLink.js +88 -0
  80. package/dist/esm-node/i18n/context.js +3 -0
  81. package/dist/esm-node/i18n/index.js +8 -0
  82. package/dist/esm-node/i18n/languageSync.js +50 -0
  83. package/dist/esm-node/i18n/types.js +1 -0
  84. package/dist/esm-node/i18n/useI18n.js +74 -0
  85. package/dist/esm-node/index.js +58 -0
  86. package/dist/esm-node/manifest.js +150 -0
  87. package/dist/esm-node/native-promise-serialization.js +113 -0
  88. package/dist/esm-node/plugin/compiler.js +209 -0
  89. package/dist/esm-node/plugin/create.js +236 -0
  90. package/dist/esm-node/plugin/index.js +70 -0
  91. package/dist/esm-node/plugin/profile.js +51 -0
  92. package/dist/esm-node/route-completion.js +161 -0
  93. package/dist/esm-node/route-data-error.js +108 -0
  94. package/dist/esm-node/router-binding/Asset.js +172 -0
  95. package/dist/esm-node/router-binding/CatchBoundary.js +136 -0
  96. package/dist/esm-node/router-binding/ClientOnly.js +46 -0
  97. package/dist/esm-node/router-binding/HeadContent.js +8 -0
  98. package/dist/esm-node/router-binding/LICENSE +21 -0
  99. package/dist/esm-node/router-binding/Match.js +660 -0
  100. package/dist/esm-node/router-binding/Matches.js +161 -0
  101. package/dist/esm-node/router-binding/PROVENANCE.json +94 -0
  102. package/dist/esm-node/router-binding/RouterProvider.js +88 -0
  103. package/dist/esm-node/router-binding/SafeFragment.js +5 -0
  104. package/dist/esm-node/router-binding/ScriptOnce.js +16 -0
  105. package/dist/esm-node/router-binding/Scripts.js +49 -0
  106. package/dist/esm-node/router-binding/ScrollRestoration.js +16 -0
  107. package/dist/esm-node/router-binding/Transitioner.js +109 -0
  108. package/dist/esm-node/router-binding/awaited.js +75 -0
  109. package/dist/esm-node/router-binding/fileRoute.js +83 -0
  110. package/dist/esm-node/router-binding/flightData.js +23 -0
  111. package/dist/esm-node/router-binding/headContentUtils.js +168 -0
  112. package/dist/esm-node/router-binding/history.js +1 -0
  113. package/dist/esm-node/router-binding/index.js +35 -0
  114. package/dist/esm-node/router-binding/lazyRouteComponent.js +30 -0
  115. package/dist/esm-node/router-binding/link.js +399 -0
  116. package/dist/esm-node/router-binding/matchContext.js +7 -0
  117. package/dist/esm-node/router-binding/nonRouteComponentContext.js +22 -0
  118. package/dist/esm-node/router-binding/not-found.js +49 -0
  119. package/dist/esm-node/router-binding/publicMatchData.js +447 -0
  120. package/dist/esm-node/router-binding/registryTransfer.js +223 -0
  121. package/dist/esm-node/router-binding/renderRouteNotFound.js +22 -0
  122. package/dist/esm-node/router-binding/route.js +162 -0
  123. package/dist/esm-node/router-binding/router.js +14 -0
  124. package/dist/esm-node/router-binding/routerContext.js +3 -0
  125. package/dist/esm-node/router-binding/routerOptions.js +1 -0
  126. package/dist/esm-node/router-binding/routerStores.js +50 -0
  127. package/dist/esm-node/router-binding/scroll-restoration.js +12 -0
  128. package/dist/esm-node/router-binding/typePrimitives.js +1 -0
  129. package/dist/esm-node/router-binding/useBlocker.js +152 -0
  130. package/dist/esm-node/router-binding/useCanGoBack.js +7 -0
  131. package/dist/esm-node/router-binding/useLoaderData.js +8 -0
  132. package/dist/esm-node/router-binding/useLoaderDeps.js +8 -0
  133. package/dist/esm-node/router-binding/useLocation.js +14 -0
  134. package/dist/esm-node/router-binding/useMatch.js +28 -0
  135. package/dist/esm-node/router-binding/useNavigate.js +25 -0
  136. package/dist/esm-node/router-binding/useParams.js +11 -0
  137. package/dist/esm-node/router-binding/useRouteContext.js +8 -0
  138. package/dist/esm-node/router-binding/useRouter.js +10 -0
  139. package/dist/esm-node/router-binding/useRouterState.js +19 -0
  140. package/dist/esm-node/router-binding/useSearch.js +11 -0
  141. package/dist/esm-node/router-binding/utils.js +23 -0
  142. package/dist/esm-node/router.js +187 -0
  143. package/dist/esm-node/server.js +396 -0
  144. package/dist/types/actions.d.ts +45 -0
  145. package/dist/types/application-router.d.ts +5 -0
  146. package/dist/types/client.d.ts +23 -0
  147. package/dist/types/entry-application.d.ts +10 -0
  148. package/dist/types/entry-client.d.ts +5 -0
  149. package/dist/types/entry-server.d.ts +5 -0
  150. package/dist/types/federation-context.d.ts +16 -0
  151. package/dist/types/federation-ssr.d.ts +19 -0
  152. package/dist/types/federation.d.ts +30 -0
  153. package/dist/types/i18n/I18nProvider.d.ts +21 -0
  154. package/dist/types/i18n/LocalizedLink.d.ts +15 -0
  155. package/dist/types/i18n/context.d.ts +11 -0
  156. package/dist/types/i18n/index.d.ts +9 -0
  157. package/dist/types/i18n/languageSync.d.ts +31 -0
  158. package/dist/types/i18n/types.d.ts +33 -0
  159. package/dist/types/i18n/useI18n.d.ts +24 -0
  160. package/dist/types/index.d.ts +41 -0
  161. package/dist/types/manifest.d.ts +55 -0
  162. package/dist/types/native-promise-serialization.d.ts +9 -0
  163. package/dist/types/plugin/compiler.d.ts +6 -0
  164. package/dist/types/plugin/create.d.ts +21 -0
  165. package/dist/types/plugin/index.d.ts +3 -0
  166. package/dist/types/plugin/lazy-modules.d.cts +15 -0
  167. package/dist/types/plugin/preserve-import-loader.d.cts +3 -0
  168. package/dist/types/plugin/profile.d.ts +2 -0
  169. package/dist/types/plugin/solid-loader.d.cts +2 -0
  170. package/dist/types/plugin/svg-component-template.d.cts +6 -0
  171. package/dist/types/route-completion.d.ts +21 -0
  172. package/dist/types/route-data-error.d.ts +17 -0
  173. package/dist/types/router-binding/Asset.d.ts +3 -0
  174. package/dist/types/router-binding/CatchBoundary.d.ts +13 -0
  175. package/dist/types/router-binding/ClientOnly.d.ts +31 -0
  176. package/dist/types/router-binding/HeadContent.d.ts +13 -0
  177. package/dist/types/router-binding/Match.d.ts +6 -0
  178. package/dist/types/router-binding/Matches.d.ts +26 -0
  179. package/dist/types/router-binding/RouterProvider.d.ts +11 -0
  180. package/dist/types/router-binding/SafeFragment.d.ts +2 -0
  181. package/dist/types/router-binding/ScriptOnce.d.ts +6 -0
  182. package/dist/types/router-binding/Scripts.d.ts +2 -0
  183. package/dist/types/router-binding/ScrollRestoration.d.ts +14 -0
  184. package/dist/types/router-binding/Transitioner.d.ts +2 -0
  185. package/dist/types/router-binding/awaited.d.ts +11 -0
  186. package/dist/types/router-binding/fileRoute.d.ts +54 -0
  187. package/dist/types/router-binding/flightData.d.ts +38 -0
  188. package/dist/types/router-binding/headContentUtils.d.ts +15 -0
  189. package/dist/types/router-binding/history.d.ts +8 -0
  190. package/dist/types/router-binding/index.d.ts +46 -0
  191. package/dist/types/router-binding/lazyRouteComponent.d.ts +2 -0
  192. package/dist/types/router-binding/link.d.ts +43 -0
  193. package/dist/types/router-binding/matchContext.d.ts +7 -0
  194. package/dist/types/router-binding/nonRouteComponentContext.d.ts +5 -0
  195. package/dist/types/router-binding/not-found.d.ts +11 -0
  196. package/dist/types/router-binding/publicMatchData.d.ts +19 -0
  197. package/dist/types/router-binding/registryTransfer.d.ts +49 -0
  198. package/dist/types/router-binding/renderRouteNotFound.d.ts +11 -0
  199. package/dist/types/router-binding/route.d.ts +105 -0
  200. package/dist/types/router-binding/router.d.ts +70 -0
  201. package/dist/types/router-binding/routerContext.d.ts +3 -0
  202. package/dist/types/router-binding/routerOptions.d.ts +6 -0
  203. package/dist/types/router-binding/routerStores.d.ts +2 -0
  204. package/dist/types/router-binding/scroll-restoration.d.ts +2 -0
  205. package/dist/types/router-binding/typePrimitives.d.ts +10 -0
  206. package/dist/types/router-binding/useBlocker.d.ts +70 -0
  207. package/dist/types/router-binding/useCanGoBack.d.ts +2 -0
  208. package/dist/types/router-binding/useLoaderData.d.ts +8 -0
  209. package/dist/types/router-binding/useLoaderDeps.d.ts +8 -0
  210. package/dist/types/router-binding/useLocation.d.ts +7 -0
  211. package/dist/types/router-binding/useMatch.d.ts +10 -0
  212. package/dist/types/router-binding/useNavigate.d.ts +5 -0
  213. package/dist/types/router-binding/useParams.d.ts +9 -0
  214. package/dist/types/router-binding/useRouteContext.d.ts +4 -0
  215. package/dist/types/router-binding/useRouter.d.ts +4 -0
  216. package/dist/types/router-binding/useRouterState.d.ts +8 -0
  217. package/dist/types/router-binding/useSearch.d.ts +9 -0
  218. package/dist/types/router-binding/utils.d.ts +25 -0
  219. package/dist/types/router.d.ts +31 -0
  220. package/dist/types/server.d.ts +47 -0
  221. package/package.json +130 -4
  222. package/src/actions.tsx +441 -0
  223. package/src/application-router.tsx +47 -0
  224. package/src/client.ts +106 -0
  225. package/src/entry-application.tsx +73 -0
  226. package/src/entry-client.tsx +49 -0
  227. package/src/entry-server.tsx +85 -0
  228. package/src/federation-context.ts +47 -0
  229. package/src/federation-ssr.ts +136 -0
  230. package/src/federation.tsx +197 -0
  231. package/src/i18n/I18nProvider.tsx +54 -0
  232. package/src/i18n/LocalizedLink.tsx +83 -0
  233. package/src/i18n/context.ts +13 -0
  234. package/src/i18n/index.ts +31 -0
  235. package/src/i18n/languageSync.ts +113 -0
  236. package/src/i18n/types.ts +35 -0
  237. package/src/i18n/useI18n.ts +121 -0
  238. package/src/index.ts +41 -0
  239. package/src/manifest.ts +337 -0
  240. package/src/native-promise-serialization.ts +167 -0
  241. package/src/plugin/compiler.ts +320 -0
  242. package/src/plugin/create.ts +271 -0
  243. package/src/plugin/index.ts +69 -0
  244. package/src/plugin/lazy-modules.cjs +146 -0
  245. package/src/plugin/preserve-import-loader.cjs +46 -0
  246. package/src/plugin/profile.ts +42 -0
  247. package/src/plugin/solid-loader.cjs +83 -0
  248. package/src/plugin/svg-component-template.cjs +19 -0
  249. package/src/route-completion.tsx +226 -0
  250. package/src/route-data-error.ts +175 -0
  251. package/src/router-binding/Asset.tsx +284 -0
  252. package/src/router-binding/CatchBoundary.tsx +130 -0
  253. package/src/router-binding/ClientOnly.tsx +76 -0
  254. package/src/router-binding/HeadContent.tsx +23 -0
  255. package/src/router-binding/LICENSE +21 -0
  256. package/src/router-binding/Match.tsx +397 -0
  257. package/src/router-binding/Matches.tsx +242 -0
  258. package/src/router-binding/PROVENANCE.json +94 -0
  259. package/src/router-binding/RouterProvider.tsx +128 -0
  260. package/src/router-binding/SafeFragment.tsx +5 -0
  261. package/src/router-binding/ScriptOnce.tsx +23 -0
  262. package/src/router-binding/Scripts.tsx +44 -0
  263. package/src/router-binding/ScrollRestoration.tsx +49 -0
  264. package/src/router-binding/Transitioner.tsx +177 -0
  265. package/src/router-binding/awaited.tsx +71 -0
  266. package/src/router-binding/fileRoute.ts +268 -0
  267. package/src/router-binding/flightData.ts +90 -0
  268. package/src/router-binding/headContentUtils.tsx +292 -0
  269. package/src/router-binding/history.ts +9 -0
  270. package/src/router-binding/index.tsx +315 -0
  271. package/src/router-binding/lazyRouteComponent.tsx +70 -0
  272. package/src/router-binding/link.tsx +865 -0
  273. package/src/router-binding/matchContext.tsx +15 -0
  274. package/src/router-binding/nonRouteComponentContext.tsx +23 -0
  275. package/src/router-binding/not-found.tsx +65 -0
  276. package/src/router-binding/publicMatchData.ts +674 -0
  277. package/src/router-binding/registryTransfer.ts +400 -0
  278. package/src/router-binding/renderRouteNotFound.tsx +53 -0
  279. package/src/router-binding/route.tsx +665 -0
  280. package/src/router-binding/router.ts +123 -0
  281. package/src/router-binding/routerContext.tsx +6 -0
  282. package/src/router-binding/routerOptions.ts +26 -0
  283. package/src/router-binding/routerStores.ts +85 -0
  284. package/src/router-binding/scroll-restoration.tsx +15 -0
  285. package/src/router-binding/typePrimitives.ts +74 -0
  286. package/src/router-binding/useBlocker.tsx +359 -0
  287. package/src/router-binding/useCanGoBack.ts +9 -0
  288. package/src/router-binding/useLoaderData.tsx +51 -0
  289. package/src/router-binding/useLoaderDeps.tsx +46 -0
  290. package/src/router-binding/useLocation.tsx +43 -0
  291. package/src/router-binding/useMatch.tsx +111 -0
  292. package/src/router-binding/useNavigate.tsx +45 -0
  293. package/src/router-binding/useParams.tsx +70 -0
  294. package/src/router-binding/useRouteContext.ts +30 -0
  295. package/src/router-binding/useRouter.tsx +17 -0
  296. package/src/router-binding/useRouterState.tsx +50 -0
  297. package/src/router-binding/useSearch.tsx +70 -0
  298. package/src/router-binding/utils.ts +59 -0
  299. package/src/router.ts +376 -0
  300. package/src/server.ts +645 -0
  301. package/README.md +0 -3
@@ -0,0 +1,400 @@
1
+ import { DataProtocolError } from '@modern-js/renderer-core/data';
2
+ import type { RequestSession } from '@modern-js/renderer-core/session';
3
+ import {
4
+ getHydrationWriter,
5
+ getRequestEvent,
6
+ takeHydrationValue,
7
+ } from '@solidjs/web';
8
+ import type { AnyRouteMatch, AnyRouter } from '@tanstack/router-core';
9
+ import * as Solid from 'solid-js';
10
+ import { restoreRouteDataError } from '../route-data-error';
11
+ import {
12
+ type PublicSnapshotOwner,
13
+ prepareHydratedLoaderData,
14
+ preparePublicContextData,
15
+ preparePublicLoaderData,
16
+ preparePublicMatchError,
17
+ preparePublishedRouteContext,
18
+ } from './publicMatchData';
19
+
20
+ /**
21
+ * Match-state transfer over Solid's hydration registry — the bare pairing's
22
+ * native SSR channel (no `__TSR_SSR__` script injection, no router-owned
23
+ * stream protocol). Entries are content-addressed (`tsr:<matchId>`; match
24
+ * ids are deterministic route-id + interpolated params, so both sides
25
+ * derive the same key from the same URL), the identical mechanism
26
+ * solid-query v6 ships query payloads through (`sq:<queryHash>`).
27
+ *
28
+ * Server half: while the render's serialization context is live, the
29
+ * provider writes each settled match's transferable state. Client half: the
30
+ * hydration-claiming boot — matching is synchronous, so the provider primes
31
+ * match state from the registry and commits before rendering, without
32
+ * running loaders or resolving route chunks up front. Route components
33
+ * resolve at the read point under the boundaries the server actually
34
+ * rendered (Solid `lazy` semantics), and staleness rules own any
35
+ * post-hydration refetching.
36
+ *
37
+ * Both halves no-op under TanStack Start: `router.serverSsr` marks the
38
+ * Start contract (`attachRouterServerSsrUtils` / `dehydrate` / `hydrate`),
39
+ * which owns transfer there — and a Start-hydrated router reaches the
40
+ * client boot with matches already committed, which skips it.
41
+ */
42
+ export const MATCH_KEY_PREFIX = 'tsr:';
43
+
44
+ /** The slice of a match that transfers; mirrors the single-flight match
45
+ * shape (`createSolidStartFlightMatch`) — state, not identity: the client
46
+ * re-derives identity by matching, then merges this in. */
47
+ interface TransferredMatch {
48
+ status: AnyRouteMatch['status'];
49
+ updatedAt: number;
50
+ loaderData?: unknown;
51
+ error?: unknown;
52
+ notFound?: true;
53
+ ssr?: AnyRouteMatch['ssr'];
54
+ beforeLoadContext?: Record<string, unknown>;
55
+ }
56
+
57
+ const preparedTransfers = new WeakMap<
58
+ RequestSession,
59
+ WeakMap<AnyRouter, Map<string, TransferredMatch>>
60
+ >();
61
+ const publicRouteDataOwners = new WeakMap<
62
+ object,
63
+ {
64
+ owner: WeakRef<PublicSnapshotOwner>;
65
+ privateContexts: Array<WeakRef<object>>;
66
+ }
67
+ >();
68
+
69
+ /** Bind the managed public-data scope before native router construction claims hydration. */
70
+ export function registerPublicRouteDataOwner(
71
+ routeTree: object,
72
+ owner: PublicSnapshotOwner,
73
+ privateContexts: readonly object[] = [],
74
+ ): void {
75
+ publicRouteDataOwners.set(routeTree, {
76
+ owner: new WeakRef(owner),
77
+ privateContexts: privateContexts.map(value => new WeakRef(value)),
78
+ });
79
+ }
80
+
81
+ /** Managed match transfer uses the immutable public-data contract, not custom adapters. */
82
+ export function assertNativeSerializationOptions(options: object): void {
83
+ if ('serializationAdapters' in options) {
84
+ const error = new DataProtocolError(
85
+ 'Solid serializationAdapters are unsupported by the immutable public-data profile; return public records, arrays and scalars instead',
86
+ );
87
+ const owner: RequestSession | undefined = getRequestEvent()?.locals.session;
88
+ owner?.fail(error);
89
+ throw error;
90
+ }
91
+ }
92
+
93
+ /** Framework SSR accepts only routers that passed its public-data factory boundary. */
94
+ export function requireManagedPublicRouter(router: AnyRouter): void {
95
+ assertNativeSerializationOptions(router.options);
96
+ const owner: RequestSession | undefined = getRequestEvent()?.locals.session;
97
+ if (
98
+ !owner ||
99
+ publicRouteDataOwners.get(router.options.routeTree)?.owner.deref()
100
+ )
101
+ return;
102
+ const error = new DataProtocolError(
103
+ 'Custom native Solid routers are unsupported by UltraModern SSR. Use the managed filesystem route tree and application router public-data boundary.',
104
+ );
105
+ owner.fail(error);
106
+ throw error;
107
+ }
108
+
109
+ /** Project composed public context before every native match-store publication. */
110
+ export function installPublicContextPublication(router: AnyRouter): void {
111
+ const scope = publicRouteDataOwners.get(router.options.routeTree);
112
+ const owner = scope?.owner.deref();
113
+ if (!scope || !owner) return;
114
+ const publish = router.stores.setMatches;
115
+ router.stores.setMatches = matches => {
116
+ try {
117
+ const privateContexts = scope.privateContexts.flatMap(reference => {
118
+ const value = reference.deref();
119
+ return value ? [value] : [];
120
+ });
121
+ preparePublishedMatches(matches, owner, privateContexts);
122
+ } catch (error) {
123
+ owner.fail(error);
124
+ throw error;
125
+ }
126
+ publish(matches);
127
+ };
128
+ }
129
+
130
+ function preparePublishedMatches(
131
+ matches: readonly AnyRouteMatch[],
132
+ owner: PublicSnapshotOwner,
133
+ privateContexts: readonly unknown[],
134
+ ): void {
135
+ // Check the complete offered chain before native publication updates IDs.
136
+ for (const match of matches)
137
+ preparePublicContextData(match.context, owner, privateContexts);
138
+ for (const match of matches)
139
+ preparePublishedRouteContext(match.context, owner, privateContexts);
140
+ }
141
+
142
+ function prepareEntries(
143
+ router: AnyRouter,
144
+ owner?: RequestSession,
145
+ privateContexts: readonly unknown[] = [],
146
+ ): Map<string, TransferredMatch> {
147
+ const entries = new Map<string, TransferredMatch>();
148
+ const matches = router.stores.matches.get();
149
+ const contexts = privateContexts;
150
+ for (const match of matches) {
151
+ if (match.status === 'pending') continue;
152
+ const entry: TransferredMatch = {
153
+ status: match.status,
154
+ updatedAt: match.updatedAt,
155
+ };
156
+ if (match.loaderData !== undefined)
157
+ entry.loaderData = preparePublicLoaderData(
158
+ match.loaderData,
159
+ owner,
160
+ contexts,
161
+ );
162
+ if (match.error !== undefined)
163
+ entry.error = preparePublicMatchError(match.error, owner, contexts);
164
+ const beforeLoadContext = nativeContextField(match, '__beforeLoadContext');
165
+ if (beforeLoadContext !== undefined)
166
+ entry.beforeLoadContext = preparePublicContextData(
167
+ beforeLoadContext,
168
+ owner,
169
+ contexts,
170
+ ) as Record<string, unknown>;
171
+ if (match._notFound) entry.notFound = true;
172
+ if (match.ssr !== undefined) entry.ssr = match.ssr;
173
+ entries.set(match.id, entry);
174
+ }
175
+ return entries;
176
+ }
177
+
178
+ /** Validate and capture native settled match state before a response is committed. */
179
+ export function prepareRouterMatchTransfer(
180
+ router: AnyRouter,
181
+ owner: RequestSession,
182
+ privateContexts: readonly unknown[] = [],
183
+ ): void {
184
+ try {
185
+ const entries = prepareEntries(router, owner, privateContexts);
186
+ let routers = preparedTransfers.get(owner);
187
+ if (!routers) {
188
+ routers = new WeakMap();
189
+ preparedTransfers.set(owner, routers);
190
+ }
191
+ routers.set(router, entries);
192
+ } catch (error) {
193
+ owner.fail(error);
194
+ throw error;
195
+ }
196
+ }
197
+
198
+ export function serializeMatchTransfer(router: AnyRouter): void {
199
+ requireManagedPublicRouter(router);
200
+ if (router.serverSsr) return;
201
+ const writer = getHydrationWriter();
202
+ if (!writer || !Solid.isHydratable()) return;
203
+
204
+ const owner: RequestSession | undefined = getRequestEvent()?.locals.session;
205
+ const entries =
206
+ (owner && preparedTransfers.get(owner)?.get(router)) ??
207
+ prepareEntries(router, owner);
208
+ for (const [id, entry] of entries) {
209
+ // Pending matches are skipped, not deferred: this core has no per-match
210
+ // settle promise to hand seroval, so promise-valued entries (streaming
211
+ // SSR, loaders landing after first flush) need a dispatch-time hook —
212
+ // the next increment. A missing entry makes the client boot fall
213
+ // through to today's behavior rather than half-prime.
214
+ writer.write(MATCH_KEY_PREFIX + id, entry);
215
+ }
216
+ }
217
+
218
+ /**
219
+ * The hydration-claiming boot. Returns true when every synchronously
220
+ * matched route found its registry entry and the matches were committed;
221
+ * false falls back to the caller's existing behavior (no entries — a
222
+ * non-registry server, `noHydrate`, or a pending match the server skipped).
223
+ *
224
+ * Entries arrive as inline scripts that execute at document parse, so they
225
+ * are readable through Solid's keyed value channel before client rendering.
226
+ * The boot commits before hydration; store writes inside the claim would
227
+ * change the owner tree being claimed.
228
+ */
229
+ export function primeRouterFromRegistry(router: AnyRouter): boolean {
230
+ if (router.stores.matches.get().length > 0) return false;
231
+ const registry = (
232
+ globalThis as unknown as { _$HY?: { r: Record<string, unknown> } }
233
+ )._$HY?.r;
234
+ if (!registry) return false;
235
+ // A page with no match entries (SPA, or Start's own channel) skips before
236
+ // paying for a match pass.
237
+ let hasMatchEntries = false;
238
+ for (const key in registry) {
239
+ if (key.startsWith(MATCH_KEY_PREFIX)) {
240
+ hasMatchEntries = true;
241
+ break;
242
+ }
243
+ }
244
+ if (!hasMatchEntries) return false;
245
+
246
+ const matches = router.matchRoutes(router.latestLocation);
247
+ if (matches.length === 0) return false;
248
+
249
+ const entries: Array<TransferredMatch> = [];
250
+ let complete = true;
251
+ for (const match of matches) {
252
+ const key = MATCH_KEY_PREFIX + match.id;
253
+ const transferred = takeHydrationValue<TransferredMatch>(key);
254
+ if (transferred?.status !== 'resolved') {
255
+ complete = false;
256
+ if (transferred?.status === 'pending')
257
+ void Promise.prototype.then.call(
258
+ transferred.promise,
259
+ undefined,
260
+ () => {},
261
+ );
262
+ continue;
263
+ }
264
+ const entry = transferred.value;
265
+ if (!entry || typeof entry.status !== 'string') {
266
+ complete = false;
267
+ continue;
268
+ }
269
+ entries.push(entry);
270
+ }
271
+ if (!complete) return false;
272
+
273
+ const primed: Array<AnyRouteMatch> = [];
274
+ const scope = publicRouteDataOwners.get(router.options.routeTree);
275
+ const owner = scope?.owner.deref();
276
+ const privateContexts =
277
+ scope?.privateContexts.flatMap(reference => {
278
+ const value = reference.deref();
279
+ return value ? [value] : [];
280
+ }) ?? [];
281
+ try {
282
+ for (const [index, match] of matches.entries()) {
283
+ const entry = entries[index]!;
284
+ const beforeLoadContext = preparePublicContextData(
285
+ entry.beforeLoadContext,
286
+ owner,
287
+ privateContexts,
288
+ ) as Record<string, unknown> | undefined;
289
+ const checked: TransferredMatch = {
290
+ ...entry,
291
+ loaderData: prepareHydratedLoaderData(
292
+ entry.loaderData,
293
+ owner,
294
+ privateContexts,
295
+ ),
296
+ ...(beforeLoadContext !== undefined ? { beforeLoadContext } : {}),
297
+ error: preparePublicContextData(entry.error, owner, privateContexts),
298
+ };
299
+ entries[index] = checked;
300
+ primed.push(applyTransferredMatch(match, checked));
301
+ }
302
+ for (const [index, next] of primed.entries()) {
303
+ const match = matches[index]!;
304
+ const route = router.routesById[match.routeId]!;
305
+ const parentContext =
306
+ primed[index - 1]?.context ?? router.options.context ?? {};
307
+ // This is the native core29 hydration context phase: reconstruct client
308
+ // route context, then inherit the explicit checked server beforeLoad value.
309
+ const routeContext =
310
+ route.options.context?.({
311
+ deps: match.loaderDeps,
312
+ params: match.params,
313
+ context: parentContext,
314
+ location: router.latestLocation,
315
+ navigate: (options: Parameters<typeof router.navigate>[0]) =>
316
+ router.navigate({
317
+ ...options,
318
+ _fromLocation: router.latestLocation,
319
+ }),
320
+ buildLocation: router.buildLocation,
321
+ cause: match.cause,
322
+ abortController: match.abortController,
323
+ preload: false,
324
+ matches: primed,
325
+ routeId: route.id,
326
+ }) || undefined;
327
+ Object.defineProperty(next, '_ctx', {
328
+ value: routeContext,
329
+ configurable: true,
330
+ writable: true,
331
+ enumerable: true,
332
+ });
333
+ next.context = {
334
+ ...parentContext,
335
+ ...routeContext,
336
+ ...entries[index]!.beforeLoadContext,
337
+ };
338
+ }
339
+ if (owner) preparePublishedMatches(primed, owner, privateContexts);
340
+ } catch (error) {
341
+ owner?.fail(error);
342
+ return false;
343
+ }
344
+
345
+ // Commit the way the single-flight client publishes hydrated matches.
346
+ router._committed = primed;
347
+ router.batch(() => {
348
+ router.stores.setMatches(primed);
349
+ router.stores.status.set('idle');
350
+ router.stores.resolvedLocation.set(router.stores.location.get());
351
+ });
352
+ return true;
353
+ }
354
+
355
+ function applyTransferredMatch(
356
+ match: AnyRouteMatch,
357
+ entry: TransferredMatch,
358
+ ): AnyRouteMatch {
359
+ const next = {
360
+ ...match,
361
+ status: entry.status,
362
+ updatedAt: entry.updatedAt,
363
+ error: isRouteDataErrorSnapshot(entry.error)
364
+ ? Object.freeze(restoreRouteDataError(entry.error))
365
+ : entry.error,
366
+ invalid: false,
367
+ isFetching: false,
368
+ preload: false,
369
+ _notFound: entry.notFound,
370
+ __beforeLoadContext: entry.beforeLoadContext,
371
+ } as AnyRouteMatch;
372
+ if ('loaderData' in entry) next.loaderData = entry.loaderData;
373
+ if ('ssr' in entry) {
374
+ if (entry.ssr === undefined) delete next.ssr;
375
+ else next.ssr = entry.ssr;
376
+ }
377
+ return next;
378
+ }
379
+
380
+ function isRouteDataErrorSnapshot(value: unknown): boolean {
381
+ return (
382
+ !!value &&
383
+ typeof value === 'object' &&
384
+ Object.getOwnPropertyDescriptor(value, 'kind')?.value ===
385
+ 'ultramodern-route-data-error'
386
+ );
387
+ }
388
+
389
+ /** Core strips these native hydration fields from its public declarations. */
390
+ function nativeContextField(
391
+ match: AnyRouteMatch,
392
+ key: '_ctx' | '__beforeLoadContext',
393
+ ): unknown {
394
+ const descriptor = Object.getOwnPropertyDescriptor(match, key);
395
+ if (descriptor?.get || descriptor?.set)
396
+ throw new DataProtocolError(
397
+ 'Native route context must not contain accessor fields',
398
+ );
399
+ return descriptor?.value;
400
+ }
@@ -0,0 +1,53 @@
1
+ import type { JSX } from '@solidjs/web';
2
+ import type { AnyRoute, AnyRouter } from '@tanstack/router-core';
3
+ import { renderInNonRouteComponentContext } from './nonRouteComponentContext';
4
+ import { DefaultGlobalNotFound } from './not-found';
5
+
6
+ /**
7
+ * Renders a not found component for a route when no matching route is found.
8
+ *
9
+ * @param router - The router instance containing the route configuration
10
+ * @param route - The route that triggered the not found state
11
+ * @param data - Additional data to pass to the not found component
12
+ * @returns The rendered not found component or a default fallback component
13
+ */
14
+ export function renderRouteNotFound(
15
+ router: AnyRouter,
16
+ route: AnyRoute,
17
+ data: any,
18
+ ): JSX.Element {
19
+ if (process.env.NODE_ENV !== 'production') {
20
+ if (!route.options.notFoundComponent) {
21
+ if (router.options.defaultNotFoundComponent) {
22
+ const DefaultNotFoundComponent =
23
+ router.options.defaultNotFoundComponent;
24
+ return renderInNonRouteComponentContext(
25
+ () => <DefaultNotFoundComponent {...data} />,
26
+ 'notFoundComponent',
27
+ );
28
+ }
29
+
30
+ console.warn(
31
+ `Warning: A notFoundError was encountered on the route with ID "${route.id}", but a notFoundComponent option was not configured, nor was a router level defaultNotFoundComponent configured. Consider configuring at least one of these to avoid TanStack Router's overly generic defaultNotFoundComponent (<p>Not Found</p>)`,
32
+ );
33
+
34
+ return <DefaultGlobalNotFound />;
35
+ }
36
+
37
+ const NotFoundComponent = route.options.notFoundComponent;
38
+ return renderInNonRouteComponentContext(
39
+ () => <NotFoundComponent {...data} />,
40
+ 'notFoundComponent',
41
+ );
42
+ }
43
+
44
+ if (!route.options.notFoundComponent) {
45
+ if (router.options.defaultNotFoundComponent) {
46
+ return <router.options.defaultNotFoundComponent {...data} />;
47
+ }
48
+
49
+ return <DefaultGlobalNotFound />;
50
+ }
51
+
52
+ return <route.options.notFoundComponent {...data} />;
53
+ }