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,101 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Context, Effect, Layer, Schema } from "effect";
3
+ import { Component, StrictMode, useLayoutEffect, useState } from "react";
4
+ import { hydrateRoot } from "react-dom/client";
5
+ import { BrowserEffectRunner } from "./browser-effect-runner.js";
6
+ import { BrowserRenderer } from "./browser-renderer.js";
7
+ import { BrowserFailureScreen } from "./browser-screen.js";
8
+ import { RouteTree } from "./route-tree.js";
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+ class ReactDOMHydrationError extends Schema.TaggedError()('ReactDOMHydrationError', {
27
+ cause: Schema.Defect()
28
+ }) {
29
+ }
30
+ class BrowserErrorBoundary extends Component {
31
+ state = {
32
+ _tag: 'Ready'
33
+ };
34
+ static getDerivedStateFromError() {
35
+ return {
36
+ _tag: 'Failed'
37
+ };
38
+ }
39
+ componentDidCatch(error, info) {
40
+ this.props.onError(error, info);
41
+ }
42
+ render() {
43
+ if (this.state._tag === 'Failed') {
44
+ return /*#__PURE__*/ jsx(BrowserFailureScreen, {});
45
+ }
46
+ return this.props.children;
47
+ }
48
+ }
49
+ class ReactDOMRenderer extends Context.Service()('ersc/client/ReactDOMRenderer', {
50
+ make: Effect.gen(function*() {
51
+ const browserRenderer = yield* BrowserRenderer;
52
+ const run = yield* BrowserEffectRunner;
53
+ const hydrate = Effect.fnUntraced(function*(container, initialPayload) {
54
+ const browserRendererReady = Promise.withResolvers();
55
+ const reportError = (error, info)=>{
56
+ void run(Effect.logError('Uncaught client render error.', error, info.componentStack));
57
+ };
58
+ function Root() {
59
+ const [render, setRender] = useState(()=>({
60
+ _tag: 'Initial',
61
+ routeTree: initialPayload.routeTree
62
+ }));
63
+ useLayoutEffect(()=>{
64
+ browserRenderer.initialize(initialPayload.routeTree, setRender);
65
+ browserRendererReady.resolve();
66
+ }, []);
67
+ useLayoutEffect(()=>{
68
+ browserRenderer.commit(render);
69
+ }, [
70
+ render
71
+ ]);
72
+ return /*#__PURE__*/ jsx(BrowserErrorBoundary, {
73
+ onError: reportError,
74
+ children: /*#__PURE__*/ jsx(RouteTree, {
75
+ root: render.routeTree
76
+ })
77
+ });
78
+ }
79
+ yield* Effect.acquireRelease(Effect["try"]({
80
+ try: ()=>hydrateRoot(container, /*#__PURE__*/ jsx(StrictMode, {
81
+ children: /*#__PURE__*/ jsx(Root, {})
82
+ }), {
83
+ formState: initialPayload.formState
84
+ }),
85
+ catch: (cause)=>new ReactDOMHydrationError({
86
+ cause
87
+ })
88
+ }), (root)=>Effect.sync(()=>root.unmount()));
89
+ yield* Effect.promise(()=>browserRendererReady.promise);
90
+ });
91
+ return {
92
+ hydrate
93
+ };
94
+ })
95
+ }) {
96
+ static layer = Layer.effect(this, this.make);
97
+ }
98
+
99
+ export { ReactDOMHydrationError, ReactDOMRenderer };
100
+
101
+ //# sourceMappingURL=react-dom-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client/react-dom-renderer.js","sources":["../../src/client/react-dom-renderer.tsx"],"sourcesContent":["import { Context, Effect, Layer, Schema } from 'effect';\nimport {\n Component,\n type ErrorInfo,\n type ReactNode,\n StrictMode,\n useLayoutEffect,\n useState,\n} from 'react';\nimport { hydrateRoot } from 'react-dom/client';\n\nimport type { FlightPayload } from '../rsc/flight';\nimport { BrowserEffectRunner } from './browser-effect-runner';\nimport { type BrowserRender, BrowserRenderer } from './browser-renderer';\nimport { BrowserFailureScreen } from './browser-screen';\nimport { RouteTree } from './route-tree';\n\nexport class ReactDOMHydrationError extends Schema.TaggedError<ReactDOMHydrationError>()(\n 'ReactDOMHydrationError',\n { cause: Schema.Defect() },\n) {}\n\ntype BrowserErrorBoundaryState = { readonly _tag: 'Ready' } | { readonly _tag: 'Failed' };\ntype BrowserErrorBoundaryProps = {\n readonly children: ReactNode;\n readonly onError: (error: unknown, info: ErrorInfo) => void;\n};\n\nclass BrowserErrorBoundary extends Component<BrowserErrorBoundaryProps, BrowserErrorBoundaryState> {\n override readonly state: BrowserErrorBoundaryState = { _tag: 'Ready' };\n\n static getDerivedStateFromError(): BrowserErrorBoundaryState {\n return { _tag: 'Failed' };\n }\n\n override componentDidCatch(error: unknown, info: ErrorInfo) {\n this.props.onError(error, info);\n }\n\n override render() {\n if (this.state._tag === 'Failed') {\n return <BrowserFailureScreen />;\n }\n\n return this.props.children;\n }\n}\n\nexport class ReactDOMRenderer extends Context.Service<ReactDOMRenderer>()(\n 'ersc/client/ReactDOMRenderer',\n {\n make: Effect.gen(function* () {\n const browserRenderer = yield* BrowserRenderer;\n const run = yield* BrowserEffectRunner;\n\n const hydrate = Effect.fnUntraced(function* (\n container: Element | Document,\n initialPayload: FlightPayload,\n ) {\n const browserRendererReady = Promise.withResolvers<void>();\n const reportError = (error: unknown, info: ErrorInfo) => {\n void run(Effect.logError('Uncaught client render error.', error, info.componentStack));\n };\n\n function Root() {\n const [render, setRender] = useState<BrowserRender>(() => ({\n _tag: 'Initial',\n routeTree: initialPayload.routeTree,\n }));\n\n useLayoutEffect(() => {\n browserRenderer.initialize(initialPayload.routeTree, setRender);\n browserRendererReady.resolve();\n }, []);\n\n useLayoutEffect(() => {\n browserRenderer.commit(render);\n }, [render]);\n\n return (\n <BrowserErrorBoundary onError={reportError}>\n <RouteTree root={render.routeTree} />\n </BrowserErrorBoundary>\n );\n }\n\n yield* Effect.acquireRelease(\n Effect.try({\n try: () =>\n hydrateRoot(\n container,\n <StrictMode>\n <Root />\n </StrictMode>,\n { formState: initialPayload.formState },\n ),\n catch: (cause) => new ReactDOMHydrationError({ cause }),\n }),\n (root) => Effect.sync(() => root.unmount()),\n );\n yield* Effect.promise(() => browserRendererReady.promise);\n });\n\n return { hydrate };\n }),\n },\n) {\n static readonly layer = Layer.effect(this, this.make);\n}\n"],"names":["Context","Effect","Layer","Schema","Component","StrictMode","useLayoutEffect","useState","hydrateRoot","BrowserEffectRunner","BrowserRenderer","BrowserFailureScreen","RouteTree","ReactDOMHydrationError","BrowserErrorBoundary","error","info","ReactDOMRenderer","browserRenderer","run","hydrate","container","initialPayload","browserRendererReady","Promise","reportError","Root","render","setRender","cause","root"],"mappings":";;;;;;;;;;;;;;;;;;AAAwD;AAQzC;AACgC;AAGe;AACW;AACjB;AACf;AAElC,MAAMa,sBAAsBA,SAASV,kBAAkB,GAC5D,0BACA;IAAE,OAAOA,aAAa;AAAG;AACxB;AAQH,MAAMW,oBAAoBA,SAASV,SAASA;IACxB,QAAmC;QAAE,MAAM;IAAQ,EAAE;IAEvE,OAAO,2BAAsD;QAC3D,OAAO;YAAE,MAAM;QAAS;IAC1B;IAES,kBAAkBW,KAAc,EAAEC,IAAe,EAAE;QAC1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAACD,OAAOC;IAC5B;IAES,SAAS;QAChB,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU;YAChC,qBAAO,IAACL,oBAAoBA;QAC9B;QAEA,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ;IAC5B;AACF;AAEO,MAAMM,gBAAgBA,SAASjB,eAAe,GACnD,gCACA;IACE,MAAMC,UAAU,CAAC;QACf,MAAMiB,kBAAkB,OAAOR,eAAeA;QAC9C,MAAMS,MAAM,OAAOV,mBAAmBA;QAEtC,MAAMW,UAAUnB,iBAAiB,CAAC,UAChCoB,SAA6B,EAC7BC,cAA6B;YAE7B,MAAMC,uBAAuBC,QAAQ,aAAa;YAClD,MAAMC,cAAc,CAACV,OAAgBC;gBACnC,KAAKG,IAAIlB,eAAe,CAAC,iCAAiCc,OAAOC,KAAK,cAAc;YACtF;YAEA,SAASU;gBACP,MAAM,CAACC,QAAQC,UAAU,GAAGrB,QAAQA,CAAgB,IAAO;wBACzD,MAAM;wBACN,WAAWe,eAAe,SAAS;oBACrC;gBAEAhB,eAAeA,CAAC;oBACdY,gBAAgB,UAAU,CAACI,eAAe,SAAS,EAAEM;oBACrDL,qBAAqB,OAAO;gBAC9B,GAAG,EAAE;gBAELjB,eAAeA,CAAC;oBACdY,gBAAgB,MAAM,CAACS;gBACzB,GAAG;oBAACA;iBAAO;gBAEX,qBACE,IAACb,oBAAoBA;oBAAC,SAASW;8BAC7B,kBAACb,SAASA;wBAAC,MAAMe,OAAO,SAAS;;;YAGvC;YAEA,OAAO1B,qBAAqB,CAC1BA,aAAU,CAAC;gBACT,KAAK,IACHO,WAAWA,CACTa,yBACA,IAAChB,UAAUA;kCACT,kBAACqB;wBAEH;wBAAE,WAAWJ,eAAe,SAAS;oBAAC;gBAE1C,OAAO,CAACO,QAAU,IAAIhB,sBAAsBA,CAAC;wBAAEgB;oBAAM;YACvD,IACA,CAACC,OAAS7B,WAAW,CAAC,IAAM6B,KAAK,OAAO;YAE1C,OAAO7B,cAAc,CAAC,IAAMsB,qBAAqB,OAAO;QAC1D;QAEA,OAAO;YAAEH;QAAQ;IACnB;AACF;IAEA,OAAgB,QAAQlB,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;AACxD"}
@@ -0,0 +1,81 @@
1
+ import { Context, Effect, Layer } from 'effect';
2
+ import type { RouteTreeModel } from '../rsc/route-tree.js';
3
+ import { FlightClient, type FlightLoadError } from './flight-client.js';
4
+ import { NavigationApi } from './navigation-api.js';
5
+ export type RouteLoad = {
6
+ readonly _tag: 'Route';
7
+ readonly cache: (entry: NavigationHistoryEntry) => void;
8
+ readonly completed: Effect.Effect<void, FlightLoadError>;
9
+ readonly release: Effect.Effect<void>;
10
+ readonly resolvedUrl: URL;
11
+ readonly routeTree: RouteTreeModel;
12
+ } | {
13
+ readonly _tag: 'Document';
14
+ readonly release: Effect.Effect<void>;
15
+ };
16
+ export type RouteLoadRequest = {
17
+ readonly destination: Pick<NavigationDestination, 'id' | 'url'>;
18
+ readonly navigationType: NavigationType;
19
+ };
20
+ declare const RouteLoader_base: Context.ServiceClass<RouteLoader, "ersc/client/RouteLoader", {
21
+ invalidate: () => void;
22
+ load: (request: RouteLoadRequest) => Effect.Effect<{
23
+ _tag: "Document";
24
+ release: Effect.Effect<void, never, never>;
25
+ completed?: never;
26
+ payload?: never;
27
+ resolvedUrl?: never;
28
+ } | {
29
+ _tag: "Route";
30
+ cache: (entry: NavigationHistoryEntry) => void;
31
+ completed: Effect.Effect<void, FlightLoadError, never>;
32
+ release: Effect.Effect<void, never, never>;
33
+ resolvedUrl: URL;
34
+ routeTree: RouteTreeModel;
35
+ }, FlightLoadError, import("effect/Scope").Scope>;
36
+ loadInitial: Effect.Effect<import("../rsc/flight.js").FlightPayload, FlightLoadError, never>;
37
+ prepareRefresh: (routeTree: RouteTreeModel) => () => void;
38
+ }> & {
39
+ readonly make: Effect.Effect<{
40
+ invalidate: () => void;
41
+ load: (request: RouteLoadRequest) => Effect.Effect<{
42
+ _tag: "Document";
43
+ release: Effect.Effect<void, never, never>;
44
+ completed?: never;
45
+ payload?: never;
46
+ resolvedUrl?: never;
47
+ } | {
48
+ _tag: "Route";
49
+ cache: (entry: NavigationHistoryEntry) => void;
50
+ completed: Effect.Effect<void, FlightLoadError, never>;
51
+ release: Effect.Effect<void, never, never>;
52
+ resolvedUrl: URL;
53
+ routeTree: RouteTreeModel;
54
+ }, FlightLoadError, import("effect/Scope").Scope>;
55
+ loadInitial: Effect.Effect<import("../rsc/flight.js").FlightPayload, FlightLoadError, never>;
56
+ prepareRefresh: (routeTree: RouteTreeModel) => () => void;
57
+ }, never, FlightClient | NavigationApi | import("effect/Scope").Scope>;
58
+ };
59
+ export declare class RouteLoader extends RouteLoader_base {
60
+ static readonly layer: Layer.Layer<RouteLoader, never, FlightClient | NavigationApi>;
61
+ static readonly layerTest: (implementation: {
62
+ invalidate: () => void;
63
+ load?: (request: RouteLoadRequest) => Effect.Effect<{
64
+ _tag: "Document";
65
+ release: Effect.Effect<void, never, never>;
66
+ completed?: never;
67
+ payload?: never;
68
+ resolvedUrl?: never;
69
+ } | {
70
+ _tag: "Route";
71
+ cache: (entry: NavigationHistoryEntry) => void;
72
+ completed: Effect.Effect<void, FlightLoadError, never>;
73
+ release: Effect.Effect<void, never, never>;
74
+ resolvedUrl: URL;
75
+ routeTree: RouteTreeModel;
76
+ }, FlightLoadError, import("effect/Scope").Scope>;
77
+ loadInitial?: Effect.Effect<import("../rsc/flight.js").FlightPayload, FlightLoadError, never>;
78
+ prepareRefresh: (routeTree: RouteTreeModel) => () => void;
79
+ }) => Layer.Layer<RouteLoader, never, never>;
80
+ }
81
+ export {};
@@ -0,0 +1,128 @@
1
+ import { Context, Effect, Layer, MutableRef } from "effect";
2
+ import { FlightClient } from "./flight-client.js";
3
+ import { NavigationApi } from "./navigation-api.js";
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+ class RouteLoader extends Context.Service()('ersc/client/RouteLoader', {
12
+ make: Effect.gen(function*() {
13
+ const flightClient = yield* FlightClient;
14
+ const navigationApi = yield* NavigationApi;
15
+ const scope = yield* Effect.scope;
16
+ const cacheRef = MutableRef.make(new Map());
17
+ const remove = (cache, entry)=>{
18
+ const cached = cache.get(entry.id);
19
+ if (cached?.entry === entry) {
20
+ cache.delete(entry.id);
21
+ }
22
+ };
23
+ const store = (cache, entry, routeTree)=>{
24
+ const cached = cache.get(entry.id);
25
+ if (cached?.entry !== entry) {
26
+ cached?.entry.removeEventListener('dispose', cached.onDispose);
27
+ const onDispose = ()=>remove(cache, entry);
28
+ entry.addEventListener('dispose', onDispose, {
29
+ once: true
30
+ });
31
+ cache.set(entry.id, {
32
+ entry,
33
+ onDispose,
34
+ routeTree
35
+ });
36
+ return;
37
+ }
38
+ cache.set(entry.id, {
39
+ ...cached,
40
+ routeTree
41
+ });
42
+ };
43
+ const clear = (cache)=>{
44
+ for (const cached of cache.values()){
45
+ cached.entry.removeEventListener('dispose', cached.onDispose);
46
+ }
47
+ cache.clear();
48
+ };
49
+ const invalidate = ()=>{
50
+ clear(MutableRef.get(cacheRef));
51
+ MutableRef.set(cacheRef, new Map());
52
+ };
53
+ const cacheRoute = (cache, routeTree)=>(entry)=>{
54
+ if (MutableRef.get(cacheRef) !== cache) {
55
+ return;
56
+ }
57
+ store(cache, entry, routeTree);
58
+ };
59
+ const prepareRefresh = (routeTree)=>{
60
+ invalidate();
61
+ const cache = MutableRef.get(cacheRef);
62
+ const entry = navigationApi.getCurrentEntry();
63
+ return ()=>{
64
+ if (MutableRef.get(cacheRef) === cache && entry !== null && entry.index !== -1) {
65
+ store(cache, entry, routeTree);
66
+ }
67
+ };
68
+ };
69
+ const load = Effect.fnUntraced(function*(request) {
70
+ const cache = MutableRef.get(cacheRef);
71
+ if (request.navigationType === 'traverse') {
72
+ const cached = cache.get(request.destination.id);
73
+ if (cached !== undefined) {
74
+ return {
75
+ _tag: 'Route',
76
+ cache: ()=>undefined,
77
+ completed: Effect["void"],
78
+ release: Effect["void"],
79
+ resolvedUrl: new URL(request.destination.url),
80
+ routeTree: cached.routeTree
81
+ };
82
+ }
83
+ }
84
+ const resource = yield* flightClient.load({
85
+ _tag: 'Navigation',
86
+ destination: new URL(request.destination.url)
87
+ });
88
+ if (resource._tag === 'Document') {
89
+ return resource;
90
+ }
91
+ return {
92
+ _tag: 'Route',
93
+ cache: cacheRoute(cache, resource.payload.routeTree),
94
+ completed: resource.completed,
95
+ release: resource.release,
96
+ resolvedUrl: resource.resolvedUrl,
97
+ routeTree: resource.payload.routeTree
98
+ };
99
+ });
100
+ const loadInitial = Effect.gen(function*() {
101
+ const cache = MutableRef.get(cacheRef);
102
+ const entry = navigationApi.getCurrentEntry();
103
+ const resource = yield* flightClient.loadInitial;
104
+ if (entry !== null) {
105
+ yield* resource.completed.pipe(Effect.andThen(Effect.sync(()=>{
106
+ if (MutableRef.get(cacheRef) === cache && entry.index !== -1) {
107
+ store(cache, entry, resource.payload.routeTree);
108
+ }
109
+ })), Effect.forkIn(scope));
110
+ }
111
+ return resource.payload;
112
+ });
113
+ yield* Effect.addFinalizer(()=>Effect.sync(()=>clear(MutableRef.get(cacheRef))));
114
+ return {
115
+ invalidate,
116
+ load,
117
+ loadInitial,
118
+ prepareRefresh
119
+ };
120
+ })
121
+ }) {
122
+ static layer = Layer.effect(this, this.make);
123
+ static layerTest = Layer.mock(this);
124
+ }
125
+
126
+ export { RouteLoader };
127
+
128
+ //# sourceMappingURL=route-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client/route-loader.js","sources":["../../src/client/route-loader.ts"],"sourcesContent":["import { Context, Effect, Layer, MutableRef } from 'effect';\n\nimport type { RouteTreeModel } from '../rsc/route-tree';\nimport { FlightClient, type FlightLoadError } from './flight-client';\nimport { NavigationApi } from './navigation-api';\n\ntype CachedRoute = {\n readonly entry: CacheHistoryEntry;\n readonly onDispose: () => void;\n readonly routeTree: RouteTreeModel;\n};\n\ntype CacheHistoryEntry = Pick<\n NavigationHistoryEntry,\n 'addEventListener' | 'id' | 'index' | 'removeEventListener'\n>;\n\ntype RouteCache = Map<string, CachedRoute>;\n\nexport type RouteLoad =\n | {\n readonly _tag: 'Route';\n readonly cache: (entry: NavigationHistoryEntry) => void;\n readonly completed: Effect.Effect<void, FlightLoadError>;\n readonly release: Effect.Effect<void>;\n readonly resolvedUrl: URL;\n readonly routeTree: RouteTreeModel;\n }\n | {\n readonly _tag: 'Document';\n readonly release: Effect.Effect<void>;\n };\n\nexport type RouteLoadRequest = {\n readonly destination: Pick<NavigationDestination, 'id' | 'url'>;\n readonly navigationType: NavigationType;\n};\n\nexport class RouteLoader extends Context.Service<RouteLoader>()('ersc/client/RouteLoader', {\n make: Effect.gen(function* () {\n const flightClient = yield* FlightClient;\n const navigationApi = yield* NavigationApi;\n const scope = yield* Effect.scope;\n const cacheRef = MutableRef.make<RouteCache>(new Map());\n\n const remove = (cache: RouteCache, entry: CacheHistoryEntry) => {\n const cached = cache.get(entry.id);\n if (cached?.entry === entry) {\n cache.delete(entry.id);\n }\n };\n\n const store = (cache: RouteCache, entry: CacheHistoryEntry, routeTree: RouteTreeModel) => {\n const cached = cache.get(entry.id);\n if (cached?.entry !== entry) {\n cached?.entry.removeEventListener('dispose', cached.onDispose);\n const onDispose = () => remove(cache, entry);\n entry.addEventListener('dispose', onDispose, { once: true });\n cache.set(entry.id, { entry, onDispose, routeTree });\n return;\n }\n cache.set(entry.id, { ...cached, routeTree });\n };\n\n const clear = (cache: RouteCache) => {\n for (const cached of cache.values()) {\n cached.entry.removeEventListener('dispose', cached.onDispose);\n }\n cache.clear();\n };\n\n const invalidate = () => {\n clear(MutableRef.get(cacheRef));\n MutableRef.set(cacheRef, new Map());\n };\n\n const cacheRoute =\n (cache: RouteCache, routeTree: RouteTreeModel) => (entry: NavigationHistoryEntry) => {\n if (MutableRef.get(cacheRef) !== cache) {\n return;\n }\n store(cache, entry, routeTree);\n };\n\n const prepareRefresh = (routeTree: RouteTreeModel) => {\n invalidate();\n const cache = MutableRef.get(cacheRef);\n const entry = navigationApi.getCurrentEntry();\n return () => {\n if (MutableRef.get(cacheRef) === cache && entry !== null && entry.index !== -1) {\n store(cache, entry, routeTree);\n }\n };\n };\n\n const load = Effect.fnUntraced(function* (request: RouteLoadRequest) {\n const cache = MutableRef.get(cacheRef);\n if (request.navigationType === 'traverse') {\n const cached = cache.get(request.destination.id);\n if (cached !== undefined) {\n return {\n _tag: 'Route',\n cache: () => undefined,\n completed: Effect.void,\n release: Effect.void,\n resolvedUrl: new URL(request.destination.url),\n routeTree: cached.routeTree,\n } satisfies RouteLoad;\n }\n }\n\n const resource = yield* flightClient.load({\n _tag: 'Navigation',\n destination: new URL(request.destination.url),\n });\n if (resource._tag === 'Document') {\n return resource satisfies RouteLoad;\n }\n return {\n _tag: 'Route',\n cache: cacheRoute(cache, resource.payload.routeTree),\n completed: resource.completed,\n release: resource.release,\n resolvedUrl: resource.resolvedUrl,\n routeTree: resource.payload.routeTree,\n } satisfies RouteLoad;\n });\n\n const loadInitial = Effect.gen(function* () {\n const cache = MutableRef.get(cacheRef);\n const entry = navigationApi.getCurrentEntry();\n const resource = yield* flightClient.loadInitial;\n\n if (entry !== null) {\n yield* resource.completed.pipe(\n Effect.andThen(\n Effect.sync(() => {\n if (MutableRef.get(cacheRef) === cache && entry.index !== -1) {\n store(cache, entry, resource.payload.routeTree);\n }\n }),\n ),\n Effect.forkIn(scope),\n );\n }\n\n return resource.payload;\n });\n\n yield* Effect.addFinalizer(() => Effect.sync(() => clear(MutableRef.get(cacheRef))));\n\n return { invalidate, load, loadInitial, prepareRefresh };\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","MutableRef","FlightClient","NavigationApi","RouteLoader","flightClient","navigationApi","scope","cacheRef","Map","remove","cache","entry","cached","store","routeTree","onDispose","clear","invalidate","cacheRoute","prepareRefresh","load","request","undefined","URL","resource","loadInitial"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { Context, Effect, Layer } from 'effect';
2
+ import { BrowserEffectRunner } from './browser-effect-runner.js';
3
+ import { BrowserRenderer } from './browser-renderer.js';
4
+ import { NavigationApi } from './navigation-api.js';
5
+ import { RouteLoader } from './route-loader.js';
6
+ export type RouteRefreshTransitionType = 'hmr-refresh' | 'server-function';
7
+ type RouteRefreshImplementation = {
8
+ readonly interruptCurrentRouteRefresh: Effect.Effect<void>;
9
+ readonly refreshCurrentRoute: (transitionType: RouteRefreshTransitionType) => Effect.Effect<void>;
10
+ };
11
+ declare const RouteRefresher_base: Context.ServiceClass<RouteRefresher, "ersc/client/RouteRefresher", {
12
+ interruptCurrentRouteRefresh: Effect.Effect<void, never, never>;
13
+ refreshCurrentRoute: (transitionType: RouteRefreshTransitionType) => Effect.Effect<void, never, never>;
14
+ replace: (replacement: RouteRefreshImplementation) => Effect.Effect<void, never, never>;
15
+ }> & {
16
+ readonly make: Effect.Effect<{
17
+ interruptCurrentRouteRefresh: Effect.Effect<void, never, never>;
18
+ refreshCurrentRoute: (transitionType: RouteRefreshTransitionType) => Effect.Effect<void, never, never>;
19
+ replace: (replacement: RouteRefreshImplementation) => Effect.Effect<void, never, never>;
20
+ }, never, NavigationApi>;
21
+ };
22
+ export declare class RouteRefresher extends RouteRefresher_base {
23
+ static readonly layer: Layer.Layer<RouteRefresher, never, NavigationApi>;
24
+ static readonly layerTest: (implementation: {
25
+ interruptCurrentRouteRefresh?: Effect.Effect<void, never, never>;
26
+ refreshCurrentRoute?: (transitionType: RouteRefreshTransitionType) => Effect.Effect<void, never, never>;
27
+ replace?: (replacement: RouteRefreshImplementation) => Effect.Effect<void, never, never>;
28
+ }) => Layer.Layer<RouteRefresher, never, never>;
29
+ }
30
+ export declare const installRouteRefresh: Effect.Effect<void, never, BrowserEffectRunner | BrowserRenderer | NavigationApi | RouteLoader | RouteRefresher | import("effect/Scope").Scope>;
31
+ export {};
@@ -0,0 +1,132 @@
1
+ import { Context, Effect, FiberMap, Layer, Ref, Schema } from "effect";
2
+ import { addTransitionType, startTransition } from "react";
3
+ import { BrowserEffectRunner } from "./browser-effect-runner.js";
4
+ import { BrowserRenderer } from "./browser-renderer.js";
5
+ import { NavigationApi } from "./navigation-api.js";
6
+ import { isRoutedNavigation, preserveRequestedHash } from "./navigation-routing.js";
7
+ import { RouteLoader } from "./route-loader.js";
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+ const CurrentRouteRefreshKey = 'CurrentRouteRefresh';
24
+ class RouteRefreshError extends Schema.TaggedError()('RouteRefreshError', {
25
+ cause: Schema.Defect()
26
+ }) {
27
+ }
28
+ class RouteRefresher extends Context.Service()('ersc/client/RouteRefresher', {
29
+ make: Effect.gen(function*() {
30
+ const navigationApi = yield* NavigationApi;
31
+ const implementation = yield* Ref.make({
32
+ interruptCurrentRouteRefresh: Effect["void"],
33
+ refreshCurrentRoute: ()=>Effect.sync(navigationApi.reloadDocument)
34
+ });
35
+ const interruptCurrentRouteRefresh = Effect.gen(function*() {
36
+ const current = yield* Ref.get(implementation);
37
+ yield* current.interruptCurrentRouteRefresh;
38
+ });
39
+ const refreshCurrentRoute = Effect.fn('RouteRefresher.refreshCurrentRoute')(function*(transitionType) {
40
+ const current = yield* Ref.get(implementation);
41
+ yield* current.refreshCurrentRoute(transitionType);
42
+ });
43
+ return {
44
+ interruptCurrentRouteRefresh,
45
+ refreshCurrentRoute,
46
+ replace: (replacement)=>Ref.set(implementation, replacement)
47
+ };
48
+ })
49
+ }) {
50
+ static layer = Layer.effect(this, this.make);
51
+ static layerTest = Layer.mock(this);
52
+ }
53
+ const installRouteRefresh = Effect.gen(function*() {
54
+ const browserRenderer = yield* BrowserRenderer;
55
+ const navigationApi = yield* NavigationApi;
56
+ const routeLoader = yield* RouteLoader;
57
+ const routeRefresher = yield* RouteRefresher;
58
+ const run = yield* BrowserEffectRunner;
59
+ const refreshes = yield* FiberMap.make();
60
+ const waitForNavigationIdle = Effect.suspend(()=>{
61
+ const transition = navigationApi.getTransition();
62
+ return transition === null ? Effect.succeed('Idle') : Effect.promise(()=>transition.finished.then(()=>undefined, ()=>undefined)).pipe(Effect.as('Settled'));
63
+ }).pipe(Effect.repeat({
64
+ while: (state)=>state === 'Settled'
65
+ }), Effect.asVoid);
66
+ const waitForRoutedNavigation = Effect.callback((resume)=>{
67
+ const onNavigate = (event)=>{
68
+ if (isRoutedNavigation(event)) {
69
+ resume(Effect["void"]);
70
+ }
71
+ };
72
+ const unsubscribe = navigationApi.subscribe(onNavigate);
73
+ return Effect.sync(unsubscribe);
74
+ });
75
+ const refreshRoute = Effect.fnUntraced(function*(transitionType) {
76
+ const currentEntry = navigationApi.getCurrentEntry();
77
+ const destination = new URL(currentEntry?.url ?? navigationApi.getCurrentUrl());
78
+ const resource = yield* routeLoader.load({
79
+ destination: {
80
+ id: currentEntry?.id ?? '',
81
+ url: destination.href
82
+ },
83
+ navigationType: 'replace'
84
+ });
85
+ if (resource._tag === 'Document') {
86
+ yield* resource.release;
87
+ yield* Effect.sync(navigationApi.reloadDocument);
88
+ return;
89
+ }
90
+ const resolvedDestination = preserveRequestedHash(destination, resource.resolvedUrl);
91
+ if (resolvedDestination.href !== destination.href) {
92
+ yield* resource.release;
93
+ yield* Effect.sync(()=>navigationApi.replaceDocument(resolvedDestination.href));
94
+ return;
95
+ }
96
+ const commitRefresh = routeLoader.prepareRefresh(resource.routeTree);
97
+ let renderCommitted;
98
+ yield* Effect.sync(()=>{
99
+ startTransition(()=>{
100
+ addTransitionType(transitionType);
101
+ renderCommitted = browserRenderer.refresh(resource.routeTree);
102
+ });
103
+ });
104
+ yield* Effect.all([
105
+ Effect.promise(()=>renderCommitted),
106
+ resource.completed
107
+ ], {
108
+ concurrency: 'unbounded',
109
+ discard: true
110
+ }).pipe(Effect.andThen(Effect.sync(commitRefresh)), Effect.ensuring(resource.release));
111
+ });
112
+ const refreshInReactTransition = (transitionType)=>Effect.callback((resume, signal)=>{
113
+ startTransition(()=>run(refreshRoute(transitionType), {
114
+ signal
115
+ }).then(()=>resume(Effect["void"]), (cause)=>resume(Effect.fail(new RouteRefreshError({
116
+ cause
117
+ })))));
118
+ });
119
+ const refreshCurrentRoute = Effect.fnUntraced(function*(transitionType) {
120
+ routeLoader.invalidate();
121
+ yield* waitForNavigationIdle;
122
+ yield* Effect.raceFirst(refreshInReactTransition(transitionType), waitForRoutedNavigation);
123
+ }, Effect["catch"]((cause)=>Effect.logError('Failed to refresh the current route.', cause)));
124
+ yield* routeRefresher.replace({
125
+ interruptCurrentRouteRefresh: FiberMap.remove(refreshes, CurrentRouteRefreshKey),
126
+ refreshCurrentRoute: (transitionType)=>FiberMap.run(refreshes, CurrentRouteRefreshKey, refreshCurrentRoute(transitionType)).pipe(Effect.asVoid)
127
+ });
128
+ });
129
+
130
+ export { RouteRefresher, installRouteRefresh };
131
+
132
+ //# sourceMappingURL=route-refresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client/route-refresh.js","sources":["../../src/client/route-refresh.ts"],"sourcesContent":["import { Context, Effect, FiberMap, Layer, Ref, Schema } from 'effect';\nimport { addTransitionType, startTransition } from 'react';\n\nimport { BrowserEffectRunner } from './browser-effect-runner';\nimport { BrowserRenderer } from './browser-renderer';\nimport { NavigationApi } from './navigation-api';\nimport { isRoutedNavigation, preserveRequestedHash } from './navigation-routing';\nimport { RouteLoader } from './route-loader';\n\nconst CurrentRouteRefreshKey = 'CurrentRouteRefresh';\n\nclass RouteRefreshError extends Schema.TaggedError<RouteRefreshError>()('RouteRefreshError', {\n cause: Schema.Defect(),\n}) {}\n\nexport type RouteRefreshTransitionType = 'hmr-refresh' | 'server-function';\n\ntype RouteRefreshImplementation = {\n readonly interruptCurrentRouteRefresh: Effect.Effect<void>;\n readonly refreshCurrentRoute: (transitionType: RouteRefreshTransitionType) => Effect.Effect<void>;\n};\n\nexport class RouteRefresher extends Context.Service<RouteRefresher>()(\n 'ersc/client/RouteRefresher',\n {\n make: Effect.gen(function* () {\n const navigationApi = yield* NavigationApi;\n const implementation = yield* Ref.make<RouteRefreshImplementation>({\n interruptCurrentRouteRefresh: Effect.void,\n refreshCurrentRoute: () => Effect.sync(navigationApi.reloadDocument),\n });\n\n const interruptCurrentRouteRefresh = Effect.gen(function* () {\n const current = yield* Ref.get(implementation);\n yield* current.interruptCurrentRouteRefresh;\n });\n\n const refreshCurrentRoute = Effect.fn('RouteRefresher.refreshCurrentRoute')(function* (\n transitionType: RouteRefreshTransitionType,\n ) {\n const current = yield* Ref.get(implementation);\n yield* current.refreshCurrentRoute(transitionType);\n });\n\n return {\n interruptCurrentRouteRefresh,\n refreshCurrentRoute,\n replace: (replacement: RouteRefreshImplementation) => Ref.set(implementation, replacement),\n };\n }),\n },\n) {\n static readonly layer = Layer.effect(this, this.make);\n\n static readonly layerTest = Layer.mock(this);\n}\n\nexport const installRouteRefresh = Effect.gen(function* () {\n const browserRenderer = yield* BrowserRenderer;\n const navigationApi = yield* NavigationApi;\n const routeLoader = yield* RouteLoader;\n const routeRefresher = yield* RouteRefresher;\n const run = yield* BrowserEffectRunner;\n const refreshes = yield* FiberMap.make<typeof CurrentRouteRefreshKey>();\n\n const waitForNavigationIdle = Effect.suspend(() => {\n const transition = navigationApi.getTransition();\n return transition === null\n ? Effect.succeed('Idle' as const)\n : Effect.promise(() =>\n transition.finished.then(\n () => undefined,\n () => undefined,\n ),\n ).pipe(Effect.as('Settled' as const));\n }).pipe(Effect.repeat({ while: (state) => state === 'Settled' }), Effect.asVoid);\n\n const waitForRoutedNavigation = Effect.callback<void>((resume) => {\n const onNavigate = (event: NavigateEvent) => {\n if (isRoutedNavigation(event)) {\n resume(Effect.void);\n }\n };\n const unsubscribe = navigationApi.subscribe(onNavigate);\n return Effect.sync(unsubscribe);\n });\n\n const refreshRoute = Effect.fnUntraced(function* (transitionType: RouteRefreshTransitionType) {\n const currentEntry = navigationApi.getCurrentEntry();\n const destination = new URL(currentEntry?.url ?? navigationApi.getCurrentUrl());\n const resource = yield* routeLoader.load({\n destination: {\n id: currentEntry?.id ?? '',\n url: destination.href,\n },\n navigationType: 'replace',\n });\n\n if (resource._tag === 'Document') {\n yield* resource.release;\n yield* Effect.sync(navigationApi.reloadDocument);\n return;\n }\n\n const resolvedDestination = preserveRequestedHash(destination, resource.resolvedUrl);\n if (resolvedDestination.href !== destination.href) {\n yield* resource.release;\n yield* Effect.sync(() => navigationApi.replaceDocument(resolvedDestination.href));\n return;\n }\n\n const commitRefresh = routeLoader.prepareRefresh(resource.routeTree);\n let renderCommitted!: Promise<void>;\n yield* Effect.sync(() => {\n startTransition(() => {\n addTransitionType(transitionType);\n renderCommitted = browserRenderer.refresh(resource.routeTree);\n });\n });\n yield* Effect.all([Effect.promise(() => renderCommitted), resource.completed], {\n concurrency: 'unbounded',\n discard: true,\n }).pipe(Effect.andThen(Effect.sync(commitRefresh)), Effect.ensuring(resource.release));\n });\n\n const refreshInReactTransition = (transitionType: RouteRefreshTransitionType) =>\n Effect.callback<void, RouteRefreshError>((resume, signal) => {\n startTransition(() =>\n run(refreshRoute(transitionType), { signal }).then(\n () => resume(Effect.void),\n (cause) => resume(Effect.fail(new RouteRefreshError({ cause }))),\n ),\n );\n });\n\n const refreshCurrentRoute = Effect.fnUntraced(\n function* (transitionType: RouteRefreshTransitionType) {\n routeLoader.invalidate();\n yield* waitForNavigationIdle;\n yield* Effect.raceFirst(refreshInReactTransition(transitionType), waitForRoutedNavigation);\n },\n Effect.catch((cause) => Effect.logError('Failed to refresh the current route.', cause)),\n );\n\n yield* routeRefresher.replace({\n interruptCurrentRouteRefresh: FiberMap.remove(refreshes, CurrentRouteRefreshKey),\n refreshCurrentRoute: (transitionType) =>\n FiberMap.run(refreshes, CurrentRouteRefreshKey, refreshCurrentRoute(transitionType)).pipe(\n Effect.asVoid,\n ),\n });\n});\n"],"names":["Context","Effect","FiberMap","Layer","Ref","Schema","addTransitionType","startTransition","BrowserEffectRunner","BrowserRenderer","NavigationApi","isRoutedNavigation","preserveRequestedHash","RouteLoader","CurrentRouteRefreshKey","RouteRefreshError","RouteRefresher","navigationApi","implementation","interruptCurrentRouteRefresh","current","refreshCurrentRoute","transitionType","replacement","installRouteRefresh","browserRenderer","routeLoader","routeRefresher","run","refreshes","waitForNavigationIdle","transition","undefined","state","waitForRoutedNavigation","resume","onNavigate","event","unsubscribe","refreshRoute","currentEntry","destination","URL","resource","resolvedDestination","commitRefresh","renderCommitted","refreshInReactTransition","signal","cause"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { RouteTreeModel } from '../rsc/route-tree.js';
2
+ type RouteTreeProps = {
3
+ readonly root: RouteTreeModel;
4
+ };
5
+ export declare function RouteTree({ root }: RouteTreeProps): import("react").JSX.Element;
6
+ export declare function RouteOutlet(): import("react").JSX.Element | null;
7
+ export {};
@@ -0,0 +1,34 @@
1
+ "use client"
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { createContext, use } from "react";
4
+
5
+
6
+
7
+
8
+
9
+
10
+ const RouteNodeContext = /*#__PURE__*/ createContext(null);
11
+ function RouteNodeRenderer({ node }) {
12
+ return /*#__PURE__*/ jsx(RouteNodeContext, {
13
+ value: node,
14
+ children: node.content
15
+ });
16
+ }
17
+ function RouteTree({ root }) {
18
+ return /*#__PURE__*/ jsx(RouteNodeRenderer, {
19
+ node: root
20
+ });
21
+ }
22
+ function RouteOutlet() {
23
+ const node = use(RouteNodeContext);
24
+ if (node === null) {
25
+ throw new TypeError('RouteOutlet rendered outside its route node.');
26
+ }
27
+ return node.child === null ? null : /*#__PURE__*/ jsx(RouteNodeRenderer, {
28
+ node: node.child
29
+ }, node.child.id);
30
+ }
31
+
32
+ export { RouteOutlet, RouteTree };
33
+
34
+ //# sourceMappingURL=route-tree.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client/route-tree.js","sources":["../../src/client/route-tree.tsx"],"sourcesContent":["'use client';\n\nimport { createContext, use } from 'react';\n\nimport type { RouteTreeModel } from '../rsc/route-tree';\n\ntype RouteNodeRendererProps = { readonly node: RouteTreeModel };\ntype RouteTreeProps = { readonly root: RouteTreeModel };\n\nconst RouteNodeContext = createContext<RouteTreeModel | null>(null);\n\nfunction RouteNodeRenderer({ node }: RouteNodeRendererProps) {\n return <RouteNodeContext value={node}>{node.content}</RouteNodeContext>;\n}\n\nexport function RouteTree({ root }: RouteTreeProps) {\n return <RouteNodeRenderer node={root} />;\n}\n\nexport function RouteOutlet() {\n const node = use(RouteNodeContext);\n if (node === null) {\n throw new TypeError('RouteOutlet rendered outside its route node.');\n }\n return node.child === null ? null : <RouteNodeRenderer key={node.child.id} node={node.child} />;\n}\n"],"names":["createContext","use","RouteNodeContext","RouteNodeRenderer","node","RouteTree","root","RouteOutlet","TypeError"],"mappings":";;;;;;AAAa;;AAE8B;AAO3C,MAAME,gBAAgBA,iBAAGF,aAAaA,CAAwB;AAE9D,SAASG,iBAAiBA,CAAC,EAAEC,IAAI,EAA0B;IACzD,qBAAO,IAACF,gBAAgBA;QAAC,OAAOE;kBAAOA,KAAK,OAAO;;AACrD;AAEO,SAASC,SAASA,CAAC,EAAEC,IAAI,EAAkB;IAChD,qBAAO,IAACH,iBAAiBA;QAAC,MAAMG;;AAClC;AAEO,SAASC,WAAWA;IACzB,MAAMH,OAAOH,GAAGA,CAACC,gBAAgBA;IACjC,IAAIE,SAAS,MAAM;QACjB,MAAM,IAAII,UAAU;IACtB;IACA,OAAOJ,KAAK,KAAK,KAAK,OAAO,qBAAO,IAACD,iBAAiBA;QAAqB,MAAMC,KAAK,KAAK;OAA/BA,KAAK,KAAK,CAAC,EAAE;AAC3E"}
@@ -0,0 +1,18 @@
1
+ import { Schema } from 'effect';
2
+ import { Rpc, RpcGroup } from 'effect/unstable/rpc';
3
+ export declare const DevChannelPath = "/_ersc/dev";
4
+ export declare const DevUpdate: Schema.Union<readonly [Schema.TaggedStruct<"ClientUpdate", {
5
+ readonly clientHash: Schema.String;
6
+ }>, Schema.TaggedStruct<"RscUpdate", {
7
+ readonly clientHash: Schema.String;
8
+ }>, Schema.TaggedStruct<"BuildFailed", {
9
+ readonly diagnostics: Schema.String;
10
+ }>]>;
11
+ export type DevUpdate = typeof DevUpdate.Type;
12
+ export declare const DevRpcs: RpcGroup.RpcGroup<Rpc.Rpc<"ObserveDevUpdates", Schema.Void, import("effect/unstable/rpc/RpcSchema").Stream<Schema.Union<readonly [Schema.TaggedStruct<"ClientUpdate", {
13
+ readonly clientHash: Schema.String;
14
+ }>, Schema.TaggedStruct<"RscUpdate", {
15
+ readonly clientHash: Schema.String;
16
+ }>, Schema.TaggedStruct<"BuildFailed", {
17
+ readonly diagnostics: Schema.String;
18
+ }>]>, Schema.Never>, Schema.Never, never, never>>;
@@ -0,0 +1,30 @@
1
+ import { Schema } from "effect";
2
+ import { Rpc, RpcGroup } from "effect/unstable/rpc";
3
+
4
+
5
+
6
+
7
+
8
+ const DevChannelPath = '/_ersc/dev';
9
+ const ClientUpdate = Schema.TaggedStruct('ClientUpdate', {
10
+ clientHash: Schema.String
11
+ });
12
+ const RscUpdate = Schema.TaggedStruct('RscUpdate', {
13
+ clientHash: Schema.String
14
+ });
15
+ const BuildFailed = Schema.TaggedStruct('BuildFailed', {
16
+ diagnostics: Schema.String
17
+ });
18
+ const DevUpdate = Schema.Union([
19
+ ClientUpdate,
20
+ RscUpdate,
21
+ BuildFailed
22
+ ]);
23
+ const DevRpcs = RpcGroup.make(Rpc.make('ObserveDevUpdates', {
24
+ success: DevUpdate,
25
+ stream: true
26
+ }));
27
+
28
+ export { DevChannelPath, DevRpcs, DevUpdate };
29
+
30
+ //# sourceMappingURL=channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dev/channel.js","sources":["../../src/dev/channel.ts"],"sourcesContent":["import { Schema } from 'effect';\nimport { Rpc, RpcGroup } from 'effect/unstable/rpc';\n\nexport const DevChannelPath = '/_ersc/dev';\n\nconst ClientUpdate = Schema.TaggedStruct('ClientUpdate', { clientHash: Schema.String });\n\nconst RscUpdate = Schema.TaggedStruct('RscUpdate', { clientHash: Schema.String });\n\nconst BuildFailed = Schema.TaggedStruct('BuildFailed', { diagnostics: Schema.String });\n\nexport const DevUpdate = Schema.Union([ClientUpdate, RscUpdate, BuildFailed]);\nexport type DevUpdate = typeof DevUpdate.Type;\n\nexport const DevRpcs = RpcGroup.make(\n Rpc.make('ObserveDevUpdates', {\n success: DevUpdate,\n stream: true,\n }),\n);\n"],"names":["Schema","Rpc","RpcGroup","DevChannelPath","ClientUpdate","RscUpdate","BuildFailed","DevUpdate","DevRpcs"],"mappings":";;;;;AAAgC;AACoB;AAE7C,MAAMG,cAAcA,GAAG,aAAa;AAE3C,MAAMC,YAAYA,GAAGJ,mBAAmB,CAAC,gBAAgB;IAAE,YAAYA,aAAa;AAAC;AAErF,MAAMK,SAASA,GAAGL,mBAAmB,CAAC,aAAa;IAAE,YAAYA,aAAa;AAAC;AAE/E,MAAMM,WAAWA,GAAGN,mBAAmB,CAAC,eAAe;IAAE,aAAaA,aAAa;AAAC;AAE7E,MAAMO,SAASA,GAAGP,YAAY,CAAC;IAACI,YAAYA;IAAEC,SAASA;IAAEC,WAAWA;CAAC,EAAE;AAGvE,MAAME,OAAOA,GAAGN,aAAa,CAClCD,QAAQ,CAAC,qBAAqB;IAC5B,SAASM,SAASA;IAClB,QAAQ;AACV,IACA"}
@@ -0,0 +1,3 @@
1
+ import { Effect } from 'effect';
2
+ import { RouteRefresher } from '../client/route-refresh.js';
3
+ export declare const startDevClient: Effect.Effect<void, import("effect/unstable/rpc/RpcClientError").RpcClientError, RouteRefresher | import("effect/Scope").Scope>;