@bleedingdev/modern-js-renderer-solid 0.0.0-stage → 3.9.3-ultramodern.2

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 (297) hide show
  1. package/dist/esm/actions.js +283 -0
  2. package/dist/esm/application-router.js +25 -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 +23 -0
  6. package/dist/esm/federation-context.js +25 -0
  7. package/dist/esm/federation-ssr.js +84 -0
  8. package/dist/esm/federation.js +83 -0
  9. package/dist/esm/i18n/I18nProvider.js +33 -0
  10. package/dist/esm/i18n/LocalizedLink.js +74 -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 +150 -0
  19. package/dist/esm/route-data-error.js +108 -0
  20. package/dist/esm/router-binding/Asset.js +201 -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 +117 -0
  27. package/dist/esm/router-binding/PROVENANCE.json +94 -0
  28. package/dist/esm/router-binding/RouterProvider.js +51 -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 +103 -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 +162 -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 +389 -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 +210 -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 +13 -0
  50. package/dist/esm/router-binding/routerContext.js +3 -0
  51. package/dist/esm/router-binding/routerStores.js +50 -0
  52. package/dist/esm/router-binding/scroll-restoration.js +13 -0
  53. package/dist/esm/router-binding/typePrimitives.js +0 -0
  54. package/dist/esm/router-binding/useBlocker.js +152 -0
  55. package/dist/esm/router-binding/useCanGoBack.js +7 -0
  56. package/dist/esm/router-binding/useLoaderData.js +9 -0
  57. package/dist/esm/router-binding/useLoaderDeps.js +8 -0
  58. package/dist/esm/router-binding/useLocation.js +14 -0
  59. package/dist/esm/router-binding/useMatch.js +28 -0
  60. package/dist/esm/router-binding/useNavigate.js +19 -0
  61. package/dist/esm/router-binding/useParams.js +13 -0
  62. package/dist/esm/router-binding/useRouteContext.js +8 -0
  63. package/dist/esm/router-binding/useRouter.js +10 -0
  64. package/dist/esm/router-binding/useRouterState.js +19 -0
  65. package/dist/esm/router-binding/useSearch.js +13 -0
  66. package/dist/esm/router-binding/utils.js +23 -0
  67. package/dist/esm/router.js +187 -0
  68. package/dist/esm-node/actions.js +263 -0
  69. package/dist/esm-node/application-router.js +25 -0
  70. package/dist/esm-node/client.js +49 -0
  71. package/dist/esm-node/entry-application.js +110 -0
  72. package/dist/esm-node/entry-client.js +23 -0
  73. package/dist/esm-node/entry-server.js +47 -0
  74. package/dist/esm-node/federation-context.js +25 -0
  75. package/dist/esm-node/federation-ssr.js +84 -0
  76. package/dist/esm-node/federation.js +83 -0
  77. package/dist/esm-node/i18n/I18nProvider.js +42 -0
  78. package/dist/esm-node/i18n/LocalizedLink.js +142 -0
  79. package/dist/esm-node/i18n/context.js +3 -0
  80. package/dist/esm-node/i18n/index.js +8 -0
  81. package/dist/esm-node/i18n/languageSync.js +50 -0
  82. package/dist/esm-node/i18n/types.js +1 -0
  83. package/dist/esm-node/i18n/useI18n.js +74 -0
  84. package/dist/esm-node/index.js +58 -0
  85. package/dist/esm-node/manifest.js +150 -0
  86. package/dist/esm-node/native-promise-serialization.js +113 -0
  87. package/dist/esm-node/plugin/compiler.js +209 -0
  88. package/dist/esm-node/plugin/create.js +235 -0
  89. package/dist/esm-node/plugin/index.js +73 -0
  90. package/dist/esm-node/plugin/profile.js +52 -0
  91. package/dist/esm-node/route-completion.js +160 -0
  92. package/dist/esm-node/route-data-error.js +108 -0
  93. package/dist/esm-node/router-binding/Asset.js +171 -0
  94. package/dist/esm-node/router-binding/CatchBoundary.js +136 -0
  95. package/dist/esm-node/router-binding/ClientOnly.js +46 -0
  96. package/dist/esm-node/router-binding/HeadContent.js +8 -0
  97. package/dist/esm-node/router-binding/LICENSE +21 -0
  98. package/dist/esm-node/router-binding/Match.js +660 -0
  99. package/dist/esm-node/router-binding/Matches.js +161 -0
  100. package/dist/esm-node/router-binding/PROVENANCE.json +94 -0
  101. package/dist/esm-node/router-binding/RouterProvider.js +87 -0
  102. package/dist/esm-node/router-binding/SafeFragment.js +5 -0
  103. package/dist/esm-node/router-binding/ScriptOnce.js +16 -0
  104. package/dist/esm-node/router-binding/Scripts.js +49 -0
  105. package/dist/esm-node/router-binding/ScrollRestoration.js +16 -0
  106. package/dist/esm-node/router-binding/Transitioner.js +103 -0
  107. package/dist/esm-node/router-binding/awaited.js +75 -0
  108. package/dist/esm-node/router-binding/fileRoute.js +83 -0
  109. package/dist/esm-node/router-binding/flightData.js +23 -0
  110. package/dist/esm-node/router-binding/headContentUtils.js +162 -0
  111. package/dist/esm-node/router-binding/history.js +1 -0
  112. package/dist/esm-node/router-binding/index.js +35 -0
  113. package/dist/esm-node/router-binding/lazyRouteComponent.js +30 -0
  114. package/dist/esm-node/router-binding/link.js +399 -0
  115. package/dist/esm-node/router-binding/matchContext.js +7 -0
  116. package/dist/esm-node/router-binding/nonRouteComponentContext.js +22 -0
  117. package/dist/esm-node/router-binding/not-found.js +49 -0
  118. package/dist/esm-node/router-binding/publicMatchData.js +447 -0
  119. package/dist/esm-node/router-binding/registryTransfer.js +210 -0
  120. package/dist/esm-node/router-binding/renderRouteNotFound.js +22 -0
  121. package/dist/esm-node/router-binding/route.js +162 -0
  122. package/dist/esm-node/router-binding/router.js +13 -0
  123. package/dist/esm-node/router-binding/routerContext.js +3 -0
  124. package/dist/esm-node/router-binding/routerStores.js +50 -0
  125. package/dist/esm-node/router-binding/scroll-restoration.js +12 -0
  126. package/dist/esm-node/router-binding/typePrimitives.js +1 -0
  127. package/dist/esm-node/router-binding/useBlocker.js +152 -0
  128. package/dist/esm-node/router-binding/useCanGoBack.js +7 -0
  129. package/dist/esm-node/router-binding/useLoaderData.js +9 -0
  130. package/dist/esm-node/router-binding/useLoaderDeps.js +8 -0
  131. package/dist/esm-node/router-binding/useLocation.js +14 -0
  132. package/dist/esm-node/router-binding/useMatch.js +28 -0
  133. package/dist/esm-node/router-binding/useNavigate.js +19 -0
  134. package/dist/esm-node/router-binding/useParams.js +13 -0
  135. package/dist/esm-node/router-binding/useRouteContext.js +8 -0
  136. package/dist/esm-node/router-binding/useRouter.js +10 -0
  137. package/dist/esm-node/router-binding/useRouterState.js +19 -0
  138. package/dist/esm-node/router-binding/useSearch.js +13 -0
  139. package/dist/esm-node/router-binding/utils.js +23 -0
  140. package/dist/esm-node/router.js +187 -0
  141. package/dist/esm-node/server.js +396 -0
  142. package/dist/types/actions.d.ts +45 -0
  143. package/dist/types/application-router.d.ts +5 -0
  144. package/dist/types/client.d.ts +23 -0
  145. package/dist/types/entry-application.d.ts +10 -0
  146. package/dist/types/entry-client.d.ts +5 -0
  147. package/dist/types/entry-server.d.ts +5 -0
  148. package/dist/types/federation-context.d.ts +16 -0
  149. package/dist/types/federation-ssr.d.ts +21 -0
  150. package/dist/types/federation.d.ts +30 -0
  151. package/dist/types/i18n/I18nProvider.d.ts +21 -0
  152. package/dist/types/i18n/LocalizedLink.d.ts +43 -0
  153. package/dist/types/i18n/context.d.ts +11 -0
  154. package/dist/types/i18n/index.d.ts +9 -0
  155. package/dist/types/i18n/languageSync.d.ts +31 -0
  156. package/dist/types/i18n/types.d.ts +33 -0
  157. package/dist/types/i18n/useI18n.d.ts +24 -0
  158. package/dist/types/index.d.ts +41 -0
  159. package/dist/types/manifest.d.ts +55 -0
  160. package/dist/types/native-promise-serialization.d.ts +9 -0
  161. package/dist/types/plugin/compiler.d.ts +6 -0
  162. package/dist/types/plugin/create.d.ts +21 -0
  163. package/dist/types/plugin/index.d.ts +3 -0
  164. package/dist/types/plugin/lazy-modules.d.cts +15 -0
  165. package/dist/types/plugin/preserve-import-loader.d.cts +3 -0
  166. package/dist/types/plugin/profile.d.ts +2 -0
  167. package/dist/types/plugin/solid-loader.d.cts +2 -0
  168. package/dist/types/plugin/svg-component-template.d.cts +6 -0
  169. package/dist/types/route-completion.d.ts +21 -0
  170. package/dist/types/route-data-error.d.ts +17 -0
  171. package/dist/types/router-binding/Asset.d.ts +3 -0
  172. package/dist/types/router-binding/CatchBoundary.d.ts +13 -0
  173. package/dist/types/router-binding/ClientOnly.d.ts +31 -0
  174. package/dist/types/router-binding/HeadContent.d.ts +13 -0
  175. package/dist/types/router-binding/Match.d.ts +6 -0
  176. package/dist/types/router-binding/Matches.d.ts +26 -0
  177. package/dist/types/router-binding/RouterProvider.d.ts +10 -0
  178. package/dist/types/router-binding/SafeFragment.d.ts +2 -0
  179. package/dist/types/router-binding/ScriptOnce.d.ts +6 -0
  180. package/dist/types/router-binding/Scripts.d.ts +2 -0
  181. package/dist/types/router-binding/ScrollRestoration.d.ts +14 -0
  182. package/dist/types/router-binding/Transitioner.d.ts +2 -0
  183. package/dist/types/router-binding/awaited.d.ts +11 -0
  184. package/dist/types/router-binding/fileRoute.d.ts +54 -0
  185. package/dist/types/router-binding/flightData.d.ts +38 -0
  186. package/dist/types/router-binding/headContentUtils.d.ts +15 -0
  187. package/dist/types/router-binding/history.d.ts +8 -0
  188. package/dist/types/router-binding/index.d.ts +45 -0
  189. package/dist/types/router-binding/lazyRouteComponent.d.ts +2 -0
  190. package/dist/types/router-binding/link.d.ts +43 -0
  191. package/dist/types/router-binding/matchContext.d.ts +7 -0
  192. package/dist/types/router-binding/nonRouteComponentContext.d.ts +5 -0
  193. package/dist/types/router-binding/not-found.d.ts +11 -0
  194. package/dist/types/router-binding/publicMatchData.d.ts +19 -0
  195. package/dist/types/router-binding/registryTransfer.d.ts +47 -0
  196. package/dist/types/router-binding/renderRouteNotFound.d.ts +11 -0
  197. package/dist/types/router-binding/route.d.ts +105 -0
  198. package/dist/types/router-binding/router.d.ts +70 -0
  199. package/dist/types/router-binding/routerContext.d.ts +3 -0
  200. package/dist/types/router-binding/routerStores.d.ts +2 -0
  201. package/dist/types/router-binding/scroll-restoration.d.ts +2 -0
  202. package/dist/types/router-binding/typePrimitives.d.ts +10 -0
  203. package/dist/types/router-binding/useBlocker.d.ts +70 -0
  204. package/dist/types/router-binding/useCanGoBack.d.ts +2 -0
  205. package/dist/types/router-binding/useLoaderData.d.ts +8 -0
  206. package/dist/types/router-binding/useLoaderDeps.d.ts +8 -0
  207. package/dist/types/router-binding/useLocation.d.ts +7 -0
  208. package/dist/types/router-binding/useMatch.d.ts +10 -0
  209. package/dist/types/router-binding/useNavigate.d.ts +5 -0
  210. package/dist/types/router-binding/useParams.d.ts +9 -0
  211. package/dist/types/router-binding/useRouteContext.d.ts +4 -0
  212. package/dist/types/router-binding/useRouter.d.ts +4 -0
  213. package/dist/types/router-binding/useRouterState.d.ts +8 -0
  214. package/dist/types/router-binding/useSearch.d.ts +9 -0
  215. package/dist/types/router-binding/utils.d.ts +25 -0
  216. package/dist/types/router.d.ts +31 -0
  217. package/dist/types/server.d.ts +47 -0
  218. package/package.json +123 -4
  219. package/src/actions.tsx +437 -0
  220. package/src/application-router.tsx +41 -0
  221. package/src/client.ts +106 -0
  222. package/src/entry-application.tsx +73 -0
  223. package/src/entry-client.tsx +48 -0
  224. package/src/entry-server.tsx +85 -0
  225. package/src/federation-context.ts +47 -0
  226. package/src/federation-ssr.ts +117 -0
  227. package/src/federation.tsx +193 -0
  228. package/src/i18n/I18nProvider.tsx +54 -0
  229. package/src/i18n/LocalizedLink.tsx +122 -0
  230. package/src/i18n/context.ts +13 -0
  231. package/src/i18n/index.ts +35 -0
  232. package/src/i18n/languageSync.ts +113 -0
  233. package/src/i18n/types.ts +35 -0
  234. package/src/i18n/useI18n.ts +121 -0
  235. package/src/index.ts +41 -0
  236. package/src/manifest.ts +337 -0
  237. package/src/native-promise-serialization.ts +167 -0
  238. package/src/plugin/compiler.ts +320 -0
  239. package/src/plugin/create.ts +270 -0
  240. package/src/plugin/index.ts +72 -0
  241. package/src/plugin/lazy-modules.cjs +146 -0
  242. package/src/plugin/preserve-import-loader.cjs +46 -0
  243. package/src/plugin/profile.ts +42 -0
  244. package/src/plugin/solid-loader.cjs +83 -0
  245. package/src/plugin/svg-component-template.cjs +19 -0
  246. package/src/route-completion.tsx +222 -0
  247. package/src/route-data-error.ts +175 -0
  248. package/src/router-binding/Asset.tsx +283 -0
  249. package/src/router-binding/CatchBoundary.tsx +130 -0
  250. package/src/router-binding/ClientOnly.tsx +76 -0
  251. package/src/router-binding/HeadContent.tsx +23 -0
  252. package/src/router-binding/LICENSE +21 -0
  253. package/src/router-binding/Match.tsx +397 -0
  254. package/src/router-binding/Matches.tsx +242 -0
  255. package/src/router-binding/PROVENANCE.json +94 -0
  256. package/src/router-binding/RouterProvider.tsx +129 -0
  257. package/src/router-binding/SafeFragment.tsx +5 -0
  258. package/src/router-binding/ScriptOnce.tsx +23 -0
  259. package/src/router-binding/Scripts.tsx +44 -0
  260. package/src/router-binding/ScrollRestoration.tsx +49 -0
  261. package/src/router-binding/Transitioner.tsx +172 -0
  262. package/src/router-binding/awaited.tsx +71 -0
  263. package/src/router-binding/fileRoute.ts +268 -0
  264. package/src/router-binding/flightData.ts +90 -0
  265. package/src/router-binding/headContentUtils.tsx +290 -0
  266. package/src/router-binding/history.ts +9 -0
  267. package/src/router-binding/index.tsx +318 -0
  268. package/src/router-binding/lazyRouteComponent.tsx +70 -0
  269. package/src/router-binding/link.tsx +865 -0
  270. package/src/router-binding/matchContext.tsx +15 -0
  271. package/src/router-binding/nonRouteComponentContext.tsx +23 -0
  272. package/src/router-binding/not-found.tsx +65 -0
  273. package/src/router-binding/publicMatchData.ts +674 -0
  274. package/src/router-binding/registryTransfer.ts +383 -0
  275. package/src/router-binding/renderRouteNotFound.tsx +53 -0
  276. package/src/router-binding/route.tsx +665 -0
  277. package/src/router-binding/router.ts +121 -0
  278. package/src/router-binding/routerContext.tsx +6 -0
  279. package/src/router-binding/routerStores.ts +85 -0
  280. package/src/router-binding/scroll-restoration.tsx +15 -0
  281. package/src/router-binding/typePrimitives.ts +74 -0
  282. package/src/router-binding/useBlocker.tsx +359 -0
  283. package/src/router-binding/useCanGoBack.ts +9 -0
  284. package/src/router-binding/useLoaderData.tsx +50 -0
  285. package/src/router-binding/useLoaderDeps.tsx +46 -0
  286. package/src/router-binding/useLocation.tsx +43 -0
  287. package/src/router-binding/useMatch.tsx +111 -0
  288. package/src/router-binding/useNavigate.tsx +43 -0
  289. package/src/router-binding/useParams.tsx +72 -0
  290. package/src/router-binding/useRouteContext.ts +30 -0
  291. package/src/router-binding/useRouter.tsx +17 -0
  292. package/src/router-binding/useRouterState.tsx +50 -0
  293. package/src/router-binding/useSearch.tsx +72 -0
  294. package/src/router-binding/utils.ts +59 -0
  295. package/src/router.ts +376 -0
  296. package/src/server.ts +645 -0
  297. package/README.md +0 -3
