@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
package/src/server.ts ADDED
@@ -0,0 +1,645 @@
1
+ import {
2
+ type DocumentAsset,
3
+ type DocumentInlineData,
4
+ prepareDocument,
5
+ } from '@modern-js/renderer-core/document';
6
+ import type { NativeFederationBinding } from '@modern-js/renderer-core/federation';
7
+ import {
8
+ policyHeaders,
9
+ type RequestSession,
10
+ responseHeaders,
11
+ restrictDocumentCache,
12
+ untilAborted,
13
+ } from '@modern-js/renderer-core/session';
14
+ import {
15
+ commitEventResponse,
16
+ createRequestEvent,
17
+ generateHydrationScript,
18
+ isServer,
19
+ type JSX,
20
+ renderToStream,
21
+ ssr,
22
+ } from '@solidjs/web';
23
+ import { provideRequestEvent } from '@solidjs/web/storage';
24
+ import {
25
+ createComponent,
26
+ createRoot,
27
+ Hydration,
28
+ NoHydration,
29
+ runWithOwner,
30
+ } from 'solid-js';
31
+ import {
32
+ createFederationScope,
33
+ provideFederation,
34
+ type SolidFederationScope,
35
+ } from './federation-context';
36
+ import { withFederatedAssets } from './federation-ssr';
37
+ import { nativePromiseSerializationPlugin } from './native-promise-serialization';
38
+
39
+ /**
40
+ * List fields components add to: browsers enforce every CSP field, and links
41
+ * from loaders and components are all hints for the document.
42
+ */
43
+ const CSP_HEADERS = new Set([
44
+ 'content-security-policy',
45
+ 'content-security-policy-report-only',
46
+ 'link',
47
+ ]);
48
+
49
+ type NativeStreamOptions = NonNullable<Parameters<typeof renderToStream>[1]>;
50
+
51
+ type ApplicationRequestEvent = ReturnType<
52
+ typeof createRequestEvent<{
53
+ locals: { session: RequestSession; bindings: object };
54
+ }>
55
+ >;
56
+
57
+ const requestEvents = new WeakMap<RequestSession, ApplicationRequestEvent>();
58
+ const nativeHeads = new WeakMap<
59
+ ApplicationRequestEvent,
60
+ { response: ApplicationRequestEvent['response']; headers: Headers }
61
+ >();
62
+
63
+ function applicationRequestEvent<Bindings extends object>(
64
+ session: RequestSession<Bindings>,
65
+ ): ApplicationRequestEvent {
66
+ if (session.identity.renderer !== 'solid') {
67
+ throw new Error('The Solid adapter requires a Solid renderer identity.');
68
+ }
69
+ if (session.platform.kind !== 'node' && session.platform.kind !== 'worker') {
70
+ throw new Error(
71
+ 'Solid request context requires a Node or worker request platform.',
72
+ );
73
+ }
74
+ if (!isServer) {
75
+ throw new Error(
76
+ 'The Solid server adapter must resolve @solidjs/web with a server (node or worker) condition.',
77
+ );
78
+ }
79
+ let event = requestEvents.get(session);
80
+ if (!event) {
81
+ event = createRequestEvent(session.request, {
82
+ locals: { session, bindings: session.platform.bindings },
83
+ });
84
+ requestEvents.set(session, event);
85
+ nativeHeads.set(event, {
86
+ response: event.response,
87
+ headers: event.response.headers,
88
+ });
89
+ }
90
+ return event;
91
+ }
92
+
93
+ /** Establish Solid's native request scope before loaders and response dispatch. */
94
+ export async function runApplicationRequest<Bindings extends object, Result>(
95
+ session: RequestSession<Bindings>,
96
+ callback: () => Result,
97
+ ): Promise<Awaited<Result>> {
98
+ let event: ApplicationRequestEvent;
99
+ try {
100
+ event = applicationRequestEvent(session);
101
+ } catch (error) {
102
+ void session.fail(error);
103
+ throw error;
104
+ }
105
+ // Fail inside the request scope so session cleanup observes its event.
106
+ return await provideRequestEvent(event, async () => {
107
+ try {
108
+ // Request work that ignores cancellation must not hold its event.
109
+ return await untilAborted(
110
+ callback() as Awaited<Result> | Promise<Awaited<Result>>,
111
+ session.signal,
112
+ );
113
+ } catch (error) {
114
+ void session.fail(error);
115
+ throw error;
116
+ }
117
+ });
118
+ }
119
+
120
+ function ownData(object: object, key: PropertyKey): unknown {
121
+ const descriptor = Object.getOwnPropertyDescriptor(object, key);
122
+ if (!descriptor || !('value' in descriptor)) {
123
+ throw new TypeError(
124
+ 'Solid response metadata must contain own data fields.',
125
+ );
126
+ }
127
+ return descriptor.value;
128
+ }
129
+
130
+ function readNativeHead(event: ApplicationRequestEvent) {
131
+ const native = nativeHeads.get(event);
132
+ if (!native || ownData(event, 'response') !== native.response) {
133
+ throw new TypeError('The native Solid response stub cannot be replaced.');
134
+ }
135
+ const response = native.response;
136
+ const status = ownData(response, 'status');
137
+ const statusText = ownData(response, 'statusText');
138
+ if (
139
+ status !== undefined &&
140
+ (typeof status !== 'number' ||
141
+ !Number.isInteger(status) ||
142
+ status < 200 ||
143
+ status > 599)
144
+ ) {
145
+ throw new TypeError(
146
+ 'A Solid response status must be an integer from 200 to 599.',
147
+ );
148
+ }
149
+ if (statusText !== undefined && typeof statusText !== 'string') {
150
+ throw new TypeError('A Solid response statusText must be a string.');
151
+ }
152
+ if (ownData(response, 'committed') !== false) {
153
+ throw new Error('The native Solid response head is already committed.');
154
+ }
155
+ if (
156
+ ownData(response, 'headers') !== native.headers ||
157
+ Object.getPrototypeOf(native.headers) !== Headers.prototype
158
+ ) {
159
+ throw new TypeError(
160
+ 'The native Solid response Headers cannot be replaced.',
161
+ );
162
+ }
163
+ for (const key of [
164
+ 'append',
165
+ 'delete',
166
+ 'entries',
167
+ 'forEach',
168
+ 'get',
169
+ 'getSetCookie',
170
+ 'has',
171
+ 'set',
172
+ Symbol.iterator,
173
+ ]) {
174
+ if (Object.getOwnPropertyDescriptor(native.headers, key)) {
175
+ throw new TypeError(
176
+ 'The native Solid response Headers methods cannot be replaced.',
177
+ );
178
+ }
179
+ }
180
+ return { status, statusText, headers: native.headers };
181
+ }
182
+
183
+ function respondApplicationBody<Bindings extends object>(
184
+ session: RequestSession<Bindings>,
185
+ body: () => ReadableStream<Uint8Array> | null,
186
+ hasSuppliedBody = false,
187
+ ): Response {
188
+ return provideRequestEvent(applicationRequestEvent(session), () => {
189
+ try {
190
+ const event = applicationRequestEvent(session);
191
+ const policy = session.responsePolicy;
192
+ if (!policy || session.committedPolicy) {
193
+ throw new Error(
194
+ 'Resolve an uncommitted Solid HTTP outcome before responding.',
195
+ );
196
+ }
197
+ const native = readNativeHead(event);
198
+ const original = policyHeaders(policy.headers);
199
+ const outgoing = policyHeaders(policy.headers);
200
+ let status = policy.status;
201
+ let statusText = policy.statusText;
202
+ let kind = policy.kind;
203
+ let bodyless = [204, 205, 304].includes(status);
204
+ if (kind === 'document') {
205
+ status = native.status ?? status;
206
+ statusText = native.statusText ?? statusText;
207
+ native.headers.forEach((value, name) => {
208
+ // Cookies and timing merge through the native commit operation below.
209
+ if (CSP_HEADERS.has(name)) outgoing.append(name, value);
210
+ else if (
211
+ name !== 'set-cookie' &&
212
+ name !== 'server-timing' &&
213
+ name !== 'vary'
214
+ ) {
215
+ outgoing.set(name, value);
216
+ }
217
+ });
218
+ const vary = [original.get('vary'), native.headers.get('vary')].flatMap(
219
+ value =>
220
+ value
221
+ ?.split(',')
222
+ .map(part => part.trim())
223
+ .filter(Boolean) ?? [],
224
+ );
225
+ if (vary.length) outgoing.set('vary', [...new Set(vary)].join(', '));
226
+ for (const name of [
227
+ 'content-length',
228
+ 'content-encoding',
229
+ 'transfer-encoding',
230
+ ])
231
+ outgoing.delete(name);
232
+ if (outgoing.has('location')) {
233
+ status = [301, 302, 303, 307, 308].includes(status) ? status : 302;
234
+ bodyless = true;
235
+ } else bodyless = [204, 205, 304].includes(status);
236
+ if (bodyless) {
237
+ kind = 'terminal';
238
+ outgoing.delete('content-type');
239
+ }
240
+ }
241
+ if (bodyless && hasSuppliedBody) {
242
+ throw new TypeError(
243
+ 'A terminal Solid HTTP outcome cannot consume a document body.',
244
+ );
245
+ }
246
+ const cache = restrictDocumentCache(
247
+ { ...policy, kind, status },
248
+ [native.headers],
249
+ outgoing,
250
+ );
251
+ // Validate the complete policy before native commit makes late writes fail.
252
+ session.resolveResponse({
253
+ kind,
254
+ status,
255
+ statusText,
256
+ headers: responseHeaders(outgoing),
257
+ cache,
258
+ });
259
+ const preview = commitEventResponse(
260
+ new Response(bodyless ? null : body(), {
261
+ status,
262
+ statusText,
263
+ headers: outgoing,
264
+ }),
265
+ event,
266
+ );
267
+ const committedHeaders = preview.headers;
268
+ const finalCache = restrictDocumentCache(
269
+ { ...policy, kind, status },
270
+ [native.headers],
271
+ committedHeaders,
272
+ );
273
+ session.resolveResponse({
274
+ kind,
275
+ status,
276
+ statusText,
277
+ headers: responseHeaders(committedHeaders),
278
+ cache: finalCache,
279
+ });
280
+ return session.respond(preview.body);
281
+ } catch (error) {
282
+ void session.fail(error);
283
+ throw error;
284
+ }
285
+ });
286
+ }
287
+
288
+ /** Fold Solid's native response metadata before the one session body commits. */
289
+ export function respondApplication<Bindings extends object>(
290
+ session: RequestSession<Bindings>,
291
+ body: ReadableStream<Uint8Array> | null,
292
+ ): Response {
293
+ try {
294
+ return respondApplicationBody(session, () => body, body !== null);
295
+ } catch (error) {
296
+ void session.fail(error);
297
+ throw error;
298
+ }
299
+ }
300
+
301
+ /** Adopt an explicit data or redirect Response without replacing its outcome. */
302
+ export function respondApplicationResponse<Bindings extends object>(
303
+ session: RequestSession<Bindings>,
304
+ response: Response,
305
+ ): Response {
306
+ try {
307
+ session.resolveResponse({
308
+ kind: 'terminal',
309
+ status: response.status,
310
+ statusText: response.statusText,
311
+ headers: responseHeaders(response.headers),
312
+ cache: { mode: 'no-store' },
313
+ });
314
+ return respondApplication(session, response.body);
315
+ } catch (error) {
316
+ void session.fail(error);
317
+ throw error;
318
+ }
319
+ }
320
+
321
+ function getDocumentNonce(
322
+ nonce: NativeStreamOptions['nonce'],
323
+ destination: 'script' | 'style',
324
+ ): string | undefined {
325
+ const value = typeof nonce === 'string' ? nonce : nonce?.[destination];
326
+ return value === false ? undefined : value;
327
+ }
328
+
329
+ /** Solid owns hydration, lazy module assets and head placement in its document. */
330
+ export type SolidDocumentOptions = Pick<
331
+ NativeStreamOptions,
332
+ 'renderId' | 'nonce' | 'manifest' | 'onHead'
333
+ >;
334
+
335
+ export interface SolidRenderOptions<Bindings extends object = object> {
336
+ readonly session: RequestSession<Bindings>;
337
+ readonly view: () => JSX.Element;
338
+ readonly document?: SolidDocumentOptions;
339
+ /** Return Solid's native public error mapping, if one is required. */
340
+ readonly onError?: NativeStreamOptions['onError'];
341
+ /** This server compilation's native Module Federation runtime. */
342
+ readonly federation?: NativeFederationBinding;
343
+ }
344
+
345
+ export type { DocumentInlineData };
346
+
347
+ export interface SolidApplicationDocumentOptions extends SolidDocumentOptions {
348
+ readonly rootId?: string;
349
+ readonly lang?: string;
350
+ readonly assets?: readonly DocumentAsset[];
351
+ /** Placed in the head, after the renderer bootstrap and before modules. */
352
+ readonly inlineData?: readonly DocumentInlineData[];
353
+ }
354
+
355
+ export interface SolidDocumentRenderOptions<Bindings extends object = object>
356
+ extends Omit<SolidRenderOptions<Bindings>, 'document'> {
357
+ readonly document?: SolidApplicationDocumentOptions;
358
+ }
359
+
360
+ /**
361
+ * Render a prepared Node document through Solid's one readable consumer.
362
+ * The caller resolves blocking route/data HTTP outcomes before calling this.
363
+ * Like Solid's own SSR response, the HTTP head commits when the shell
364
+ * completes, so status, headers and redirects declared before the shell apply
365
+ * and a shell-time failure rejects before any head commits.
366
+ * A contained native fallback can finish, but is never a successful cache entry.
367
+ * A deferred uncontained failure cancels delivery without changing sent headers.
368
+ */
369
+ export async function renderApplication<Bindings extends object>(
370
+ options: SolidRenderOptions<Bindings>,
371
+ ): Promise<Response> {
372
+ let federation: SolidFederationScope | undefined;
373
+ try {
374
+ federation = createFederationScope(options.federation);
375
+ } catch (error) {
376
+ void options.session.fail(error);
377
+ throw error;
378
+ }
379
+ return renderNativeApplication(
380
+ { ...options, view: provideFederation(federation, options.view) },
381
+ federation,
382
+ );
383
+ }
384
+
385
+ /** The view already provides this response's federation scope. */
386
+ async function renderNativeApplication<Bindings extends object>(
387
+ options: SolidRenderOptions<Bindings>,
388
+ federation: SolidFederationScope | undefined,
389
+ ): Promise<Response> {
390
+ const { session } = options;
391
+ let readable: ReadableStream<Uint8Array> | undefined;
392
+ let consumed = false;
393
+ try {
394
+ const event = applicationRequestEvent(session);
395
+ if (
396
+ session.responsePolicy?.kind !== 'document' ||
397
+ [204, 205, 304].includes(session.responsePolicy.status)
398
+ ) {
399
+ throw new Error(
400
+ 'Resolve a document HTTP outcome before invoking the Solid renderer; terminal responses bypass rendering.',
401
+ );
402
+ }
403
+ session.startRendering();
404
+ let renderFailure: { error: unknown } | undefined;
405
+ const {
406
+ promise: shell,
407
+ resolve,
408
+ reject,
409
+ } = Promise.withResolvers<Response>();
410
+ // A synchronous construction failure rethrows below without awaiting this.
411
+ shell.catch(() => {});
412
+ const failBeforeShell = () =>
413
+ reject(renderFailure ? renderFailure.error : session.signal.reason);
414
+ // A native abort abandons the render without completing its shell.
415
+ if (session.signal.aborted) failBeforeShell();
416
+ else
417
+ session.signal.addEventListener('abort', failBeforeShell, { once: true });
418
+ readable = provideRequestEvent(event, () =>
419
+ runWithOwner(null, () =>
420
+ createRoot(
421
+ dispose => {
422
+ // Solid links its render root to this detached transparent owner.
423
+ // Register disposal before construction: a throwing view can precede
424
+ // renderToStream's own abort listener. Cleanup retains the request event.
425
+ const nativeAbort = new AbortController();
426
+ const abortNative = () =>
427
+ provideRequestEvent(event, () => {
428
+ nativeAbort.abort(session.signal.reason);
429
+ });
430
+ session.signal.addEventListener('abort', abortNative, {
431
+ once: true,
432
+ });
433
+ session.registerCleanup(() =>
434
+ provideRequestEvent(event, () => {
435
+ session.signal.removeEventListener('abort', abortNative);
436
+ if (session.committedPolicy?.kind === 'terminal') {
437
+ nativeAbort.abort(
438
+ new DOMException(
439
+ 'The request resolved without a document body.',
440
+ 'AbortError',
441
+ ),
442
+ );
443
+ }
444
+ dispose();
445
+ }),
446
+ );
447
+ if (session.signal.aborted) abortNative();
448
+ const native = renderToStream(options.view, {
449
+ ...options.document,
450
+ // Server-rendered federated components add their remote assets.
451
+ manifest: withFederatedAssets(
452
+ options.document?.manifest,
453
+ federation,
454
+ ),
455
+ plugins: [nativePromiseSerializationPlugin],
456
+ // Restore the request event when transport cancellation occurs
457
+ // outside the async scope that constructed the native stream.
458
+ signal: nativeAbort.signal,
459
+ // The shell completes synchronously before its first write and
460
+ // before a finished render disposes owner-scoped declarations.
461
+ onCompleteShell() {
462
+ session.signal.removeEventListener('abort', failBeforeShell);
463
+ try {
464
+ resolve(
465
+ respondApplicationBody(session, () => {
466
+ consumed = true;
467
+ return native.readable;
468
+ }),
469
+ );
470
+ } catch (error) {
471
+ reject(error);
472
+ throw error;
473
+ }
474
+ },
475
+ onError(error, context) {
476
+ if (context.handling === 'failed') {
477
+ renderFailure ??= { error };
478
+ void session.fail(error);
479
+ } else if (
480
+ session.state !== 'completed' &&
481
+ session.state !== 'failed' &&
482
+ session.state !== 'aborted'
483
+ ) {
484
+ session.markFallback();
485
+ }
486
+ return options.onError?.(error, context);
487
+ },
488
+ });
489
+ if (renderFailure) throw renderFailure.error;
490
+ // Claim Solid's one consumer; do not await the native thenable, which
491
+ // waits for the complete document. The session owns cancellation,
492
+ // backpressure and exactly-once cleanup.
493
+ return native.readable;
494
+ },
495
+ { transparent: true },
496
+ ),
497
+ ),
498
+ );
499
+ return await shell;
500
+ } catch (error) {
501
+ void session.fail(error);
502
+ throw error;
503
+ } finally {
504
+ // A bodyless or failed outcome releases the native document consumer.
505
+ if (readable && !consumed) void readable.cancel().catch(() => {});
506
+ }
507
+ }
508
+
509
+ function createDocumentParts<Bindings extends object>(
510
+ options: Pick<SolidDocumentRenderOptions<Bindings>, 'session' | 'document'>,
511
+ hydrating: boolean,
512
+ ) {
513
+ const { session } = options;
514
+ const document = options.document ?? {};
515
+ const renderId =
516
+ document.renderId ??
517
+ `${[
518
+ session.identity.appId,
519
+ session.identity.entryName,
520
+ session.identity.buildId,
521
+ ]
522
+ .map(value => encodeURIComponent(value).replaceAll("'", '%27'))
523
+ .join(':')}:`;
524
+ if (typeof renderId !== 'string' || /[\s"'`=<>&]/u.test(renderId)) {
525
+ throw new TypeError(
526
+ 'A Solid renderId cannot contain whitespace, quotes or HTML syntax.',
527
+ );
528
+ }
529
+ const script = getDocumentNonce(document.nonce, 'script');
530
+ const style = getDocumentNonce(document.nonce, 'style');
531
+ const parts = prepareDocument(
532
+ { identity: session.identity, documentId: renderId, hydrating },
533
+ {
534
+ rootId: document.rootId,
535
+ lang: document.lang,
536
+ nonce: { script, style },
537
+ assets: document.assets,
538
+ inlineData: document.inlineData,
539
+ },
540
+ );
541
+ return {
542
+ renderId,
543
+ lang: ` lang="${parts.lang}"`,
544
+ root: ` id="${parts.rootId}"`,
545
+ // Solid keeps the bootstrap in the head, before its hydration script.
546
+ head:
547
+ parts.headAssets +
548
+ parts.bootstrap +
549
+ (hydrating ? generateHydrationScript({ nonce: script }) : ''),
550
+ modules: parts.entryScripts,
551
+ };
552
+ }
553
+
554
+ /** Construct the native document used by generated and hand-authored entries. */
555
+ export async function renderDocumentApplication<Bindings extends object>(
556
+ options: SolidDocumentRenderOptions<Bindings>,
557
+ ): Promise<Response> {
558
+ try {
559
+ const parts = createDocumentParts(options, true);
560
+ // The browser provides federation at its hydration root, inside Hydration.
561
+ const federation = createFederationScope(options.federation);
562
+ const view = provideFederation(federation, options.view);
563
+ return await renderNativeApplication(
564
+ {
565
+ session: options.session,
566
+ document: {
567
+ renderId: parts.renderId,
568
+ nonce: options.document?.nonce,
569
+ manifest: options.document?.manifest,
570
+ onHead: options.document?.onHead,
571
+ },
572
+ onError: options.onError,
573
+ view: () =>
574
+ createComponent(NoHydration, {
575
+ get children() {
576
+ return ssr(
577
+ [
578
+ '<!doctype html><html',
579
+ '><head>',
580
+ '</head><body><div',
581
+ '>',
582
+ '</div>',
583
+ '</body></html>',
584
+ ],
585
+ parts.lang,
586
+ ssr(parts.head),
587
+ parts.root,
588
+ createComponent(Hydration, {
589
+ id: parts.renderId,
590
+ get children() {
591
+ return view();
592
+ },
593
+ }),
594
+ ssr(parts.modules),
595
+ );
596
+ },
597
+ }),
598
+ },
599
+ federation,
600
+ );
601
+ } catch (error) {
602
+ void options.session.fail(error);
603
+ throw error;
604
+ }
605
+ }
606
+
607
+ /** CSR delivers an empty mount region and never evaluates an SSR application. */
608
+ export function renderCSRDocument<Bindings extends object>(
609
+ options: Pick<SolidDocumentRenderOptions<Bindings>, 'session' | 'document'>,
610
+ ): Response {
611
+ const { session } = options;
612
+ try {
613
+ if (
614
+ session.identity.renderer !== 'solid' ||
615
+ (session.platform.kind !== 'node' && session.platform.kind !== 'worker')
616
+ ) {
617
+ throw new Error(
618
+ 'The Solid CSR document requires a Solid Node or worker request session.',
619
+ );
620
+ }
621
+ if (
622
+ session.responsePolicy?.kind !== 'document' ||
623
+ [204, 205, 304].includes(session.responsePolicy.status)
624
+ ) {
625
+ throw new Error('Terminal HTTP outcomes bypass the Solid CSR document.');
626
+ }
627
+ const parts = createDocumentParts(options, false);
628
+ const html = `<!doctype html><html${parts.lang}><head>${parts.head}</head><body><div${parts.root}></div>${parts.modules}</body></html>`;
629
+ return respondApplication(
630
+ session,
631
+ new ReadableStream<Uint8Array>(
632
+ {
633
+ start(controller) {
634
+ controller.enqueue(new TextEncoder().encode(html));
635
+ controller.close();
636
+ },
637
+ },
638
+ { highWaterMark: 0 },
639
+ ),
640
+ );
641
+ } catch (error) {
642
+ void session.fail(error);
643
+ throw error;
644
+ }
645
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.