effective-rsc 0.1.0

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 (220) hide show
  1. package/LICENSE +21 -0
  2. package/LLMS.md +382 -0
  3. package/README.md +235 -0
  4. package/bin/ersc.js +3 -0
  5. package/dist/application/component.d.ts +15 -0
  6. package/dist/application/component.js +20 -0
  7. package/dist/application/component.js.map +1 -0
  8. package/dist/application/definition.d.ts +31 -0
  9. package/dist/application/definition.js +57 -0
  10. package/dist/application/definition.js.map +1 -0
  11. package/dist/application/ersc-identity.d.ts +25 -0
  12. package/dist/application/ersc-identity.js +23 -0
  13. package/dist/application/ersc-identity.js.map +1 -0
  14. package/dist/application/ersc.d.ts +28 -0
  15. package/dist/application/ersc.js +72 -0
  16. package/dist/application/ersc.js.map +1 -0
  17. package/dist/application/layout.d.ts +18 -0
  18. package/dist/application/layout.js +17 -0
  19. package/dist/application/layout.js.map +1 -0
  20. package/dist/application/loading.d.ts +17 -0
  21. package/dist/application/loading.js +14 -0
  22. package/dist/application/loading.js.map +1 -0
  23. package/dist/application/middleware.d.ts +36 -0
  24. package/dist/application/middleware.js +46 -0
  25. package/dist/application/middleware.js.map +1 -0
  26. package/dist/application/page.d.ts +58 -0
  27. package/dist/application/page.js +50 -0
  28. package/dist/application/page.js.map +1 -0
  29. package/dist/application/render-runtime.d.ts +9 -0
  30. package/dist/application/render-runtime.js +28 -0
  31. package/dist/application/render-runtime.js.map +1 -0
  32. package/dist/application/route-graph.d.ts +22 -0
  33. package/dist/application/route-graph.js +68 -0
  34. package/dist/application/route-graph.js.map +1 -0
  35. package/dist/application/route-path.d.ts +31 -0
  36. package/dist/application/route-path.js +67 -0
  37. package/dist/application/route-path.js.map +1 -0
  38. package/dist/application/routes.d.ts +66 -0
  39. package/dist/application/routes.js +159 -0
  40. package/dist/application/routes.js.map +1 -0
  41. package/dist/application/server-fn.d.ts +30 -0
  42. package/dist/application/server-fn.js +58 -0
  43. package/dist/application/server-fn.js.map +1 -0
  44. package/dist/build/build.d.ts +26 -0
  45. package/dist/build/build.js +59 -0
  46. package/dist/build/build.js.map +1 -0
  47. package/dist/build/compiled-server.d.ts +53 -0
  48. package/dist/build/compiled-server.js +77 -0
  49. package/dist/build/compiled-server.js.map +1 -0
  50. package/dist/build/contract.d.ts +23 -0
  51. package/dist/build/contract.js +41 -0
  52. package/dist/build/contract.js.map +1 -0
  53. package/dist/build/dev-channel.d.ts +20 -0
  54. package/dist/build/dev-channel.js +71 -0
  55. package/dist/build/dev-channel.js.map +1 -0
  56. package/dist/build/dev.d.ts +41 -0
  57. package/dist/build/dev.js +186 -0
  58. package/dist/build/dev.js.map +1 -0
  59. package/dist/build/rsc-entry.d.ts +4 -0
  60. package/dist/build/rsc-entry.js +17 -0
  61. package/dist/build/rsc-entry.js.map +1 -0
  62. package/dist/build/rspack-config.d.ts +17 -0
  63. package/dist/build/rspack-config.js +259 -0
  64. package/dist/build/rspack-config.js.map +1 -0
  65. package/dist/build/rspack.d.ts +45 -0
  66. package/dist/build/rspack.js +231 -0
  67. package/dist/build/rspack.js.map +1 -0
  68. package/dist/build/terminal.d.ts +9 -0
  69. package/dist/build/terminal.js +17 -0
  70. package/dist/build/terminal.js.map +1 -0
  71. package/dist/cli.d.ts +14 -0
  72. package/dist/cli.js +116 -0
  73. package/dist/cli.js.map +1 -0
  74. package/dist/client/application.d.ts +2 -0
  75. package/dist/client/application.js +73 -0
  76. package/dist/client/application.js.map +1 -0
  77. package/dist/client/browser-capabilities.d.ts +9 -0
  78. package/dist/client/browser-capabilities.js +20 -0
  79. package/dist/client/browser-capabilities.js.map +1 -0
  80. package/dist/client/browser-effect-runner.d.ts +13 -0
  81. package/dist/client/browser-effect-runner.js +13 -0
  82. package/dist/client/browser-effect-runner.js.map +1 -0
  83. package/dist/client/browser-renderer.d.ts +70 -0
  84. package/dist/client/browser-renderer.js +159 -0
  85. package/dist/client/browser-renderer.js.map +1 -0
  86. package/dist/client/browser-screen.d.ts +2 -0
  87. package/dist/client/browser-screen.js +215 -0
  88. package/dist/client/browser-screen.js.map +1 -0
  89. package/dist/client/call-server.d.ts +8 -0
  90. package/dist/client/call-server.js +151 -0
  91. package/dist/client/call-server.js.map +1 -0
  92. package/dist/client/client-router.d.ts +6 -0
  93. package/dist/client/client-router.js +588 -0
  94. package/dist/client/client-router.js.map +1 -0
  95. package/dist/client/entry.d.ts +1 -0
  96. package/dist/client/entry.js +12 -0
  97. package/dist/client/entry.js.map +1 -0
  98. package/dist/client/flight-client.d.ts +83 -0
  99. package/dist/client/flight-client.js +146 -0
  100. package/dist/client/flight-client.js.map +1 -0
  101. package/dist/client/initial-flight-stream.d.ts +18 -0
  102. package/dist/client/initial-flight-stream.js +60 -0
  103. package/dist/client/initial-flight-stream.js.map +1 -0
  104. package/dist/client/navigation-api.d.ts +34 -0
  105. package/dist/client/navigation-api.js +25 -0
  106. package/dist/client/navigation-api.js.map +1 -0
  107. package/dist/client/navigation-routing.d.ts +3 -0
  108. package/dist/client/navigation-routing.js +8 -0
  109. package/dist/client/navigation-routing.js.map +1 -0
  110. package/dist/client/react-dom-renderer.d.ts +20 -0
  111. package/dist/client/react-dom-renderer.js +101 -0
  112. package/dist/client/react-dom-renderer.js.map +1 -0
  113. package/dist/client/route-loader.d.ts +81 -0
  114. package/dist/client/route-loader.js +128 -0
  115. package/dist/client/route-loader.js.map +1 -0
  116. package/dist/client/route-refresh.d.ts +31 -0
  117. package/dist/client/route-refresh.js +132 -0
  118. package/dist/client/route-refresh.js.map +1 -0
  119. package/dist/client/route-tree.d.ts +7 -0
  120. package/dist/client/route-tree.js +34 -0
  121. package/dist/client/route-tree.js.map +1 -0
  122. package/dist/dev/channel.d.ts +18 -0
  123. package/dist/dev/channel.js +30 -0
  124. package/dist/dev/channel.js.map +1 -0
  125. package/dist/dev/client.d.ts +3 -0
  126. package/dist/dev/client.js +132 -0
  127. package/dist/dev/client.js.map +1 -0
  128. package/dist/dev/hmr-update.d.ts +20 -0
  129. package/dist/dev/hmr-update.js +28 -0
  130. package/dist/dev/hmr-update.js.map +1 -0
  131. package/dist/dev/panel.d.ts +41 -0
  132. package/dist/dev/panel.js +9946 -0
  133. package/dist/dev/panel.js.map +1 -0
  134. package/dist/dev/runtime-failure.d.ts +11 -0
  135. package/dist/dev/runtime-failure.js +32 -0
  136. package/dist/dev/runtime-failure.js.map +1 -0
  137. package/dist/index.d.ts +1 -0
  138. package/dist/index.js +6 -0
  139. package/dist/index.js.map +1 -0
  140. package/dist/rsc/flight.d.ts +16 -0
  141. package/dist/rsc/flight.js +6 -0
  142. package/dist/rsc/flight.js.map +1 -0
  143. package/dist/rsc/render-route-tree.d.ts +11 -0
  144. package/dist/rsc/render-route-tree.js +52 -0
  145. package/dist/rsc/render-route-tree.js.map +1 -0
  146. package/dist/rsc/route-tree.d.ts +6 -0
  147. package/dist/rsc/route-tree.js +5 -0
  148. package/dist/rsc/route-tree.js.map +1 -0
  149. package/dist/server/application.d.ts +17 -0
  150. package/dist/server/application.js +178 -0
  151. package/dist/server/application.js.map +1 -0
  152. package/dist/server/flight-html-stream.d.ts +19 -0
  153. package/dist/server/flight-html-stream.js +193 -0
  154. package/dist/server/flight-html-stream.js.map +1 -0
  155. package/dist/server/flight-renderer.d.ts +31 -0
  156. package/dist/server/flight-renderer.js +47 -0
  157. package/dist/server/flight-renderer.js.map +1 -0
  158. package/dist/server/html-renderer.d.ts +28 -0
  159. package/dist/server/html-renderer.js +82 -0
  160. package/dist/server/html-renderer.js.map +1 -0
  161. package/dist/server/request-outcome.d.ts +8 -0
  162. package/dist/server/request-outcome.js +5 -0
  163. package/dist/server/request-outcome.js.map +1 -0
  164. package/dist/server/server-config.d.ts +17 -0
  165. package/dist/server/server-config.js +18 -0
  166. package/dist/server/server-config.js.map +1 -0
  167. package/dist/server/server-fn-outcome.d.ts +13 -0
  168. package/dist/server/server-fn-outcome.js +24 -0
  169. package/dist/server/server-fn-outcome.js.map +1 -0
  170. package/dist/server/server-fn-request.d.ts +24 -0
  171. package/dist/server/server-fn-request.js +160 -0
  172. package/dist/server/server-fn-request.js.map +1 -0
  173. package/dist/unsupported.d.ts +0 -0
  174. package/dist/unsupported.js +5 -0
  175. package/dist/unsupported.js.map +1 -0
  176. package/docs/01-getting-started/01_first-application.tsx +26 -0
  177. package/docs/01-getting-started/20_styling.tsx +6 -0
  178. package/docs/01-getting-started/index.md +27 -0
  179. package/docs/01-getting-started/styles.css +1 -0
  180. package/docs/02-guides/01-server-functions/10_ersc.ts +6 -0
  181. package/docs/02-guides/01-server-functions/20_follow-author.ts +15 -0
  182. package/docs/02-guides/01-server-functions/30_follow-author-button.tsx +19 -0
  183. package/docs/02-guides/01-server-functions/40_application.tsx +30 -0
  184. package/docs/02-guides/01-server-functions/index.md +19 -0
  185. package/docs/02-guides/02-services/10_catalog.ts +22 -0
  186. package/docs/02-guides/02-services/20_application.tsx +44 -0
  187. package/docs/02-guides/02-services/index.md +17 -0
  188. package/docs/02-guides/03-routing/10_ersc.ts +6 -0
  189. package/docs/02-guides/03-routing/10_layouts.tsx +36 -0
  190. package/docs/02-guides/03-routing/20_pages.tsx +23 -0
  191. package/docs/02-guides/03-routing/30_routes.tsx +17 -0
  192. package/docs/02-guides/03-routing/40_application.ts +7 -0
  193. package/docs/02-guides/03-routing/index.md +22 -0
  194. package/docs/02-guides/04-middleware/10_auth.ts +27 -0
  195. package/docs/02-guides/04-middleware/20_account-page.tsx +13 -0
  196. package/docs/02-guides/04-middleware/30_update-profile.ts +16 -0
  197. package/docs/02-guides/04-middleware/40_application.tsx +20 -0
  198. package/docs/02-guides/04-middleware/index.md +25 -0
  199. package/docs/02-guides/05-http/10_application-layer.tsx +60 -0
  200. package/docs/02-guides/05-http/index.md +23 -0
  201. package/docs/02-guides/index.md +11 -0
  202. package/docs/03-advanced/01-request-runtime-and-lifetimes/index.md +13 -0
  203. package/docs/03-advanced/02-client-navigation/index.md +61 -0
  204. package/docs/03-advanced/03-server-function-execution-and-refresh/index.md +17 -0
  205. package/docs/03-advanced/index.md +11 -0
  206. package/docs/04-api-reference/01-application/index.md +8 -0
  207. package/docs/04-api-reference/02-page/index.md +12 -0
  208. package/docs/04-api-reference/03-layout/index.md +4 -0
  209. package/docs/04-api-reference/04-loading/index.md +4 -0
  210. package/docs/04-api-reference/05-component/10_component.tsx +18 -0
  211. package/docs/04-api-reference/05-component/index.md +10 -0
  212. package/docs/04-api-reference/06-middleware/index.md +33 -0
  213. package/docs/04-api-reference/07-routes/index.md +20 -0
  214. package/docs/04-api-reference/08-server-fn/index.md +43 -0
  215. package/docs/04-api-reference/index.md +17 -0
  216. package/docs/environment.d.ts +1 -0
  217. package/docs/index.md +15 -0
  218. package/logo-dark.svg +6 -0
  219. package/logo.svg +6 -0
  220. package/package.json +87 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server/flight-html-stream.js","sources":["../../src/server/flight-html-stream.ts"],"sourcesContent":["// Adapted from rsc-html-stream by Devon Govett.\n// Copyright (c) 2024-present Devon Govett. Licensed under the MIT License; see vendor/rsc-html-stream/LICENSE.\nimport { Context, Effect, Layer } from 'effect';\n\nconst Encoder = new TextEncoder();\nconst HtmlTrailer = Encoder.encode('</body></html>');\nconst EmptyBytes = new Uint8Array();\n\ntype StreamController = TransformStreamDefaultController<Uint8Array>;\n\nexport type FlightHtmlStreamOptions = {\n readonly nonce?: string;\n};\n\nconst trailerPrefixLength = (bytes: Uint8Array) => {\n const maximumLength = Math.min(bytes.byteLength, HtmlTrailer.byteLength);\n for (let length = maximumLength; length > 0; length -= 1) {\n const offset = bytes.byteLength - length;\n let matches = true;\n for (let index = 0; index < length; index += 1) {\n if (bytes[offset + index] !== HtmlTrailer[index]) {\n matches = false;\n break;\n }\n }\n if (matches) {\n return length;\n }\n }\n return 0;\n};\n\nconst escapeInlineScript = (script: string) =>\n script.replace(/<!--|<\\/script/gi, (match) =>\n match === '<!--' ? '<\\\\!--' : `</\\\\${match.slice(2)}`,\n );\n\nconst writeFlightValue = (\n value: string,\n controller: StreamController,\n nonce: string | undefined,\n) => {\n const script = escapeInlineScript(`(self.__FLIGHT_DATA||=[]).push(${value})`);\n const nonceAttribute = nonce === undefined ? '' : ` nonce=\"${nonce}\"`;\n controller.enqueue(Encoder.encode(`<script${nonceAttribute}>${script}</script>`));\n};\n\nconst writeFlightChunk = (\n decoder: TextDecoder,\n chunk: Uint8Array,\n controller: StreamController,\n nonce: string | undefined,\n) => {\n try {\n const text = decoder.decode(chunk);\n if (text.length > 0) {\n writeFlightValue(JSON.stringify(text), controller, nonce);\n }\n } catch {\n const base64 = JSON.stringify(chunk.toBase64());\n writeFlightValue(\n `Uint8Array.from(atob(${base64}),character=>character.codePointAt(0))`,\n controller,\n nonce,\n );\n }\n};\n\nconst writeFlightStream = (\n stream: ReadableStream<Uint8Array>,\n controller: StreamController,\n nonce: string | undefined,\n): Promise<void> => {\n const decoder = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });\n const reader = stream.getReader();\n let released = false;\n const release = () => {\n if (!released) {\n released = true;\n reader.releaseLock();\n }\n };\n const cancel = (cause: unknown): Promise<never> => {\n let cancellation: Promise<void>;\n try {\n cancellation = reader.cancel(cause);\n } catch {\n release();\n return Promise.reject(cause);\n }\n return cancellation.then(\n () => {\n release();\n return Promise.reject(cause);\n },\n () => {\n release();\n return Promise.reject(cause);\n },\n );\n };\n const handle = (result: Bun.ReadableStreamDefaultReadManyResult<Uint8Array>): Promise<void> => {\n if (result.done) {\n release();\n return Promise.resolve();\n }\n try {\n for (const chunk of result.value) {\n writeFlightChunk(decoder, chunk, controller, nonce);\n }\n } catch (cause) {\n return cancel(cause);\n }\n return read();\n };\n const read = (): Promise<void> => {\n let result:\n | Bun.ReadableStreamDefaultReadManyResult<Uint8Array>\n | Promise<Bun.ReadableStreamDefaultReadManyResult<Uint8Array>>;\n try {\n result = reader.readMany();\n } catch (cause) {\n return cancel(cause);\n }\n return 'then' in result ? result.then(handle, cancel) : handle(result);\n };\n\n return read();\n};\n\nconst makeHtmlWriter = () => {\n let tail = EmptyBytes;\n\n return {\n finish(controller: StreamController) {\n if (tail.byteLength !== HtmlTrailer.byteLength && tail.byteLength > 0) {\n controller.enqueue(tail);\n }\n controller.enqueue(HtmlTrailer);\n },\n write(chunks: ReadonlyArray<Uint8Array>, controller: StreamController) {\n if (chunks.length === 0) {\n return;\n }\n const byteLength = chunks.reduce((total, chunk) => total + chunk.byteLength, tail.byteLength);\n const combined = new Uint8Array(byteLength);\n combined.set(tail);\n let offset = tail.byteLength;\n for (const chunk of chunks) {\n combined.set(chunk, offset);\n offset += chunk.byteLength;\n }\n\n const bodyLength = combined.byteLength - trailerPrefixLength(combined);\n if (bodyLength > 0) {\n controller.enqueue(combined.subarray(0, bodyLength));\n }\n tail = combined.slice(bodyLength);\n },\n };\n};\n\nexport const injectFlightPayload = (\n flightStream: ReadableStream<Uint8Array>,\n options?: FlightHtmlStreamOptions,\n) => {\n const htmlWriter = makeHtmlWriter();\n const bufferedHtml: Array<Uint8Array> = [];\n const flightCompletion = Promise.withResolvers<void>();\n let flightStarted = false;\n let flushScheduled = false;\n\n const fail = (controller: StreamController, cause: unknown) => {\n try {\n controller.error(cause);\n } finally {\n flightCompletion.resolve();\n }\n };\n const flushHtml = (controller: StreamController) => {\n htmlWriter.write(bufferedHtml, controller);\n bufferedHtml.length = 0;\n };\n const startFlight = (controller: StreamController) => {\n if (flightStarted) {\n return;\n }\n flightStarted = true;\n writeFlightStream(flightStream, controller, options?.nonce).then(\n flightCompletion.resolve,\n (cause: unknown) => fail(controller, cause),\n );\n };\n const flushAndStartFlight = (controller: StreamController) => {\n try {\n flushHtml(controller);\n startFlight(controller);\n } catch (cause) {\n fail(controller, cause);\n }\n };\n\n return new TransformStream<Uint8Array, Uint8Array>({\n flush(controller) {\n if (flushScheduled) {\n flushScheduled = false;\n flushHtml(controller);\n }\n startFlight(controller);\n return flightCompletion.promise.then(() => htmlWriter.finish(controller));\n },\n transform(chunk, controller) {\n bufferedHtml.push(chunk);\n if (!flushScheduled) {\n flushScheduled = true;\n void Bun.sleep(0).then(() => {\n if (flushScheduled) {\n flushScheduled = false;\n flushAndStartFlight(controller);\n }\n });\n }\n },\n });\n};\n\nexport class FlightHtmlInjector extends Context.Service<FlightHtmlInjector>()(\n 'ersc/server/flight-html-stream/FlightHtmlInjector',\n {\n make: Effect.succeed({ inject: injectFlightPayload }),\n },\n) {\n static readonly layer = Layer.effect(this, this.make);\n\n static readonly layerTest = Layer.mock(this);\n}\n"],"names":["Context","Effect","Layer","Encoder","TextEncoder","HtmlTrailer","EmptyBytes","Uint8Array","trailerPrefixLength","bytes","maximumLength","Math","length","offset","matches","index","escapeInlineScript","script","match","writeFlightValue","value","controller","nonce","nonceAttribute","undefined","writeFlightChunk","decoder","chunk","text","JSON","base64","writeFlightStream","stream","TextDecoder","reader","released","release","cancel","cause","cancellation","Promise","handle","result","read","makeHtmlWriter","tail","chunks","byteLength","total","combined","bodyLength","injectFlightPayload","flightStream","options","htmlWriter","bufferedHtml","flightCompletion","flightStarted","flushScheduled","fail","flushHtml","startFlight","flushAndStartFlight","TransformStream","Bun","FlightHtmlInjector"],"mappings":";;;AAAA,gDAAgD;AAChD,+GAA+G;AAC/D;AAEhD,MAAMG,OAAOA,GAAG,IAAIC;AACpB,MAAMC,WAAWA,GAAGF,OAAOA,CAAC,MAAM,CAAC;AACnC,MAAMG,UAAUA,GAAG,IAAIC;AAQvB,MAAMC,mBAAmBA,GAAG,CAACC;IAC3B,MAAMC,gBAAgBC,KAAK,GAAG,CAACF,MAAM,UAAU,EAAEJ,WAAWA,CAAC,UAAU;IACvE,IAAK,IAAIO,SAASF,eAAeE,SAAS,GAAGA,UAAU,EAAG;QACxD,MAAMC,SAASJ,MAAM,UAAU,GAAGG;QAClC,IAAIE,UAAU;QACd,IAAK,IAAIC,QAAQ,GAAGA,QAAQH,QAAQG,SAAS,EAAG;YAC9C,IAAIN,KAAK,CAACI,SAASE,MAAM,KAAKV,WAAW,CAACU,MAAM,EAAE;gBAChDD,UAAU;gBACV;YACF;QACF;QACA,IAAIA,SAAS;YACX,OAAOF;QACT;IACF;IACA,OAAO;AACT;AAEA,MAAMI,kBAAkBA,GAAG,CAACC,SAC1BA,OAAO,OAAO,CAAC,oBAAoB,CAACC,QAClCA,UAAU,SAAS,WAAW,CAAC,IAAI,EAAEA,MAAM,KAAK,CAAC,IAAI;AAGzD,MAAMC,gBAAgBA,GAAG,CACvBC,OACAC,YACAC;IAEA,MAAML,SAASD,kBAAkBA,CAAC,CAAC,+BAA+B,EAAEI,MAAM,CAAC,CAAC;IAC5E,MAAMG,iBAAiBD,UAAUE,YAAY,KAAK,CAAC,QAAQ,EAAEF,MAAM,CAAC,CAAC;IACrED,WAAW,OAAO,CAAClB,OAAOA,CAAC,MAAM,CAAC,CAAC,OAAO,EAAEoB,eAAe,CAAC,EAAEN,OAAO,SAAS,CAAC;AACjF;AAEA,MAAMQ,gBAAgBA,GAAG,CACvBC,SACAC,OACAN,YACAC;IAEA,IAAI;QACF,MAAMM,OAAOF,QAAQ,MAAM,CAACC;QAC5B,IAAIC,KAAK,MAAM,GAAG,GAAG;YACnBT,gBAAgBA,CAACU,KAAK,SAAS,CAACD,OAAOP,YAAYC;QACrD;IACF,EAAE,OAAM;QACN,MAAMQ,SAASD,KAAK,SAAS,CAACF,MAAM,QAAQ;QAC5CR,gBAAgBA,CACd,CAAC,qBAAqB,EAAEW,OAAO,sCAAsC,CAAC,EACtET,YACAC;IAEJ;AACF;AAEA,MAAMS,iBAAiBA,GAAG,CACxBC,QACAX,YACAC;IAEA,MAAMI,UAAU,IAAIO,YAAY,SAAS;QAAE,OAAO;QAAM,WAAW;IAAK;IACxE,MAAMC,SAASF,OAAO,SAAS;IAC/B,IAAIG,WAAW;IACf,MAAMC,UAAU;QACd,IAAI,CAACD,UAAU;YACbA,WAAW;YACXD,OAAO,WAAW;QACpB;IACF;IACA,MAAMG,SAAS,CAACC;QACd,IAAIC;QACJ,IAAI;YACFA,eAAeL,OAAO,MAAM,CAACI;QAC/B,EAAE,OAAM;YACNF;YACA,OAAOI,QAAQ,MAAM,CAACF;QACxB;QACA,OAAOC,aAAa,IAAI,CACtB;YACEH;YACA,OAAOI,QAAQ,MAAM,CAACF;QACxB,GACA;YACEF;YACA,OAAOI,QAAQ,MAAM,CAACF;QACxB;IAEJ;IACA,MAAMG,SAAS,CAACC;QACd,IAAIA,OAAO,IAAI,EAAE;YACfN;YACA,OAAOI,QAAQ,OAAO;QACxB;QACA,IAAI;YACF,KAAK,MAAMb,SAASe,OAAO,KAAK,CAAE;gBAChCjB,gBAAgBA,CAACC,SAASC,OAAON,YAAYC;YAC/C;QACF,EAAE,OAAOgB,OAAO;YACd,OAAOD,OAAOC;QAChB;QACA,OAAOK;IACT;IACA,MAAMA,OAAO;QACX,IAAID;QAGJ,IAAI;YACFA,SAASR,OAAO,QAAQ;QAC1B,EAAE,OAAOI,OAAO;YACd,OAAOD,OAAOC;QAChB;QACA,OAAO,UAAUI,SAASA,OAAO,IAAI,CAACD,QAAQJ,UAAUI,OAAOC;IACjE;IAEA,OAAOC;AACT;AAEA,MAAMC,cAAcA,GAAG;IACrB,IAAIC,OAAOvC,UAAUA;IAErB,OAAO;QACL,QAAOe,UAA4B;YACjC,IAAIwB,KAAK,UAAU,KAAKxC,WAAWA,CAAC,UAAU,IAAIwC,KAAK,UAAU,GAAG,GAAG;gBACrExB,WAAW,OAAO,CAACwB;YACrB;YACAxB,WAAW,OAAO,CAAChB,WAAWA;QAChC;QACA,OAAMyC,MAAiC,EAAEzB,UAA4B;YACnE,IAAIyB,OAAO,MAAM,KAAK,GAAG;gBACvB;YACF;YACA,MAAMC,aAAaD,OAAO,MAAM,CAAC,CAACE,OAAOrB,QAAUqB,QAAQrB,MAAM,UAAU,EAAEkB,KAAK,UAAU;YAC5F,MAAMI,WAAW,IAAI1C,WAAWwC;YAChCE,SAAS,GAAG,CAACJ;YACb,IAAIhC,SAASgC,KAAK,UAAU;YAC5B,KAAK,MAAMlB,SAASmB,OAAQ;gBAC1BG,SAAS,GAAG,CAACtB,OAAOd;gBACpBA,UAAUc,MAAM,UAAU;YAC5B;YAEA,MAAMuB,aAAaD,SAAS,UAAU,GAAGzC,mBAAmBA,CAACyC;YAC7D,IAAIC,aAAa,GAAG;gBAClB7B,WAAW,OAAO,CAAC4B,SAAS,QAAQ,CAAC,GAAGC;YAC1C;YACAL,OAAOI,SAAS,KAAK,CAACC;QACxB;IACF;AACF;AAEO,MAAMC,mBAAmBA,GAAG,CACjCC,cACAC;IAEA,MAAMC,aAAaV,cAAcA;IACjC,MAAMW,eAAkC,EAAE;IAC1C,MAAMC,mBAAmBhB,QAAQ,aAAa;IAC9C,IAAIiB,gBAAgB;IACpB,IAAIC,iBAAiB;IAErB,MAAMC,OAAO,CAACtC,YAA8BiB;QAC1C,IAAI;YACFjB,WAAW,KAAK,CAACiB;QACnB,SAAU;YACRkB,iBAAiB,OAAO;QAC1B;IACF;IACA,MAAMI,YAAY,CAACvC;QACjBiC,WAAW,KAAK,CAACC,cAAclC;QAC/BkC,aAAa,MAAM,GAAG;IACxB;IACA,MAAMM,cAAc,CAACxC;QACnB,IAAIoC,eAAe;YACjB;QACF;QACAA,gBAAgB;QAChB1B,iBAAiBA,CAACqB,cAAc/B,YAAYgC,SAAS,OAAO,IAAI,CAC9DG,iBAAiB,OAAO,EACxB,CAAClB,QAAmBqB,KAAKtC,YAAYiB;IAEzC;IACA,MAAMwB,sBAAsB,CAACzC;QAC3B,IAAI;YACFuC,UAAUvC;YACVwC,YAAYxC;QACd,EAAE,OAAOiB,OAAO;YACdqB,KAAKtC,YAAYiB;QACnB;IACF;IAEA,OAAO,IAAIyB,gBAAwC;QACjD,OAAM1C,UAAU;YACd,IAAIqC,gBAAgB;gBAClBA,iBAAiB;gBACjBE,UAAUvC;YACZ;YACAwC,YAAYxC;YACZ,OAAOmC,iBAAiB,OAAO,CAAC,IAAI,CAAC,IAAMF,WAAW,MAAM,CAACjC;QAC/D;QACA,WAAUM,KAAK,EAAEN,UAAU;YACzBkC,aAAa,IAAI,CAAC5B;YAClB,IAAI,CAAC+B,gBAAgB;gBACnBA,iBAAiB;gBACjB,KAAKM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC;oBACrB,IAAIN,gBAAgB;wBAClBA,iBAAiB;wBACjBI,oBAAoBzC;oBACtB;gBACF;YACF;QACF;IACF;AACF,EAAE;AAEK,MAAM4C,kBAAkBA,SAASjE,eAAe,GACrD,qDACA;IACE,MAAMC,cAAc,CAAC;QAAE,QAAQkD,mBAAmBA;IAAC;AACrD;IAEA,OAAgB,QAAQjD,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;IAEtD,OAAgB,YAAYA,UAAU,CAAC,IAAI,EAAE;AAC/C"}