@@ -0,0 +1,172 @@
1
+ import type { AnyRouteMatch } from '@tanstack/router-core';
2
+ import { getLocationChangeInfo, trimPathRight } from '@tanstack/router-core';
3
+ import { isServer } from '@tanstack/router-core/isServer';
4
+ import type { NavigationRef } from 'solid-js';
5
+ import * as Solid from 'solid-js';
6
+ import { useRouter } from './useRouter';
7
+
8
+ /**
9
+ * Solid's observe tier (`OBSERVE` is defined on the dev and observe builds,
10
+ * undefined in production) attributes what the user waited on to the
11
+ * navigation that caused it. The rule for every router is the same: wrap the
12
+ * write whose landing is the destination showing, and pass `at` when the
13
+ * request predates that write. Here that write is the match publish inside
14
+ * `startTransition` — the loaders were awaited in router-core before it —
15
+ * so the ref names the destination route from the expected matches and
16
+ * dates from the history change that started the load. The pending offer
17
+ * (`offerPending`, a match with `status: 'pending'`) is not the destination
18
+ * and is published undeclared; the initial load and a same-location reload
19
+ * are not navigations.
20
+ */
21
+ function describeNavigation(
22
+ router: ReturnType<typeof useRouter>,
23
+ expected: Array<AnyRouteMatch>,
24
+ at: number | undefined,
25
+ ): NavigationRef | undefined {
26
+ if (expected.some(match => match.status === 'pending')) return;
27
+ const to = router.latestLocation;
28
+ const from = router.stores.resolvedLocation.get();
29
+ // Nothing shown yet (the initial load), or a reload of what is shown.
30
+ if (!from || from.href === to.href) return;
31
+ const leaf = expected[expected.length - 1];
32
+ const ref: NavigationRef = {
33
+ kind: 'navigation',
34
+ name: leaf?.fullPath || to.pathname,
35
+ to: to.pathname,
36
+ from: from.pathname,
37
+ };
38
+ if (leaf && Object.keys(leaf.params).length) ref.params = leaf.params;
39
+ if (at !== undefined) ref.at = at;
40
+ return ref;
41
+ }
42
+
43
+ function getResolvedLocation(router: ReturnType<typeof useRouter>) {
44
+ const resolvedLocation = router.stores.resolvedLocation.get();
45
+ if (
46
+ resolvedLocation?.href === router.latestLocation.href &&
47
+ resolvedLocation.state.__TSR_key === router.latestLocation.state.__TSR_key
48
+ ) {
49
+ return resolvedLocation;
50
+ }
51
+ return;
52
+ }
53
+
54
+ export function Transitioner() {
55
+ const router = useRouter();
56
+
57
+ type Ack = [
58
+ expected: Array<AnyRouteMatch>,
59
+ resolve: (rendered: boolean) => void,
60
+ ];
61
+ const acks: Array<Ack> = [];
62
+ let committed: Array<AnyRouteMatch> | undefined;
63
+
64
+ const isCommitted = (expected: Array<AnyRouteMatch>) =>
65
+ !!committed &&
66
+ committed.length === expected.length &&
67
+ expected.every((match, index) => committed![index] === match);
68
+
69
+ // When the history changed since the last declared publish: the moment
70
+ // the user asked, which is where the navigation's wait starts.
71
+ let requestedAt: number | undefined;
72
+
73
+ // Ack when the commit's transition settles (the atomic swap), not when the
74
+ // flush parks it; superseded or rolled-back commits resolve false.
75
+ router.startTransition = (fn, expectedMatches) => {
76
+ if (isServer ?? router.isServer) {
77
+ fn();
78
+ return Promise.resolve(true);
79
+ }
80
+ return new Promise(resolve => {
81
+ const ack: Ack = [expectedMatches, resolve];
82
+ acks.push(ack);
83
+ let publish = fn;
84
+ if (Solid.OBSERVE !== undefined) {
85
+ const ref = describeNavigation(router, expectedMatches, requestedAt);
86
+ if (ref !== undefined) {
87
+ requestedAt = undefined;
88
+ const observe = Solid.OBSERVE;
89
+ publish = () => observe.attribution.withOrigin(ref, fn);
90
+ }
91
+ }
92
+ Solid.runWithOwner(null, publish);
93
+ try {
94
+ Solid.flush();
95
+ } catch {
96
+ // Solid auto-flushes when this is called from a reactive context.
97
+ }
98
+ // A commit that changed nothing produces no settlement to observe.
99
+ if (acks.includes(ack) && isCommitted(expectedMatches)) {
100
+ acks.splice(acks.indexOf(ack), 1);
101
+ resolve(true);
102
+ }
103
+ });
104
+ };
105
+
106
+ // No server early-return here or below: Solid 2 derives hydration keys
107
+ // from the reactive owner tree, so the server must register the same slots
108
+ // as the client. The callbacks themselves never run on the server.
109
+ Solid.createEffect(
110
+ () => router.stores.matches.get(),
111
+ current => {
112
+ committed = current;
113
+ if (acks.length) {
114
+ for (const [expected, resolve] of acks.splice(0)) {
115
+ resolve(isCommitted(expected));
116
+ }
117
+ }
118
+ },
119
+ );
120
+
121
+ Solid.onSettled(() => {
122
+ const unsub = router.history.subscribe(() => {
123
+ requestedAt ??= performance.now();
124
+ queueMicrotask(() => router.load().catch(console.error));
125
+ });
126
+
127
+ // The URL may have changed synchronously between render and settlement.
128
+ router.updateLatestLocation();
129
+ const nextLocation = router.buildLocation({
130
+ to: router.latestLocation.pathname,
131
+ search: true,
132
+ params: true,
133
+ hash: true,
134
+ state: true,
135
+ _includeValidateSearch: true,
136
+ });
137
+
138
+ if (
139
+ trimPathRight(router.latestLocation.publicHref) !==
140
+ trimPathRight(nextLocation.publicHref)
141
+ ) {
142
+ router.commitLocation({
143
+ ...nextLocation,
144
+ replace: true,
145
+ ignoreBlocker: true,
146
+ });
147
+ return unsub;
148
+ }
149
+
150
+ if (!getResolvedLocation(router) && !router._tx) {
151
+ queueMicrotask(() => router.load().catch(console.error));
152
+ }
153
+
154
+ return unsub;
155
+ });
156
+
157
+ return null;
158
+ }
159
+
160
+ export function Rendered() {
161
+ const router = useRouter();
162
+ Solid.onSettled(() => {
163
+ const resolvedLocation = getResolvedLocation(router);
164
+ if (resolvedLocation) {
165
+ router.emit({
166
+ type: 'onRendered',
167
+ ...getLocationChangeInfo(resolvedLocation, resolvedLocation),
168
+ });
169
+ }
170
+ });
171
+ return null;
172
+ }
@@ -0,0 +1,71 @@
1
+ import type { JSX } from '@solidjs/web';
2
+ import type { DeferredPromise } from '@tanstack/router-core';
3
+ import { defer, TSR_DEFERRED_PROMISE } from '@tanstack/router-core';
4
+ import * as Solid from 'solid-js';
5
+ import type { SolidNode } from './route';
6
+
7
+ export type AwaitOptions<T> = {
8
+ promise: Promise<T>;
9
+ };
10
+
11
+ /**
12
+ * Native loader data is frozen, and defer() tags the promise it tracks, so a
13
+ * frozen promise is tracked through a follower that settles the same way.
14
+ */
15
+ function track<T>(promise: Promise<T>): DeferredPromise<T> {
16
+ return defer(Object.isExtensible(promise) ? promise : promise.then(v => v));
17
+ }
18
+
19
+ export function useAwaited<T>({
20
+ promise: _promise,
21
+ }: AwaitOptions<T>): [data: T, promise: DeferredPromise<T>] {
22
+ const promise = track(_promise);
23
+ const data = Solid.createMemo(async () => await promise);
24
+
25
+ return [data(), promise];
26
+ }
27
+
28
+ function InnerAwait<T>(props: {
29
+ deferred: DeferredPromise<T>;
30
+ ready: Solid.Accessor<unknown>;
31
+ children: (res: T) => SolidNode;
32
+ }) {
33
+ return (
34
+ <Solid.Show when={props.ready()}>
35
+ {_ => {
36
+ const state = props.deferred[TSR_DEFERRED_PROMISE];
37
+ if (state.status === 'error') {
38
+ throw state.error;
39
+ }
40
+ return props.children(state.data as T) as any;
41
+ }}
42
+ </Solid.Show>
43
+ );
44
+ }
45
+
46
+ export function Await<T>(
47
+ props: AwaitOptions<T> & {
48
+ fallback?: SolidNode;
49
+ children: (result: T) => SolidNode;
50
+ },
51
+ ): JSX.Element {
52
+ const deferred = track(props.promise);
53
+ const ready = Solid.createMemo(async () => {
54
+ await deferred;
55
+ return true;
56
+ });
57
+
58
+ const inner = (
59
+ <InnerAwait deferred={deferred} ready={ready}>
60
+ {props.children}
61
+ </InnerAwait>
62
+ );
63
+
64
+ if (props.fallback === undefined) {
65
+ return inner;
66
+ }
67
+
68
+ return (
69
+ <Solid.Loading fallback={props.fallback as any}>{inner}</Solid.Loading>
70
+ );
71
+ }
@@ -0,0 +1,268 @@
1
+ import type {
2
+ AnyContext,
3
+ AnyRoute,
4
+ AnyRouter,
5
+ Constrain,
6
+ ConstrainLiteral,
7
+ FileBaseRouteOptions,
8
+ FileRoutesByPath,
9
+ LazyRouteOptions,
10
+ Register,
11
+ RegisteredRouter,
12
+ ResolveParams,
13
+ Route,
14
+ RouteById,
15
+ RouteConstraints,
16
+ RouteIds,
17
+ RouteLoaderEntry,
18
+ UpdatableRouteOptions,
19
+ UseNavigateResult,
20
+ } from '@tanstack/router-core';
21
+ import { createRoute } from './route';
22
+ import type { UseLoaderDataRoute } from './useLoaderData';
23
+ import { useLoaderData } from './useLoaderData';
24
+ import type { UseLoaderDepsRoute } from './useLoaderDeps';
25
+ import { useLoaderDeps } from './useLoaderDeps';
26
+ import type { UseMatchRoute } from './useMatch';
27
+ import { useMatch } from './useMatch';
28
+ import { useNavigate } from './useNavigate';
29
+ import type { UseParamsRoute } from './useParams';
30
+ import { useParams } from './useParams';
31
+ import type { UseRouteContextRoute } from './useRouteContext';
32
+ import { useRouteContext } from './useRouteContext';
33
+ import { useRouter } from './useRouter';
34
+ import type { UseSearchRoute } from './useSearch';
35
+ import { useSearch } from './useSearch';
36
+
37
+ export function createFileRoute<
38
+ TFilePath extends keyof FileRoutesByPath,
39
+ TParentRoute extends AnyRoute = FileRoutesByPath[TFilePath]['parentRoute'],
40
+ TId extends RouteConstraints['TId'] = FileRoutesByPath[TFilePath]['id'],
41
+ TPath extends RouteConstraints['TPath'] = FileRoutesByPath[TFilePath]['path'],
42
+ TFullPath extends
43
+ RouteConstraints['TFullPath'] = FileRoutesByPath[TFilePath]['fullPath'],
44
+ >(
45
+ _path?: TFilePath,
46
+ ): FileRoute<TFilePath, TParentRoute, TId, TPath, TFullPath>['createRoute'] {
47
+ return options => {
48
+ const route = createRoute(options as any);
49
+ (route as any).isRoot = false;
50
+ return route as any;
51
+ };
52
+ }
53
+
54
+ /**
55
+ @deprecated It's no longer recommended to use the `FileRoute` class directly.
56
+ Instead, use `createFileRoute('/path/to/file')(options)` to create a file route.
57
+ */
58
+ export class FileRoute<
59
+ TFilePath extends keyof FileRoutesByPath,
60
+ TParentRoute extends AnyRoute = FileRoutesByPath[TFilePath]['parentRoute'],
61
+ TId extends RouteConstraints['TId'] = FileRoutesByPath[TFilePath]['id'],
62
+ TPath extends RouteConstraints['TPath'] = FileRoutesByPath[TFilePath]['path'],
63
+ TFullPath extends
64
+ RouteConstraints['TFullPath'] = FileRoutesByPath[TFilePath]['fullPath'],
65
+ > {
66
+ silent?: boolean;
67
+
68
+ constructor(
69
+ public path?: TFilePath,
70
+ _opts?: { silent: boolean },
71
+ ) {
72
+ this.silent = _opts?.silent;
73
+ }
74
+
75
+ createRoute = <
76
+ TRegister = Register,
77
+ TSearchValidator = undefined,
78
+ TParams = ResolveParams<TPath>,
79
+ TRouteContextFn = AnyContext,
80
+ TBeforeLoadFn = AnyContext,
81
+ TLoaderDeps extends Record<string, any> = {},
82
+ TLoaderFn = undefined,
83
+ TChildren = unknown,
84
+ TSSR = unknown,
85
+ const TMiddlewares = unknown,
86
+ THandlers = undefined,
87
+ >(
88
+ options?: FileBaseRouteOptions<
89
+ TRegister,
90
+ TParentRoute,
91
+ TId,
92
+ TPath,
93
+ TSearchValidator,
94
+ TParams,
95
+ TLoaderDeps,
96
+ TLoaderFn,
97
+ AnyContext,
98
+ TRouteContextFn,
99
+ TBeforeLoadFn,
100
+ AnyContext,
101
+ TSSR,
102
+ TMiddlewares,
103
+ THandlers
104
+ > &
105
+ UpdatableRouteOptions<
106
+ TParentRoute,
107
+ TId,
108
+ TFullPath,
109
+ TParams,
110
+ TSearchValidator,
111
+ TLoaderFn,
112
+ TLoaderDeps,
113
+ AnyContext,
114
+ TRouteContextFn,
115
+ TBeforeLoadFn
116
+ >,
117
+ ): Route<
118
+ TRegister,
119
+ TParentRoute,
120
+ TPath,
121
+ TFullPath,
122
+ TFilePath,
123
+ TId,
124
+ TSearchValidator,
125
+ TParams,
126
+ AnyContext,
127
+ TRouteContextFn,
128
+ TBeforeLoadFn,
129
+ TLoaderDeps,
130
+ TLoaderFn,
131
+ TChildren,
132
+ unknown,
133
+ TSSR,
134
+ TMiddlewares,
135
+ THandlers
136
+ > => {
137
+ if (process.env.NODE_ENV !== 'production') {
138
+ if (!this.silent) {
139
+ console.warn(
140
+ 'Warning: FileRoute is deprecated and will be removed in the next major version. Use the createFileRoute(path)(options) function instead.',
141
+ );
142
+ }
143
+ }
144
+ const route = createRoute(options as any);
145
+ (route as any).isRoot = false;
146
+ return route as any;
147
+ };
148
+ }
149
+
150
+ /**
151
+ @deprecated It's recommended not to split loaders into separate files.
152
+ Instead, place the loader function in the main route file, inside the
153
+ `createFileRoute('/path/to/file)(options)` options.
154
+ */
155
+ export function FileRouteLoader<
156
+ TFilePath extends keyof FileRoutesByPath,
157
+ TRoute extends FileRoutesByPath[TFilePath]['preLoaderRoute'],
158
+ >(
159
+ _path: TFilePath,
160
+ ): <TLoaderFn>(
161
+ loaderFn: Constrain<
162
+ TLoaderFn,
163
+ RouteLoaderEntry<
164
+ Register,
165
+ TRoute['parentRoute'],
166
+ TRoute['types']['id'],
167
+ TRoute['types']['params'],
168
+ TRoute['types']['loaderDeps'],
169
+ TRoute['types']['routerContext'],
170
+ TRoute['types']['routeContextFn'],
171
+ TRoute['types']['beforeLoadFn']
172
+ >
173
+ >,
174
+ ) => TLoaderFn {
175
+ if (process.env.NODE_ENV !== 'production') {
176
+ console.warn(
177
+ `Warning: FileRouteLoader is deprecated and will be removed in the next major version. Please place the loader function in the main route file, inside the \`createFileRoute('/path/to/file')(options)\` options`,
178
+ );
179
+ }
180
+ return loaderFn => loaderFn as any;
181
+ }
182
+
183
+ declare module '@tanstack/router-core' {
184
+ export interface LazyRoute<in out TRoute extends AnyRoute> {
185
+ useMatch: UseMatchRoute<TRoute['id']>;
186
+ useRouteContext: UseRouteContextRoute<TRoute['id']>;
187
+ useSearch: UseSearchRoute<TRoute['id']>;
188
+ useParams: UseParamsRoute<TRoute['id']>;
189
+ useLoaderDeps: UseLoaderDepsRoute<TRoute['id']>;
190
+ useLoaderData: UseLoaderDataRoute<TRoute['id']>;
191
+ useNavigate: () => UseNavigateResult<TRoute['fullPath']>;
192
+ }
193
+ }
194
+
195
+ export class LazyRoute<TRoute extends AnyRoute> {
196
+ options: {
197
+ id: string;
198
+ } & LazyRouteOptions;
199
+
200
+ constructor(
201
+ opts: {
202
+ id: string;
203
+ } & LazyRouteOptions,
204
+ ) {
205
+ this.options = opts;
206
+ }
207
+
208
+ useMatch: UseMatchRoute<TRoute['id']> = opts => {
209
+ return useMatch({
210
+ select: opts?.select,
211
+ from: this.options.id,
212
+ } as any) as any;
213
+ };
214
+
215
+ useRouteContext: UseRouteContextRoute<TRoute['id']> = opts => {
216
+ return useRouteContext({ ...(opts as any), from: this.options.id });
217
+ };
218
+
219
+ useSearch: UseSearchRoute<TRoute['id']> = opts => {
220
+ return useSearch({
221
+ select: opts?.select,
222
+ from: this.options.id,
223
+ } as any) as any;
224
+ };
225
+
226
+ useParams: UseParamsRoute<TRoute['id']> = opts => {
227
+ return useParams({
228
+ select: opts?.select,
229
+ from: this.options.id,
230
+ } as any) as any;
231
+ };
232
+
233
+ useLoaderDeps: UseLoaderDepsRoute<TRoute['id']> = opts => {
234
+ return useLoaderDeps({ ...opts, from: this.options.id } as any);
235
+ };
236
+
237
+ useLoaderData: UseLoaderDataRoute<TRoute['id']> = opts => {
238
+ return useLoaderData({ ...opts, from: this.options.id } as any);
239
+ };
240
+
241
+ useNavigate = (): UseNavigateResult<TRoute['fullPath']> => {
242
+ const router = useRouter();
243
+ return useNavigate({ from: router.routesById[this.options.id].fullPath });
244
+ };
245
+ }
246
+
247
+ export function createLazyRoute<
248
+ TRouter extends AnyRouter = RegisteredRouter,
249
+ TId extends string = string,
250
+ TRoute extends AnyRoute = RouteById<TRouter['routeTree'], TId>,
251
+ >(id: ConstrainLiteral<TId, RouteIds<TRouter['routeTree']>>) {
252
+ return (opts: LazyRouteOptions) => {
253
+ return new LazyRoute<TRoute>({
254
+ id: id,
255
+ ...opts,
256
+ });
257
+ };
258
+ }
259
+ export function createLazyFileRoute<
260
+ TFilePath extends keyof FileRoutesByPath,
261
+ TRoute extends FileRoutesByPath[TFilePath]['preLoaderRoute'],
262
+ >(id: TFilePath): (opts: LazyRouteOptions) => LazyRoute<TRoute> {
263
+ if (typeof id === 'object') {
264
+ return new LazyRoute<TRoute>(id) as any;
265
+ }
266
+
267
+ return (opts: LazyRouteOptions) => new LazyRoute<TRoute>({ id, ...opts });
268
+ }
@@ -0,0 +1,90 @@
1
+ import { REVALIDATE_HEADER } from '@solidjs/web';
2
+ import {
3
+ decodeRedirectHeaderValue,
4
+ REDIRECT_HEADER,
5
+ subscribeFlightData,
6
+ } from '@solidjs/web/server-functions';
7
+ import type { AnyRouter } from '@tanstack/router-core';
8
+
9
+ /**
10
+ * Registers the router as the unnamed single-flight consumer of Solid's
11
+ * server-function transport, so the response helpers a mutation returns —
12
+ * `redirect()`, `reload()`, `respond(value, { revalidate })` — take effect
13
+ * on the client without the caller wrapping the call: the transport hands
14
+ * the caller the plain value and the router applies the metadata. Called
15
+ * by `RouterContextProvider` on the client; returns the unsubscribe.
16
+ *
17
+ * Subscribing is also the single-flight opt-in: while registered, the
18
+ * transport tags mutation calls so the server can fold fresh data for
19
+ * registered collectors into the same response. The router claims no
20
+ * slice of that data itself — route data is reloaded through `invalidate`
21
+ * below, and caches that want seeding (a query client) subscribe under
22
+ * their own source id.
23
+ */
24
+ export function setupFlightDataConsumer(router: AnyRouter): () => void {
25
+ return subscribeFlightData((_data, { response }) =>
26
+ applyResponseMetadata(router, response),
27
+ );
28
+ }
29
+
30
+ /**
31
+ * Applies a server-function response's integration metadata to the
32
+ * router. A mutation is a write, so a response carrying metadata reloads
33
+ * the route data the page is built on: committed and cached matches are
34
+ * invalidated the way `router.invalidate()` does after a mutation.
35
+ *
36
+ * `X-Revalidate` names entries in caches the router does not own, so the
37
+ * keys themselves are left to those caches' consumers; the router reads
38
+ * only the declaration's shape. Absent (a bare `redirect()`/`reload()`),
39
+ * named keys, or the reserved `*` all say a write happened — route data
40
+ * reloads. An EMPTY declaration (`revalidate: []`) is the author narrowing
41
+ * the scope to nothing, and the router honors that too: a redirect still
42
+ * navigates, but nothing is reloaded on the way.
43
+ *
44
+ * The redirect carrier delivers the target RESOLVED to an absolute url, so
45
+ * the soft/hard split is a real origin comparison: a same-origin target
46
+ * navigates under the router (`replace`, matching what HTTP gives a form
47
+ * post — the destination takes the submission's place in history), and any
48
+ * other origin leaves the app through a document navigation.
49
+ */
50
+ export function applyResponseMetadata(
51
+ router: AnyRouter,
52
+ response: Response,
53
+ ): void {
54
+ const carried = decodeRedirectHeaderValue(
55
+ response.headers.get(REDIRECT_HEADER),
56
+ );
57
+ const declared = response.headers.get(REVALIDATE_HEADER);
58
+ if (!carried && declared === null) return;
59
+ const reload = declared === null || declared.split(',').some(Boolean);
60
+
61
+ const target = carried ? new URL(carried.url) : undefined;
62
+ const origin = router.options.origin ?? window.location.origin;
63
+ if (target && target.origin !== origin) {
64
+ // A full url makes `navigate` reload the document (through the
65
+ // router, so protocol allowlisting and blockers still apply).
66
+ router.navigate({ href: target.href, replace: true });
67
+ return;
68
+ }
69
+
70
+ // Navigate, then invalidate — in this order so the write costs one load.
71
+ // `navigate` commits the destination to history synchronously (the
72
+ // adapter's own load follows in a microtask); `invalidate` then marks the
73
+ // committed matches — the layouts the destination shares with the page
74
+ // the mutation ran on, whose data is what just changed — and starts a
75
+ // load that already reads the destination as the latest location. The
76
+ // adapter's load adopts the loader generations that load started for
77
+ // the same match ids rather than restarting them, so the destination
78
+ // commits with the layouts reloaded, and the page being left never has
79
+ // its own loaders rerun. The other order would reload the abandoned
80
+ // page first.
81
+ if (target) {
82
+ router
83
+ .navigate({
84
+ href: target.pathname + target.search + target.hash,
85
+ replace: true,
86
+ })
87
+ .catch(console.error);
88
+ }
89
+ if (reload) router.invalidate().catch(console.error);
90
+ }