@@ -0,0 +1,31 @@
1
+ import { Context, Effect, Layer, Scope } from 'effect';
2
+ import type { TemporaryReferenceSet } from 'react-server-dom-rspack/server.node';
3
+ import type { AnyMiddleware } from '../application/middleware.js';
4
+ import type { RenderRuntimeContext } from '../application/render-runtime.js';
5
+ import type { FlightPayload, ServerFnResult } from '../rsc/flight.js';
6
+ import type { RouteTreeModel } from '../rsc/route-tree.js';
7
+ type FlightStream = ReadableStream<Uint8Array>;
8
+ export type FlightRender = {
9
+ readonly release: Effect.Effect<void>;
10
+ readonly signal: AbortSignal;
11
+ readonly stream: FlightStream;
12
+ };
13
+ export type FlightRenderOptions<Services> = {
14
+ readonly formState: FlightPayload['formState'];
15
+ readonly middleware: ReadonlyArray<AnyMiddleware<Services>>;
16
+ readonly renderRuntime: RenderRuntimeContext;
17
+ readonly routeTree: RouteTreeModel;
18
+ readonly serverFnResult: ServerFnResult | null;
19
+ readonly temporaryReferences?: TemporaryReferenceSet;
20
+ };
21
+ declare const FlightRenderer_base: Context.ServiceClass<FlightRenderer, "ersc/server/flight-renderer/FlightRenderer", {
22
+ render: <Services>(args_0: FlightRenderOptions<Services>) => Effect.Effect<FlightRender, never, Services | Scope.Scope>;
23
+ }> & {
24
+ readonly make: Effect.Effect<{
25
+ render: <Services>(args_0: FlightRenderOptions<Services>) => Effect.Effect<FlightRender, never, Services | Scope.Scope>;
26
+ }, never, never>;
27
+ };
28
+ export declare class FlightRenderer extends FlightRenderer_base {
29
+ static readonly layer: Layer.Layer<FlightRenderer, never, never>;
30
+ }
31
+ export {};
@@ -0,0 +1,47 @@
1
+ import { Context, Effect, Exit, FiberSet, Layer, Scope } from "effect";
2
+ import { renderToReadableStream } from "react-server-dom-rspack/server.node";
3
+
4
+
5
+
6
+
7
+
8
+ class FlightRenderer extends Context.Service()('ersc/server/flight-renderer/FlightRenderer', {
9
+ make: Effect.succeed({
10
+ render: Effect.fn('FlightRenderer.render')(function*({ formState, middleware, renderRuntime, routeTree, serverFnResult, temporaryReferences }) {
11
+ const parentScope = yield* Effect.scope;
12
+ const renderScope = yield* Scope.fork(parentScope);
13
+ const release = Scope.close(renderScope, Exit["void"]);
14
+ return yield* Effect.gen(function*() {
15
+ const runtime = yield* FiberSet.makeRuntimePromise().pipe(Scope.provide(renderScope));
16
+ const signal = yield* Effect.abortSignal.pipe(Scope.provide(renderScope));
17
+ const stream = renderRuntime.bind(runtime, middleware, ()=>{
18
+ const payload = {
19
+ formState,
20
+ routeTree,
21
+ serverFnResult
22
+ };
23
+ return renderToReadableStream(payload, {
24
+ onError: (error)=>{
25
+ if (!signal.aborted) {
26
+ void runtime(Effect.logError(error));
27
+ }
28
+ },
29
+ signal,
30
+ temporaryReferences
31
+ });
32
+ });
33
+ return {
34
+ release,
35
+ signal,
36
+ stream
37
+ };
38
+ }).pipe(Effect.onError(()=>release));
39
+ })
40
+ })
41
+ }) {
42
+ static layer = Layer.effect(this, this.make);
43
+ }
44
+
45
+ export { FlightRenderer };
46
+
47
+ //# sourceMappingURL=flight-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server/flight-renderer.js","sources":["../../src/server/flight-renderer.tsx"],"sourcesContent":["import { Context, Effect, Exit, FiberSet, Layer, Scope } from 'effect';\nimport type { TemporaryReferenceSet } from 'react-server-dom-rspack/server.node';\nimport { renderToReadableStream } from 'react-server-dom-rspack/server.node';\n\nimport type { AnyMiddleware } from '../application/middleware';\nimport type { RenderRuntimeContext } from '../application/render-runtime';\nimport type { FlightPayload, ServerFnResult } from '../rsc/flight';\nimport type { RouteTreeModel } from '../rsc/route-tree';\n\ntype FlightStream = ReadableStream<Uint8Array>;\n\nexport type FlightRender = {\n readonly release: Effect.Effect<void>;\n readonly signal: AbortSignal;\n readonly stream: FlightStream;\n};\n\nexport type FlightRenderOptions<Services> = {\n readonly formState: FlightPayload['formState'];\n readonly middleware: ReadonlyArray<AnyMiddleware<Services>>;\n readonly renderRuntime: RenderRuntimeContext;\n readonly routeTree: RouteTreeModel;\n readonly serverFnResult: ServerFnResult | null;\n readonly temporaryReferences?: TemporaryReferenceSet;\n};\n\nexport class FlightRenderer extends Context.Service<FlightRenderer>()(\n 'ersc/server/flight-renderer/FlightRenderer',\n {\n make: Effect.succeed({\n render: Effect.fn('FlightRenderer.render')(function* <Services>({\n formState,\n middleware,\n renderRuntime,\n routeTree,\n serverFnResult,\n temporaryReferences,\n }: FlightRenderOptions<Services>): Effect.fn.Return<\n FlightRender,\n never,\n Services | Scope.Scope\n > {\n const parentScope = yield* Effect.scope;\n const renderScope = yield* Scope.fork(parentScope);\n const release = Scope.close(renderScope, Exit.void);\n return yield* Effect.gen(function* () {\n const runtime = yield* FiberSet.makeRuntimePromise<Services>().pipe(\n Scope.provide(renderScope),\n );\n const signal = yield* Effect.abortSignal.pipe(Scope.provide(renderScope));\n const stream = renderRuntime.bind(runtime, middleware, () => {\n const payload = { formState, routeTree, serverFnResult } satisfies FlightPayload;\n return renderToReadableStream(payload, {\n onError: (error) => {\n if (!signal.aborted) {\n void runtime(Effect.logError(error));\n }\n },\n signal,\n temporaryReferences,\n });\n });\n return { release, signal, stream } satisfies FlightRender;\n }).pipe(Effect.onError(() => release));\n }),\n }),\n },\n) {\n static readonly layer = Layer.effect(this, this.make);\n}\n"],"names":["Context","Effect","Exit","FiberSet","Layer","Scope","renderToReadableStream","FlightRenderer","formState","middleware","renderRuntime","routeTree","serverFnResult","temporaryReferences","parentScope","renderScope","release","runtime","signal","stream","payload","error"],"mappings":";;;;;AAAuE;AAEM;AAwBtE,MAAMO,cAAcA,SAASP,eAAe,GACjD,8CACA;IACE,MAAMC,cAAc,CAAC;QACnB,QAAQA,SAAS,CAAC,yBAAyB,UAAqB,EAC9DO,SAAS,EACTC,UAAU,EACVC,aAAa,EACbC,SAAS,EACTC,cAAc,EACdC,mBAAmB,EACW;YAK9B,MAAMC,cAAc,OAAOb,YAAY;YACvC,MAAMc,cAAc,OAAOV,UAAU,CAACS;YACtC,MAAME,UAAUX,WAAW,CAACU,aAAab,YAAS;YAClD,OAAO,OAAOD,UAAU,CAAC;gBACvB,MAAMgB,UAAU,OAAOd,2BAA2B,GAAa,IAAI,CACjEE,aAAa,CAACU;gBAEhB,MAAMG,SAAS,OAAOjB,uBAAuB,CAACI,aAAa,CAACU;gBAC5D,MAAMI,SAAST,cAAc,IAAI,CAACO,SAASR,YAAY;oBACrD,MAAMW,UAAU;wBAAEZ;wBAAWG;wBAAWC;oBAAe;oBACvD,OAAON,sBAAsBA,CAACc,SAAS;wBACrC,SAAS,CAACC;4BACR,IAAI,CAACH,OAAO,OAAO,EAAE;gCACnB,KAAKD,QAAQhB,eAAe,CAACoB;4BAC/B;wBACF;wBACAH;wBACAL;oBACF;gBACF;gBACA,OAAO;oBAAEG;oBAASE;oBAAQC;gBAAO;YACnC,GAAG,IAAI,CAAClB,cAAc,CAAC,IAAMe;QAC/B;IACF;AACF;IAEA,OAAgB,QAAQZ,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;AACxD"}
@@ -0,0 +1,28 @@
1
+ import { Context, Effect, Layer, Schema, type Scope } from 'effect';
2
+ import type { FlightPayload } from '../rsc/flight.js';
3
+ import { FlightHtmlInjector } from './flight-html-stream.js';
4
+ import type { FlightRender } from './flight-renderer.js';
5
+ import { ServerConfig } from './server-config.js';
6
+ type HtmlStream = ReadableStream<Uint8Array>;
7
+ declare const HtmlRenderError_base: Schema.Class<HtmlRenderError, Schema.TaggedStruct<"HtmlRenderError", {
8
+ readonly cause: Schema.Defect;
9
+ }>, import("effect/Cause").YieldableError>;
10
+ export declare class HtmlRenderError extends HtmlRenderError_base {
11
+ }
12
+ declare const HtmlRenderer_base: Context.ServiceClass<HtmlRenderer, "ersc/server/html-renderer/HtmlRenderer", {
13
+ render: (args_0: {
14
+ readonly flight: FlightRender;
15
+ readonly formState: FlightPayload['formState'];
16
+ }) => Effect.Effect<HtmlStream, HtmlRenderError, Scope.Scope>;
17
+ }> & {
18
+ readonly make: Effect.Effect<{
19
+ render: (args_0: {
20
+ readonly flight: FlightRender;
21
+ readonly formState: FlightPayload['formState'];
22
+ }) => Effect.Effect<HtmlStream, HtmlRenderError, Scope.Scope>;
23
+ }, never, FlightHtmlInjector | ServerConfig>;
24
+ };
25
+ export declare class HtmlRenderer extends HtmlRenderer_base {
26
+ static readonly layer: Layer.Layer<HtmlRenderer, never, FlightHtmlInjector | ServerConfig>;
27
+ }
28
+ export {};
@@ -0,0 +1,82 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { Context, Effect, FiberSet, Layer, Schema } from "effect";
3
+ import { use } from "react";
4
+ import { renderToReadableStream } from "react-dom/server.bun";
5
+ import { createFromReadableStream } from "react-server-dom-rspack/client";
6
+ import { RouteTree } from "../client/route-tree.js";
7
+ import { FlightHtmlInjector } from "./flight-html-stream.js";
8
+ import { ServerConfig } from "./server-config.js";
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+ class HtmlRenderError extends Schema.TaggedError()('HtmlRenderError', {
27
+ cause: Schema.Defect()
28
+ }) {
29
+ }
30
+ class HtmlRenderer extends Context.Service()('ersc/server/html-renderer/HtmlRenderer', {
31
+ make: Effect.gen(function*() {
32
+ const { clientBootstrapScripts, clientStylesheets } = yield* ServerConfig;
33
+ const flightHtmlInjector = yield* FlightHtmlInjector;
34
+ return {
35
+ render: Effect.fn('HtmlRenderer.render')(function*({ flight, formState }) {
36
+ const signal = yield* Effect.abortSignal;
37
+ const runtime = yield* FiberSet.makeRuntimePromise();
38
+ const [ssrFlightStream, browserFlightStream] = flight.stream.tee();
39
+ let payload = null;
40
+ function SsrRoot() {
41
+ const { routeTree } = use(payload ??= createFromReadableStream(ssrFlightStream));
42
+ return /*#__PURE__*/ jsx(RouteTree, {
43
+ root: routeTree
44
+ });
45
+ }
46
+ const htmlStream = yield* Effect.tryPromise({
47
+ try: ()=>renderToReadableStream(/*#__PURE__*/ jsxs(Fragment, {
48
+ children: [
49
+ clientStylesheets.map((href)=>/*#__PURE__*/ jsx("link", {
50
+ rel: "stylesheet",
51
+ href: href,
52
+ precedence: "default"
53
+ }, href)),
54
+ /*#__PURE__*/ jsx(SsrRoot, {})
55
+ ]
56
+ }), {
57
+ bootstrapScripts: [
58
+ ...clientBootstrapScripts
59
+ ],
60
+ formState,
61
+ onError: (error, errorInfo)=>{
62
+ if (!signal.aborted && !flight.signal.aborted) {
63
+ void runtime(Effect.logError('HTML render failed.', error, errorInfo.componentStack));
64
+ }
65
+ },
66
+ signal
67
+ }),
68
+ catch: (cause)=>new HtmlRenderError({
69
+ cause
70
+ })
71
+ });
72
+ return htmlStream.pipeThrough(flightHtmlInjector.inject(browserFlightStream));
73
+ })
74
+ };
75
+ })
76
+ }) {
77
+ static layer = Layer.effect(this, this.make);
78
+ }
79
+
80
+ export { HtmlRenderError, HtmlRenderer };
81
+
82
+ //# sourceMappingURL=html-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server/html-renderer.js","sources":["../../src/server/html-renderer.tsx"],"sourcesContent":["import { Context, Effect, FiberSet, Layer, Schema, type Scope } from 'effect';\nimport { use } from 'react';\nimport { renderToReadableStream } from 'react-dom/server.bun';\nimport { createFromReadableStream } from 'react-server-dom-rspack/client';\n\nimport { RouteTree } from '../client/route-tree';\nimport type { FlightPayload } from '../rsc/flight';\nimport { FlightHtmlInjector } from './flight-html-stream';\nimport type { FlightRender } from './flight-renderer';\nimport { ServerConfig } from './server-config';\n\ntype HtmlStream = ReadableStream<Uint8Array>;\n\nexport class HtmlRenderError extends Schema.TaggedError<HtmlRenderError>()('HtmlRenderError', {\n cause: Schema.Defect(),\n}) {}\n\nexport class HtmlRenderer extends Context.Service<HtmlRenderer>()(\n 'ersc/server/html-renderer/HtmlRenderer',\n {\n make: Effect.gen(function* () {\n const { clientBootstrapScripts, clientStylesheets } = yield* ServerConfig;\n const flightHtmlInjector = yield* FlightHtmlInjector;\n\n return {\n render: Effect.fn('HtmlRenderer.render')(function* ({\n flight,\n formState,\n }: {\n readonly flight: FlightRender;\n readonly formState: FlightPayload['formState'];\n }): Effect.fn.Return<HtmlStream, HtmlRenderError, Scope.Scope> {\n const signal = yield* Effect.abortSignal;\n const runtime = yield* FiberSet.makeRuntimePromise<never>();\n const [ssrFlightStream, browserFlightStream] = flight.stream.tee();\n let payload: PromiseLike<FlightPayload> | null = null;\n\n function SsrRoot() {\n const { routeTree } = use(\n (payload ??= createFromReadableStream<FlightPayload>(ssrFlightStream)),\n );\n return <RouteTree root={routeTree} />;\n }\n\n const htmlStream = yield* Effect.tryPromise({\n try: () =>\n renderToReadableStream(\n <>\n {clientStylesheets.map((href) => (\n <link key={href} rel='stylesheet' href={href} precedence='default' />\n ))}\n <SsrRoot />\n </>,\n {\n bootstrapScripts: [...clientBootstrapScripts],\n formState,\n onError: (error, errorInfo) => {\n if (!signal.aborted && !flight.signal.aborted) {\n void runtime(\n Effect.logError('HTML render failed.', error, errorInfo.componentStack),\n );\n }\n },\n signal,\n },\n ),\n catch: (cause) => new HtmlRenderError({ cause }),\n });\n\n return htmlStream.pipeThrough(flightHtmlInjector.inject(browserFlightStream));\n }),\n };\n }),\n },\n) {\n static readonly layer = Layer.effect(this, this.make);\n}\n"],"names":["Context","Effect","FiberSet","Layer","Schema","use","renderToReadableStream","createFromReadableStream","RouteTree","FlightHtmlInjector","ServerConfig","HtmlRenderError","HtmlRenderer","clientBootstrapScripts","clientStylesheets","flightHtmlInjector","flight","formState","signal","runtime","ssrFlightStream","browserFlightStream","payload","SsrRoot","routeTree","htmlStream","href","error","errorInfo","cause"],"mappings":";;;;;;;;;;;;;;;;;;AAA8E;AAClD;AACkC;AACY;AAEzB;AAES;AAEX;AAIxC,MAAMW,eAAeA,SAASP,kBAAkB,GAAoB,mBAAmB;IAC5F,OAAOA,aAAa;AACtB;AAAI;AAEG,MAAMQ,YAAYA,SAASZ,eAAe,GAC/C,0CACA;IACE,MAAMC,UAAU,CAAC;QACf,MAAM,EAAEY,sBAAsB,EAAEC,iBAAiB,EAAE,GAAG,OAAOJ,YAAYA;QACzE,MAAMK,qBAAqB,OAAON,kBAAkBA;QAEpD,OAAO;YACL,QAAQR,SAAS,CAAC,uBAAuB,UAAW,EAClDe,MAAM,EACNC,SAAS,EAIV;gBACC,MAAMC,SAAS,OAAOjB,kBAAkB;gBACxC,MAAMkB,UAAU,OAAOjB,2BAA2B;gBAClD,MAAM,CAACkB,iBAAiBC,oBAAoB,GAAGL,OAAO,MAAM,CAAC,GAAG;gBAChE,IAAIM,UAA6C;gBAEjD,SAASC;oBACP,MAAM,EAAEC,SAAS,EAAE,GAAGnB,GAAGA,CACtBiB,YAAYf,wBAAwBA,CAAgBa;oBAEvD,qBAAO,IAACZ,SAASA;wBAAC,MAAMgB;;gBAC1B;gBAEA,MAAMC,aAAa,OAAOxB,iBAAiB,CAAC;oBAC1C,KAAK,IACHK,sBAAsBA,eACpB;;gCACGQ,kBAAkB,GAAG,CAAC,CAACY,qBACtB,IAAC;wCAAgB,KAAI;wCAAa,MAAMA;wCAAM,YAAW;uCAA9CA;8CAEb,IAACH;;4BAEH;4BACE,kBAAkB;mCAAIV;6BAAuB;4BAC7CI;4BACA,SAAS,CAACU,OAAOC;gCACf,IAAI,CAACV,OAAO,OAAO,IAAI,CAACF,OAAO,MAAM,CAAC,OAAO,EAAE;oCAC7C,KAAKG,QACHlB,eAAe,CAAC,uBAAuB0B,OAAOC,UAAU,cAAc;gCAE1E;4BACF;4BACAV;wBACF;oBAEJ,OAAO,CAACW,QAAU,IAAIlB,eAAeA,CAAC;4BAAEkB;wBAAM;gBAChD;gBAEA,OAAOJ,WAAW,WAAW,CAACV,mBAAmB,MAAM,CAACM;YAC1D;QACF;IACF;AACF;IAEA,OAAgB,QAAQlB,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;AACxD"}
@@ -0,0 +1,8 @@
1
+ import type { TemporaryReferenceSet } from 'react-server-dom-rspack/server.node';
2
+ import type { FlightPayload } from '../rsc/flight.js';
3
+ export type RequestOutcome = {
4
+ readonly formState: FlightPayload['formState'];
5
+ readonly serverFnResult: FlightPayload['serverFnResult'];
6
+ readonly status: 200;
7
+ readonly temporaryReferences?: TemporaryReferenceSet;
8
+ };
@@ -0,0 +1,5 @@
1
+
2
+
3
+ export {};
4
+
5
+ //# sourceMappingURL=request-outcome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server/request-outcome.js","sources":["../../src/server/request-outcome.ts"],"sourcesContent":["import type { TemporaryReferenceSet } from 'react-server-dom-rspack/server.node';\n\nimport type { FlightPayload } from '../rsc/flight';\n\nexport type RequestOutcome = {\n readonly formState: FlightPayload['formState'];\n readonly serverFnResult: FlightPayload['serverFnResult'];\n readonly status: 200;\n readonly temporaryReferences?: TemporaryReferenceSet;\n};\n"],"names":[],"mappings":"AASE"}
@@ -0,0 +1,17 @@
1
+ import { Context } from 'effect';
2
+ export declare const DefaultApplicationPort = 18193;
3
+ export declare const DefaultApplicationHostname = "localhost";
4
+ export declare const ApplicationIdleTimeoutSeconds = 0;
5
+ export declare const ApplicationMaxRequestBodySizeBytes: number;
6
+ declare const ServerConfig_base: Context.ServiceClass<ServerConfig, "ersc/server/server-config/ServerConfig", {
7
+ readonly clientAssetsCacheControl: string;
8
+ readonly clientAssetsRoot: string;
9
+ readonly clientBootstrapScripts: ReadonlyArray<string>;
10
+ readonly clientStylesheets: ReadonlyArray<string>;
11
+ readonly hostname: string;
12
+ readonly port: number;
13
+ readonly publicAssetsRoot: string;
14
+ }>;
15
+ export declare class ServerConfig extends ServerConfig_base {
16
+ }
17
+ export {};
@@ -0,0 +1,18 @@
1
+ import { Context } from "effect";
2
+
3
+
4
+
5
+ const DefaultApplicationPort = 18193;
6
+ const DefaultApplicationHostname = 'localhost';
7
+ // Zero disables Bun's idle timeout, which would otherwise cut a stalled Suspense boundary off at
8
+ // ten seconds. Connection deadlines belong to the deployment's proxy.
9
+ const ApplicationIdleTimeoutSeconds = 0;
10
+ // Bun rejects oversized bodies before they reach the framework router or React's Server Function
11
+ // decoder.
12
+ const ApplicationMaxRequestBodySizeBytes = 10 * 1024 * 1024;
13
+ class ServerConfig extends Context.Service()('ersc/server/server-config/ServerConfig') {
14
+ }
15
+
16
+ export { ApplicationIdleTimeoutSeconds, ApplicationMaxRequestBodySizeBytes, DefaultApplicationHostname, DefaultApplicationPort, ServerConfig };
17
+
18
+ //# sourceMappingURL=server-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server/server-config.js","sources":["../../src/server/server-config.ts"],"sourcesContent":["import { Context } from 'effect';\n\nexport const DefaultApplicationPort = 18193;\nexport const DefaultApplicationHostname = 'localhost';\n\n// Zero disables Bun's idle timeout, which would otherwise cut a stalled Suspense boundary off at\n// ten seconds. Connection deadlines belong to the deployment's proxy.\nexport const ApplicationIdleTimeoutSeconds = 0;\n\n// Bun rejects oversized bodies before they reach the framework router or React's Server Function\n// decoder.\nexport const ApplicationMaxRequestBodySizeBytes = 10 * 1024 * 1024;\n\nexport class ServerConfig extends Context.Service<\n ServerConfig,\n {\n readonly clientAssetsCacheControl: string;\n readonly clientAssetsRoot: string;\n readonly clientBootstrapScripts: ReadonlyArray<string>;\n readonly clientStylesheets: ReadonlyArray<string>;\n readonly hostname: string;\n readonly port: number;\n readonly publicAssetsRoot: string;\n }\n>()('ersc/server/server-config/ServerConfig') {}\n"],"names":["Context","DefaultApplicationPort","DefaultApplicationHostname","ApplicationIdleTimeoutSeconds","ApplicationMaxRequestBodySizeBytes","ServerConfig"],"mappings":";;;AAAiC;AAE1B,MAAMC,sBAAsBA,GAAG,MAAM;AACrC,MAAMC,0BAA0BA,GAAG,YAAY;AAEtD,iGAAiG;AACjG,sEAAsE;AAC/D,MAAMC,6BAA6BA,GAAG,EAAE;AAE/C,iGAAiG;AACjG,WAAW;AACJ,MAAMC,kCAAkCA,GAAG,KAAK,OAAO,KAAK;AAE5D,MAAMC,YAAYA,SAASL,eAAe,GAW7C;AAA2C"}
@@ -0,0 +1,13 @@
1
+ import { Effect } from 'effect';
2
+ export declare const serverFnOutcome: <Output, Error, Requirements>(operation: Effect.Effect<Output, Error, Requirements>) => Effect.Effect<{
3
+ serverFnResult: {
4
+ _tag: "Success";
5
+ value: Output;
6
+ error?: never;
7
+ } | {
8
+ value?: never;
9
+ _tag: "Failure";
10
+ error: unknown;
11
+ };
12
+ status: 200;
13
+ }, never, Requirements>;
@@ -0,0 +1,24 @@
1
+ import { Cause, Effect } from "effect";
2
+
3
+
4
+
5
+ const serverFnOutcome = Effect.fnUntraced(function*(operation) {
6
+ const exit = yield* Effect.exit(operation);
7
+ if (exit._tag === 'Failure' && Cause.hasInterrupts(exit.cause)) {
8
+ return yield* Effect.interrupt;
9
+ }
10
+ return {
11
+ serverFnResult: exit._tag === 'Success' ? {
12
+ _tag: 'Success',
13
+ value: exit.value
14
+ } : {
15
+ _tag: 'Failure',
16
+ error: Cause.squash(exit.cause)
17
+ },
18
+ status: 200
19
+ };
20
+ });
21
+
22
+ export { serverFnOutcome };
23
+
24
+ //# sourceMappingURL=server-fn-outcome.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server/server-fn-outcome.js","sources":["../../src/server/server-fn-outcome.ts"],"sourcesContent":["import { Cause, Effect } from 'effect';\n\nimport type { ServerFnResult } from '../rsc/flight';\nimport type { RequestOutcome } from './request-outcome';\n\nexport const serverFnOutcome = Effect.fnUntraced(function* <Output, Error, Requirements>(\n operation: Effect.Effect<Output, Error, Requirements>,\n) {\n const exit = yield* Effect.exit(operation);\n if (exit._tag === 'Failure' && Cause.hasInterrupts(exit.cause)) {\n return yield* Effect.interrupt;\n }\n\n return {\n serverFnResult:\n exit._tag === 'Success'\n ? ({ _tag: 'Success', value: exit.value } satisfies ServerFnResult)\n : ({ _tag: 'Failure', error: Cause.squash(exit.cause) } satisfies ServerFnResult),\n status: 200,\n } satisfies Pick<RequestOutcome, 'serverFnResult' | 'status'>;\n});\n"],"names":["Cause","Effect","serverFnOutcome","operation","exit"],"mappings":";;;AAAuC;AAKhC,MAAME,eAAeA,GAAGD,iBAAiB,CAAC,UAC/CE,SAAqD;IAErD,MAAMC,OAAO,OAAOH,WAAW,CAACE;IAChC,IAAIC,KAAK,IAAI,KAAK,aAAaJ,mBAAmB,CAACI,KAAK,KAAK,GAAG;QAC9D,OAAO,OAAOH,gBAAgB;IAChC;IAEA,OAAO;QACL,gBACEG,KAAK,IAAI,KAAK,YACT;YAAE,MAAM;YAAW,OAAOA,KAAK,KAAK;QAAC,IACrC;YAAE,MAAM;YAAW,OAAOJ,YAAY,CAACI,KAAK,KAAK;QAAE;QAC1D,QAAQ;IACV;AACF,GAAG"}
@@ -0,0 +1,24 @@
1
+ import { Cause, Effect, Schema } from 'effect';
2
+ import { HttpServerRequest } from 'effect/unstable/http';
3
+ import type { ERSCIdentity } from '../application/ersc-identity.js';
4
+ import type { AnyMiddleware } from '../application/middleware.js';
5
+ import type { RequestOutcome } from './request-outcome.js';
6
+ declare const ServerFnRequestError_base: Schema.Class<ServerFnRequestError, Schema.TaggedStruct<"ServerFnRequestError", {
7
+ readonly cause: Schema.Defect;
8
+ readonly message: Schema.String;
9
+ readonly status: Schema.Literals<readonly [400, 403, 500]>;
10
+ }>, Cause.YieldableError>;
11
+ export declare class ServerFnRequestError extends ServerFnRequestError_base {
12
+ }
13
+ declare const ServerFnExecutionError_base: Schema.Class<ServerFnExecutionError, Schema.TaggedStruct<"ServerFnExecutionError", {
14
+ readonly cause: Schema.Defect;
15
+ }>, Cause.YieldableError>;
16
+ declare class ServerFnExecutionError extends ServerFnExecutionError_base {
17
+ }
18
+ export type PreparedServerFnRequest<ApplicationServices> = {
19
+ readonly execute: Effect.Effect<RequestOutcome, ServerFnRequestError, ApplicationServices>;
20
+ readonly middleware: ReadonlyArray<AnyMiddleware<ApplicationServices>>;
21
+ };
22
+ export declare const prepareServerFnRequest: <Services>(request: HttpServerRequest.HttpServerRequest, identity: ERSCIdentity<Services>) => Effect.Effect<PreparedServerFnRequest<Services>, ServerFnExecutionError | ServerFnRequestError | import("effect/unstable/http/HttpServerError").RequestError, import("effect/Scope").Scope>;
23
+ export type ServerFnRequestFailure = Effect.Error<ReturnType<typeof prepareServerFnRequest>>;
24
+ export {};
@@ -0,0 +1,160 @@
1
+ import { Cause, Effect, Schema } from "effect";
2
+ import { HttpServerRequest } from "effect/unstable/http";
3
+ import { createTemporaryReferenceSet, decodeAction, decodeFormState, decodeReply, loadServerAction } from "react-server-dom-rspack/server.node";
4
+ import { matchServerFnInvocation } from "../application/server-fn.js";
5
+ import { ServerFnIdHeader } from "../rsc/flight.js";
6
+ import { serverFnOutcome } from "./server-fn-outcome.js";
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+ const ServerFnArraySizeLimit = 10000;
21
+ const NoMiddleware = Object.freeze([]);
22
+ class ServerFnRequestError extends Schema.TaggedError()('ServerFnRequestError', {
23
+ cause: Schema.Defect(),
24
+ message: Schema.String,
25
+ status: Schema.Literals([
26
+ 400,
27
+ 403,
28
+ 500
29
+ ])
30
+ }) {
31
+ }
32
+ class ServerFnExecutionError extends Schema.TaggedError()('ServerFnExecutionError', {
33
+ cause: Schema.Defect()
34
+ }) {
35
+ }
36
+ const requestError = (message, status, cause)=>new ServerFnRequestError({
37
+ cause,
38
+ message,
39
+ status
40
+ });
41
+ const bodyReadError = (message, cause)=>requestError(message, 400, cause);
42
+ const normalizeServerFnFailure = (effect)=>effect.pipe(Effect.catchCause((cause)=>Cause.hasInterrupts(cause) ? Effect.interrupt : Effect.fail(new ServerFnExecutionError({
43
+ cause: Cause.squash(cause)
44
+ }))));
45
+ const validateOrigin = (request)=>Effect["try"]({
46
+ try: ()=>{
47
+ const origin = request.headers['origin'];
48
+ if (origin === undefined) {
49
+ throw new Error('The Origin header is missing.');
50
+ }
51
+ const expectedHost = request.headers['host'];
52
+ if (expectedHost === undefined || new URL(origin).host !== expectedHost.toLowerCase()) {
53
+ throw new Error(`Origin "${origin}" does not match host "${expectedHost ?? ''}".`);
54
+ }
55
+ },
56
+ catch: (cause)=>requestError('Rejected a cross-origin Server Function request.', 403, cause)
57
+ });
58
+ const readBody = Effect.fnUntraced(function*(request) {
59
+ if (request.headers.get('content-type')?.toLowerCase().startsWith('multipart/form-data')) {
60
+ return yield* Effect.tryPromise({
61
+ try: ()=>request.formData(),
62
+ catch: (cause)=>bodyReadError('Failed to read the Server Function request body.', cause)
63
+ });
64
+ }
65
+ return yield* Effect.tryPromise({
66
+ try: ()=>request.text(),
67
+ catch: (cause)=>bodyReadError('Failed to read the Server Function request body.', cause)
68
+ });
69
+ });
70
+ const prepareServerFnOperation = (identity, action, args)=>Effect.sync(()=>{
71
+ const invocation = action(...args);
72
+ const match = matchServerFnInvocation(invocation, identity);
73
+ switch(match._tag){
74
+ case 'Match':
75
+ return {
76
+ effect: normalizeServerFnFailure(match.effect),
77
+ middleware: match.middleware
78
+ };
79
+ case 'IdentityMismatch':
80
+ return {
81
+ effect: Effect.die(new TypeError('Server Function was created by a different ERSC module.')),
82
+ middleware: NoMiddleware
83
+ };
84
+ case 'Native':
85
+ return {
86
+ effect: normalizeServerFnFailure(Effect.promise(()=>Promise.resolve(invocation))),
87
+ middleware: NoMiddleware
88
+ };
89
+ }
90
+ }).pipe(normalizeServerFnFailure);
91
+ const prepareClientServerFn = Effect.fnUntraced(function*(request, actionId, identity) {
92
+ const temporaryReferences = createTemporaryReferenceSet();
93
+ const body = yield* readBody(request);
94
+ const args = yield* Effect.tryPromise({
95
+ try: ()=>decodeReply(body, {
96
+ arraySizeLimit: ServerFnArraySizeLimit,
97
+ temporaryReferences
98
+ }),
99
+ catch: (cause)=>requestError('Failed to decode Server Function arguments.', 400, cause)
100
+ });
101
+ const action = yield* Effect["try"]({
102
+ try: ()=>loadServerAction(actionId),
103
+ catch: (cause)=>requestError('The requested Server Function does not exist.', 400, cause)
104
+ });
105
+ const operation = yield* prepareServerFnOperation(identity, action, args);
106
+ const prepared = {
107
+ execute: serverFnOutcome(operation.effect).pipe(Effect.map((outcome)=>({
108
+ formState: null,
109
+ ...outcome,
110
+ temporaryReferences
111
+ }))),
112
+ middleware: operation.middleware
113
+ };
114
+ return prepared;
115
+ });
116
+ const prepareProgressiveServerFn = Effect.fnUntraced(function*(request, identity) {
117
+ const formData = yield* Effect.tryPromise({
118
+ try: ()=>request.formData(),
119
+ catch: (cause)=>bodyReadError('Failed to read the Server Function form body.', cause)
120
+ });
121
+ const decodedAction = yield* Effect.tryPromise({
122
+ try: ()=>Promise.resolve(decodeAction(formData)),
123
+ catch: (cause)=>requestError('Failed to decode the Server Function form action.', 400, cause)
124
+ });
125
+ if (decodedAction === null) {
126
+ return yield* requestError('The submitted form does not contain a Server Function action.', 400, new Error('decodeAction returned null.'));
127
+ }
128
+ const operation = yield* prepareServerFnOperation(identity, decodedAction, []);
129
+ const execute = Effect.gen(function*() {
130
+ const actionResult = yield* operation.effect.pipe(Effect.mapError((error)=>requestError('The Server Function form action failed.', 500, error.cause)));
131
+ const decodedFormState = yield* Effect.tryPromise({
132
+ try: ()=>decodeFormState(actionResult, formData),
133
+ catch: (cause)=>requestError('Failed to decode React form state.', 500, cause)
134
+ });
135
+ return {
136
+ formState: decodedFormState,
137
+ serverFnResult: null,
138
+ status: 200
139
+ };
140
+ });
141
+ const prepared = {
142
+ execute,
143
+ middleware: operation.middleware
144
+ };
145
+ return prepared;
146
+ });
147
+ const prepareServerFnRequest = Effect.fnUntraced(function*(request, identity) {
148
+ yield* validateOrigin(request);
149
+ const signal = yield* Effect.abortSignal;
150
+ const webRequest = yield* HttpServerRequest.toWeb(request, {
151
+ signal
152
+ });
153
+ const actionId = request.headers[ServerFnIdHeader];
154
+ const prepareRequest = actionId === undefined ? prepareProgressiveServerFn(webRequest, identity) : prepareClientServerFn(webRequest, actionId, identity);
155
+ return yield* prepareRequest;
156
+ });
157
+
158
+ export { ServerFnRequestError, prepareServerFnRequest };
159
+
160
+ //# sourceMappingURL=server-fn-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server/server-fn-request.js","sources":["../../src/server/server-fn-request.ts"],"sourcesContent":["import { Cause, Effect, Schema } from 'effect';\nimport { HttpServerRequest } from 'effect/unstable/http';\nimport {\n createTemporaryReferenceSet,\n decodeAction,\n decodeFormState,\n decodeReply,\n loadServerAction,\n} from 'react-server-dom-rspack/server.node';\n\nimport type { ERSCIdentity } from '../application/ersc-identity';\nimport type { AnyMiddleware } from '../application/middleware';\nimport { matchServerFnInvocation } from '../application/server-fn';\nimport { ServerFnIdHeader } from '../rsc/flight';\nimport type { RequestOutcome } from './request-outcome';\nimport { serverFnOutcome } from './server-fn-outcome';\n\nconst ServerFnArraySizeLimit = 10_000;\nconst NoMiddleware = Object.freeze([]);\n\nexport class ServerFnRequestError extends Schema.TaggedError<ServerFnRequestError>()(\n 'ServerFnRequestError',\n {\n cause: Schema.Defect(),\n message: Schema.String,\n status: Schema.Literals([400, 403, 500]),\n },\n) {}\n\nclass ServerFnExecutionError extends Schema.TaggedError<ServerFnExecutionError>()(\n 'ServerFnExecutionError',\n { cause: Schema.Defect() },\n) {}\n\nconst requestError = (message: string, status: 400 | 403 | 500, cause: unknown) =>\n new ServerFnRequestError({ cause, message, status });\n\nconst bodyReadError = (message: string, cause: unknown) => requestError(message, 400, cause);\n\nconst normalizeServerFnFailure = <Output, Error, Services>(\n effect: Effect.Effect<Output, Error, Services>,\n): Effect.Effect<Output, ServerFnExecutionError, Services> =>\n effect.pipe(\n Effect.catchCause((cause) =>\n Cause.hasInterrupts(cause)\n ? Effect.interrupt\n : Effect.fail(new ServerFnExecutionError({ cause: Cause.squash(cause) })),\n ),\n );\n\ntype ServerFnOperation<ApplicationServices> = {\n readonly effect: Effect.Effect<unknown, ServerFnExecutionError, ApplicationServices>;\n readonly middleware: ReadonlyArray<AnyMiddleware<ApplicationServices>>;\n};\n\nexport type PreparedServerFnRequest<ApplicationServices> = {\n readonly execute: Effect.Effect<RequestOutcome, ServerFnRequestError, ApplicationServices>;\n readonly middleware: ReadonlyArray<AnyMiddleware<ApplicationServices>>;\n};\n\nconst validateOrigin = (request: HttpServerRequest.HttpServerRequest) =>\n Effect.try({\n try: () => {\n const origin = request.headers['origin'];\n if (origin === undefined) {\n throw new Error('The Origin header is missing.');\n }\n\n const expectedHost = request.headers['host'];\n if (expectedHost === undefined || new URL(origin).host !== expectedHost.toLowerCase()) {\n throw new Error(`Origin \"${origin}\" does not match host \"${expectedHost ?? ''}\".`);\n }\n },\n catch: (cause) => requestError('Rejected a cross-origin Server Function request.', 403, cause),\n });\n\nconst readBody = Effect.fnUntraced(function* (request: Request) {\n if (request.headers.get('content-type')?.toLowerCase().startsWith('multipart/form-data')) {\n return yield* Effect.tryPromise({\n try: () => request.formData(),\n catch: (cause) => bodyReadError('Failed to read the Server Function request body.', cause),\n });\n }\n\n return yield* Effect.tryPromise({\n try: () => request.text(),\n catch: (cause) => bodyReadError('Failed to read the Server Function request body.', cause),\n });\n});\n\nconst prepareServerFnOperation = <ApplicationServices>(\n identity: ERSCIdentity<ApplicationServices>,\n action: (...args: ReadonlyArray<unknown>) => unknown,\n args: ReadonlyArray<unknown>,\n) =>\n Effect.sync((): ServerFnOperation<ApplicationServices> => {\n const invocation = action(...args);\n const match = matchServerFnInvocation(invocation, identity);\n switch (match._tag) {\n case 'Match':\n return {\n effect: normalizeServerFnFailure(match.effect),\n middleware: match.middleware,\n };\n case 'IdentityMismatch':\n return {\n effect: Effect.die(\n new TypeError('Server Function was created by a different ERSC module.'),\n ),\n middleware: NoMiddleware,\n };\n case 'Native':\n return {\n effect: normalizeServerFnFailure(Effect.promise(() => Promise.resolve(invocation))),\n middleware: NoMiddleware,\n };\n }\n }).pipe(normalizeServerFnFailure);\n\nconst prepareClientServerFn = Effect.fnUntraced(function* <ApplicationServices>(\n request: Request,\n actionId: string,\n identity: ERSCIdentity<ApplicationServices>,\n) {\n const temporaryReferences = createTemporaryReferenceSet();\n const body = yield* readBody(request);\n const args = yield* Effect.tryPromise({\n try: () =>\n decodeReply(body, {\n arraySizeLimit: ServerFnArraySizeLimit,\n temporaryReferences,\n }),\n catch: (cause) => requestError('Failed to decode Server Function arguments.', 400, cause),\n });\n const action = yield* Effect.try({\n try: () => loadServerAction(actionId),\n catch: (cause) => requestError('The requested Server Function does not exist.', 400, cause),\n });\n const operation = yield* prepareServerFnOperation(identity, action, args);\n\n const prepared: PreparedServerFnRequest<ApplicationServices> = {\n execute: serverFnOutcome(operation.effect).pipe(\n Effect.map(\n (outcome) =>\n ({\n formState: null,\n ...outcome,\n temporaryReferences,\n }) satisfies RequestOutcome,\n ),\n ),\n middleware: operation.middleware,\n };\n return prepared;\n});\n\nconst prepareProgressiveServerFn = Effect.fnUntraced(function* <ApplicationServices>(\n request: Request,\n identity: ERSCIdentity<ApplicationServices>,\n) {\n const formData = yield* Effect.tryPromise({\n try: () => request.formData(),\n catch: (cause) => bodyReadError('Failed to read the Server Function form body.', cause),\n });\n const decodedAction = yield* Effect.tryPromise({\n try: () => Promise.resolve(decodeAction(formData)),\n catch: (cause) => requestError('Failed to decode the Server Function form action.', 400, cause),\n });\n if (decodedAction === null) {\n return yield* requestError(\n 'The submitted form does not contain a Server Function action.',\n 400,\n new Error('decodeAction returned null.'),\n );\n }\n\n const operation = yield* prepareServerFnOperation(identity, decodedAction, []);\n const execute = Effect.gen(function* () {\n const actionResult = yield* operation.effect.pipe(\n Effect.mapError((error) =>\n requestError('The Server Function form action failed.', 500, error.cause),\n ),\n );\n const decodedFormState = yield* Effect.tryPromise({\n try: () => decodeFormState(actionResult, formData),\n catch: (cause) => requestError('Failed to decode React form state.', 500, cause),\n });\n\n return {\n formState: decodedFormState,\n serverFnResult: null,\n status: 200,\n } satisfies RequestOutcome;\n });\n\n const prepared: PreparedServerFnRequest<ApplicationServices> = {\n execute,\n middleware: operation.middleware,\n };\n return prepared;\n});\n\nexport const prepareServerFnRequest = Effect.fnUntraced(function* <Services>(\n request: HttpServerRequest.HttpServerRequest,\n identity: ERSCIdentity<Services>,\n) {\n yield* validateOrigin(request);\n const signal = yield* Effect.abortSignal;\n const webRequest = yield* HttpServerRequest.toWeb(request, { signal });\n const actionId = request.headers[ServerFnIdHeader];\n const prepareRequest =\n actionId === undefined\n ? prepareProgressiveServerFn(webRequest, identity)\n : prepareClientServerFn(webRequest, actionId, identity);\n\n return yield* prepareRequest;\n});\n\nexport type ServerFnRequestFailure = Effect.Error<ReturnType<typeof prepareServerFnRequest>>;\n"],"names":["Cause","Effect","Schema","HttpServerRequest","createTemporaryReferenceSet","decodeAction","decodeFormState","decodeReply","loadServerAction","matchServerFnInvocation","ServerFnIdHeader","serverFnOutcome","ServerFnArraySizeLimit","NoMiddleware","Object","ServerFnRequestError","ServerFnExecutionError","requestError","message","status","cause","bodyReadError","normalizeServerFnFailure","effect","validateOrigin","request","origin","undefined","Error","expectedHost","URL","readBody","prepareServerFnOperation","identity","action","args","invocation","match","TypeError","Promise","prepareClientServerFn","actionId","temporaryReferences","body","operation","prepared","outcome","prepareProgressiveServerFn","formData","decodedAction","execute","actionResult","error","decodedFormState","prepareServerFnRequest","signal","webRequest","prepareRequest"],"mappings":"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"}
File without changes
@@ -0,0 +1,5 @@
1
+ throw new TypeError('The "effective-rsc" package can only be imported in a React Server Components environment.');
2
+
3
+ export {};
4
+
5
+ //# sourceMappingURL=unsupported.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unsupported.js","sources":["../src/unsupported.ts"],"sourcesContent":["throw new TypeError(\n 'The \"effective-rsc\" package can only be imported in a React Server Components environment.',\n);\n"],"names":["TypeError"],"mappings":"AAAA,MAAM,IAAIA,UACR"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @title A minimal application
3
+ *
4
+ * Create values from one ERSC identity and close it with ERSC.make.
5
+ */
6
+ import { Effect } from 'effect';
7
+ import { Application } from 'effective-rsc';
8
+
9
+ const ERSC = Application.ersc();
10
+
11
+ const RootLayout = ERSC.Layout.make({
12
+ render: ({ children }) =>
13
+ Effect.succeed(
14
+ <html lang='en'>
15
+ <body>{children}</body>
16
+ </html>,
17
+ ),
18
+ });
19
+
20
+ const HomePage = ERSC.Page.make({
21
+ render: () => Effect.succeed(<h1>Hello from effective-rsc</h1>),
22
+ });
23
+
24
+ export default ERSC.make({
25
+ routes: ERSC.Routes.make({ layout: RootLayout }).page('/', HomePage),
26
+ });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @title Importing styles
3
+ *
4
+ * ERSC has no magic stylesheet entry; import styles from their owning module.
5
+ */
6
+ import './styles.css';