effective-rsc 0.1.2 → 0.1.4

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 (54) hide show
  1. package/LLMS.md +85 -0
  2. package/README.md +14 -8
  3. package/dist/application/routes.d.ts +10 -10
  4. package/dist/application/routes.js.map +1 -1
  5. package/dist/build/build.d.ts +4 -2
  6. package/dist/build/build.js +19 -2
  7. package/dist/build/build.js.map +1 -1
  8. package/dist/build/deployment.d.ts +10 -0
  9. package/dist/build/deployment.js +59 -0
  10. package/dist/build/deployment.js.map +1 -0
  11. package/dist/build/dev.d.ts +4 -4
  12. package/dist/build/dev.js +22 -7
  13. package/dist/build/dev.js.map +1 -1
  14. package/dist/build/hook.d.ts +8 -0
  15. package/dist/build/hook.js +5 -0
  16. package/dist/build/hook.js.map +1 -0
  17. package/dist/build/rspack.js +1 -1
  18. package/dist/build/rspack.js.map +1 -1
  19. package/dist/cli.js +13 -24
  20. package/dist/cli.js.map +1 -1
  21. package/dist/client/browser-renderer.d.ts +25 -25
  22. package/dist/client/browser-renderer.js +80 -94
  23. package/dist/client/browser-renderer.js.map +1 -1
  24. package/dist/client/call-server.js +7 -5
  25. package/dist/client/call-server.js.map +1 -1
  26. package/dist/client/client-router.js +23 -7
  27. package/dist/client/client-router.js.map +1 -1
  28. package/dist/client/flight-client.js +3 -4
  29. package/dist/client/flight-client.js.map +1 -1
  30. package/dist/client/react-dom-renderer.js +2 -1
  31. package/dist/client/react-dom-renderer.js.map +1 -1
  32. package/dist/client/route-refresh.d.ts +2 -2
  33. package/dist/client/route-refresh.js +54 -39
  34. package/dist/client/route-refresh.js.map +1 -1
  35. package/dist/dev/panel.js +14 -14
  36. package/dist/dev/panel.js.map +1 -1
  37. package/dist/server/application.d.ts +2 -1
  38. package/dist/server/application.js +8 -6
  39. package/dist/server/application.js.map +1 -1
  40. package/dist/server/html-renderer.js +12 -11
  41. package/dist/server/html-renderer.js.map +1 -1
  42. package/dist/server/serve.d.ts +7 -0
  43. package/dist/server/serve.js +31 -0
  44. package/dist/server/serve.js.map +1 -0
  45. package/dist/server/start.d.ts +3 -0
  46. package/dist/server/start.js +24 -0
  47. package/dist/server/start.js.map +1 -0
  48. package/docs/02-guides/06-deploying-to-vercel/index.md +34 -0
  49. package/docs/02-guides/index.md +1 -0
  50. package/docs/03-advanced/02-client-navigation/index.md +17 -0
  51. package/docs/03-advanced/04-production-startup/01_server.ts +11 -0
  52. package/docs/03-advanced/04-production-startup/index.md +22 -0
  53. package/docs/03-advanced/index.md +1 -0
  54. package/package.json +27 -20
@@ -1 +1 @@
1
- {"version":3,"file":"client/call-server.js","sources":["../../src/client/call-server.ts"],"sourcesContent":["import { Effect, MutableRef, Schema } from 'effect';\nimport { addTransitionType, startTransition } from 'react';\nimport {\n createTemporaryReferenceSet,\n encodeReply,\n setServerCallback,\n} from 'react-server-dom-rspack/client.browser';\n\nimport { BrowserEffectRunner } from './browser-effect-runner';\nimport { BrowserRenderer } from './browser-renderer';\nimport { FlightClient } from './flight-client';\nimport { NavigationApi } from './navigation-api';\nimport { RouteLoader } from './route-loader';\nimport { RouteRefresher } from './route-refresh';\n\nclass ServerFnCallError extends Schema.TaggedError<ServerFnCallError>()('ServerFnCallError', {\n cause: Schema.Defect(),\n message: Schema.String,\n}) {}\n\ntype ServerFnInvocation =\n | {\n readonly _tag: 'HistoryEntry';\n readonly id: string;\n readonly order: number;\n readonly url: string;\n }\n | { readonly _tag: 'CurrentUrl'; readonly order: number; readonly url: string };\n\ntype ServerFnRefreshSource = 'Response' | 'CurrentRoute';\n\nexport const installCallServer = Effect.gen(function* () {\n const browserRenderer = yield* BrowserRenderer;\n const navigationApi = yield* NavigationApi;\n const run = yield* BrowserEffectRunner;\n const flightClient = yield* FlightClient;\n const routeLoader = yield* RouteLoader;\n const routeRefresher = yield* RouteRefresher;\n const latestInvocationOrder = MutableRef.make(0);\n const selectRefreshSource = (invocation: ServerFnInvocation): ServerFnRefreshSource => {\n if (\n MutableRef.get(latestInvocationOrder) !== invocation.order ||\n navigationApi.getTransition() !== null\n ) {\n return 'CurrentRoute';\n }\n\n const currentEntry = navigationApi.getCurrentEntry();\n switch (invocation._tag) {\n case 'HistoryEntry':\n return currentEntry?.id === invocation.id ? 'Response' : 'CurrentRoute';\n case 'CurrentUrl':\n return currentEntry === null && navigationApi.getCurrentUrl() === invocation.url\n ? 'Response'\n : 'CurrentRoute';\n }\n };\n const callServer = Effect.fnUntraced(function* (\n id: string,\n args: ReadonlyArray<unknown>,\n invocationResult: PromiseWithResolvers<unknown>,\n ) {\n const currentEntry = navigationApi.getCurrentEntry();\n const order = MutableRef.incrementAndGet(latestInvocationOrder);\n const invocation: ServerFnInvocation =\n currentEntry === null\n ? { _tag: 'CurrentUrl', order, url: navigationApi.getCurrentUrl() }\n : {\n _tag: 'HistoryEntry',\n id: currentEntry.id,\n order,\n url: currentEntry.url ?? navigationApi.getCurrentUrl(),\n };\n const temporaryReferences = createTemporaryReferenceSet();\n const body = yield* Effect.tryPromise({\n try: () => encodeReply(args, { temporaryReferences }),\n catch: (cause) => new ServerFnCallError({ cause, message: 'Failed to encode arguments.' }),\n });\n const resource = yield* flightClient\n .load({\n _tag: 'ServerFunction',\n body,\n destination: new URL(invocation.url),\n id,\n temporaryReferences,\n })\n .pipe(\n Effect.mapError(\n (cause) => new ServerFnCallError({ cause, message: 'Server Function request failed.' }),\n ),\n );\n if (resource._tag === 'Document') {\n yield* resource.release;\n return yield* new ServerFnCallError({\n cause: new Error('A Server Function response cannot request document navigation.'),\n message: 'Server Function response was incompatible with Flight.',\n });\n }\n const serverFnResult = resource.payload.serverFnResult;\n if (serverFnResult === null) {\n yield* resource.release;\n return yield* new ServerFnCallError({\n cause: new Error('The Flight payload omitted the Server Function return value.'),\n message: 'Server Function response was incomplete.',\n });\n }\n switch (serverFnResult._tag) {\n case 'Failure':\n invocationResult.reject(\n new ServerFnCallError({\n cause: serverFnResult.error,\n message: 'Server Function execution failed.',\n }),\n );\n break;\n case 'Success':\n invocationResult.resolve(serverFnResult.value);\n break;\n }\n // React registered its Action reactions before the request completed. Registering ERSC's\n // continuation after settlement lets React close that Action before the refresh Transition.\n yield* Effect.promise(() =>\n invocationResult.promise.then(\n () => undefined,\n () => undefined,\n ),\n );\n let refreshSource = selectRefreshSource(invocation);\n if (refreshSource === 'Response') {\n yield* routeRefresher.interruptCurrentRouteRefresh;\n // Interruption awaits cleanup, during which navigation or another invocation can win.\n refreshSource = selectRefreshSource(invocation);\n }\n\n if (refreshSource === 'CurrentRoute') {\n yield* resource.release;\n yield* routeRefresher.refreshCurrentRoute('server-function');\n return;\n }\n const commitRefresh = routeLoader.prepareRefresh(resource.payload.routeTree);\n let renderCommitted!: Promise<void>;\n yield* Effect.sync(() => {\n startTransition(() => {\n addTransitionType('server-function');\n // Do not return the commit Promise from React's Transition Action. React cannot commit the\n // render until that Action ends.\n renderCommitted = browserRenderer.refresh(resource.payload.routeTree);\n });\n });\n yield* Effect.all([resource.completed, Effect.promise(() => renderCommitted)], {\n concurrency: 'unbounded',\n discard: true,\n }).pipe(\n Effect.andThen(Effect.sync(commitRefresh)),\n Effect.onError(() => resource.release),\n Effect.forkScoped,\n );\n });\n\n yield* Effect.sync(() => {\n setServerCallback((id, args) => {\n const invocationResult = Promise.withResolvers<unknown>();\n void run(callServer(id, args, invocationResult)).catch(invocationResult.reject);\n return invocationResult.promise;\n });\n });\n});\n"],"names":["Effect","MutableRef","Schema","addTransitionType","startTransition","createTemporaryReferenceSet","encodeReply","setServerCallback","BrowserEffectRunner","BrowserRenderer","FlightClient","NavigationApi","RouteLoader","RouteRefresher","ServerFnCallError","installCallServer","browserRenderer","navigationApi","run","flightClient","routeLoader","routeRefresher","latestInvocationOrder","selectRefreshSource","invocation","currentEntry","callServer","id","args","invocationResult","order","temporaryReferences","body","cause","resource","URL","Error","serverFnResult","undefined","refreshSource","commitRefresh","renderCommitted","Promise"],"mappings":"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"}
1
+ {"version":3,"file":"client/call-server.js","sources":["../../src/client/call-server.ts"],"sourcesContent":["import { Effect, MutableRef, Schema } from 'effect';\nimport { addTransitionType, startTransition } from 'react';\nimport {\n createTemporaryReferenceSet,\n encodeReply,\n setServerCallback,\n} from 'react-server-dom-rspack/client.browser';\n\nimport { BrowserEffectRunner } from './browser-effect-runner';\nimport { BrowserRenderer } from './browser-renderer';\nimport { FlightClient } from './flight-client';\nimport { NavigationApi } from './navigation-api';\nimport { RouteLoader } from './route-loader';\nimport { RouteRefresher } from './route-refresh';\n\nclass ServerFnCallError extends Schema.TaggedError<ServerFnCallError>()('ServerFnCallError', {\n cause: Schema.Defect(),\n message: Schema.String,\n}) {}\n\ntype ServerFnInvocation =\n | {\n readonly _tag: 'HistoryEntry';\n readonly id: string;\n readonly order: number;\n readonly url: string;\n }\n | { readonly _tag: 'CurrentUrl'; readonly order: number; readonly url: string };\n\ntype ServerFnRefreshSource = 'Response' | 'CurrentRoute';\n\nexport const installCallServer = Effect.gen(function* () {\n const browserRenderer = yield* BrowserRenderer;\n const navigationApi = yield* NavigationApi;\n const run = yield* BrowserEffectRunner;\n const flightClient = yield* FlightClient;\n const routeLoader = yield* RouteLoader;\n const routeRefresher = yield* RouteRefresher;\n const latestInvocationOrder = MutableRef.make(0);\n const selectRefreshSource = (invocation: ServerFnInvocation): ServerFnRefreshSource => {\n if (\n MutableRef.get(latestInvocationOrder) !== invocation.order ||\n navigationApi.getTransition() !== null\n ) {\n return 'CurrentRoute';\n }\n\n const currentEntry = navigationApi.getCurrentEntry();\n switch (invocation._tag) {\n case 'HistoryEntry':\n return currentEntry?.id === invocation.id ? 'Response' : 'CurrentRoute';\n case 'CurrentUrl':\n return currentEntry === null && navigationApi.getCurrentUrl() === invocation.url\n ? 'Response'\n : 'CurrentRoute';\n }\n };\n const callServer = Effect.fnUntraced(function* (\n id: string,\n args: ReadonlyArray<unknown>,\n invocationResult: PromiseWithResolvers<unknown>,\n ) {\n const currentEntry = navigationApi.getCurrentEntry();\n const order = MutableRef.incrementAndGet(latestInvocationOrder);\n const invocation: ServerFnInvocation =\n currentEntry === null\n ? { _tag: 'CurrentUrl', order, url: navigationApi.getCurrentUrl() }\n : {\n _tag: 'HistoryEntry',\n id: currentEntry.id,\n order,\n url: currentEntry.url ?? navigationApi.getCurrentUrl(),\n };\n const temporaryReferences = createTemporaryReferenceSet();\n const body = yield* Effect.tryPromise({\n try: () => encodeReply(args, { temporaryReferences }),\n catch: (cause) => new ServerFnCallError({ cause, message: 'Failed to encode arguments.' }),\n });\n const resource = yield* flightClient\n .load({\n _tag: 'ServerFunction',\n body,\n destination: new URL(invocation.url),\n id,\n temporaryReferences,\n })\n .pipe(\n Effect.mapError(\n (cause) => new ServerFnCallError({ cause, message: 'Server Function request failed.' }),\n ),\n );\n if (resource._tag === 'Document') {\n yield* resource.release;\n return yield* new ServerFnCallError({\n cause: new Error('A Server Function response cannot request document navigation.'),\n message: 'Server Function response was incompatible with Flight.',\n });\n }\n const serverFnResult = resource.payload.serverFnResult;\n if (serverFnResult === null) {\n yield* resource.release;\n return yield* new ServerFnCallError({\n cause: new Error('The Flight payload omitted the Server Function return value.'),\n message: 'Server Function response was incomplete.',\n });\n }\n switch (serverFnResult._tag) {\n case 'Failure':\n invocationResult.reject(\n new ServerFnCallError({\n cause: serverFnResult.error,\n message: 'Server Function execution failed.',\n }),\n );\n break;\n case 'Success':\n invocationResult.resolve(serverFnResult.value);\n break;\n }\n // React registered its Action reactions before the request completed. Registering ERSC's\n // continuation after settlement lets React close that Action before the refresh Transition.\n yield* Effect.promise(() =>\n invocationResult.promise.then(\n () => undefined,\n () => undefined,\n ),\n );\n let refreshSource = selectRefreshSource(invocation);\n if (refreshSource === 'Response') {\n yield* routeRefresher.interruptCurrentRouteRefresh;\n // Interruption awaits cleanup, during which navigation or another invocation can win.\n refreshSource = selectRefreshSource(invocation);\n }\n\n if (refreshSource === 'CurrentRoute') {\n yield* resource.release;\n yield* routeRefresher.refreshCurrentRoute('server-function');\n return;\n }\n const commitRefresh = routeLoader.prepareRefresh(resource.payload.routeTree);\n let published!: ReturnType<BrowserRenderer['Service']['refresh']>;\n yield* Effect.sync(() => {\n startTransition(() => {\n addTransitionType('server-function');\n // Do not return the commit Promise from React's Transition Action. React cannot commit the\n // render until that Action ends.\n published = browserRenderer.refresh(resource.payload.routeTree);\n });\n });\n yield* Effect.raceFirst(\n Effect.all([resource.completed, Effect.promise(() => published.committed)], {\n concurrency: 'unbounded',\n discard: true,\n }).pipe(Effect.andThen(Effect.sync(commitRefresh))),\n Effect.promise(() => published.retired),\n ).pipe(Effect.ensuring(resource.release), Effect.forkScoped({ startImmediately: true }));\n });\n\n yield* Effect.sync(() => {\n setServerCallback((id, args) => {\n const invocationResult = Promise.withResolvers<unknown>();\n void run(callServer(id, args, invocationResult)).catch(invocationResult.reject);\n return invocationResult.promise;\n });\n });\n});\n"],"names":["Effect","MutableRef","Schema","addTransitionType","startTransition","createTemporaryReferenceSet","encodeReply","setServerCallback","BrowserEffectRunner","BrowserRenderer","FlightClient","NavigationApi","RouteLoader","RouteRefresher","ServerFnCallError","installCallServer","browserRenderer","navigationApi","run","flightClient","routeLoader","routeRefresher","latestInvocationOrder","selectRefreshSource","invocation","currentEntry","callServer","id","args","invocationResult","order","temporaryReferences","body","cause","resource","URL","Error","serverFnResult","undefined","refreshSource","commitRefresh","published","Promise"],"mappings":";;;;;;;;;;;;;;;;;;;AAAoD;AACO;AAKX;AAEc;AACT;AACN;AACE;AACJ;AACI;AAEjD,MAAMc,iBAAiBA,SAASZ,kBAAkB,GAAsB,qBAAqB;IAC3F,OAAOA,aAAa;IACpB,SAASA,aAAa;AACxB;AAAI;AAaG,MAAMa,iBAAiBA,GAAGf,UAAU,CAAC;IAC1C,MAAMgB,kBAAkB,OAAOP,eAAeA;IAC9C,MAAMQ,gBAAgB,OAAON,aAAaA;IAC1C,MAAMO,MAAM,OAAOV,mBAAmBA;IACtC,MAAMW,eAAe,OAAOT,YAAYA;IACxC,MAAMU,cAAc,OAAOR,WAAWA;IACtC,MAAMS,iBAAiB,OAAOR,cAAcA;IAC5C,MAAMS,wBAAwBrB,eAAe,CAAC;IAC9C,MAAMsB,sBAAsB,CAACC;QAC3B,IACEvB,cAAc,CAACqB,2BAA2BE,WAAW,KAAK,IAC1DP,cAAc,aAAa,OAAO,MAClC;YACA,OAAO;QACT;QAEA,MAAMQ,eAAeR,cAAc,eAAe;QAClD,OAAQO,WAAW,IAAI;YACrB,KAAK;gBACH,OAAOC,cAAc,OAAOD,WAAW,EAAE,GAAG,aAAa;YAC3D,KAAK;gBACH,OAAOC,iBAAiB,QAAQR,cAAc,aAAa,OAAOO,WAAW,GAAG,GAC5E,aACA;QACR;IACF;IACA,MAAME,aAAa1B,iBAAiB,CAAC,UACnC2B,EAAU,EACVC,IAA4B,EAC5BC,gBAA+C;QAE/C,MAAMJ,eAAeR,cAAc,eAAe;QAClD,MAAMa,QAAQ7B,0BAA0B,CAACqB;QACzC,MAAME,aACJC,iBAAiB,OACb;YAAE,MAAM;YAAcK;YAAO,KAAKb,cAAc,aAAa;QAAG,IAChE;YACE,MAAM;YACN,IAAIQ,aAAa,EAAE;YACnBK;YACA,KAAKL,aAAa,GAAG,IAAIR,cAAc,aAAa;QACtD;QACN,MAAMc,sBAAsB1B,2BAA2BA;QACvD,MAAM2B,OAAO,OAAOhC,iBAAiB,CAAC;YACpC,KAAK,IAAMM,WAAWA,CAACsB,MAAM;oBAAEG;gBAAoB;YACnD,OAAO,CAACE,QAAU,IAAInB,iBAAiBA,CAAC;oBAAEmB;oBAAO,SAAS;gBAA8B;QAC1F;QACA,MAAMC,WAAW,OAAOf,aACrB,IAAI,CAAC;YACJ,MAAM;YACNa;YACA,aAAa,IAAIG,IAAIX,WAAW,GAAG;YACnCG;YACAI;QACF,GACC,IAAI,CACH/B,eAAe,CACb,CAACiC,QAAU,IAAInB,iBAAiBA,CAAC;gBAAEmB;gBAAO,SAAS;YAAkC;QAG3F,IAAIC,SAAS,IAAI,KAAK,YAAY;YAChC,OAAOA,SAAS,OAAO;YACvB,OAAO,OAAO,IAAIpB,iBAAiBA,CAAC;gBAClC,OAAO,IAAIsB,MAAM;gBACjB,SAAS;YACX;QACF;QACA,MAAMC,iBAAiBH,SAAS,OAAO,CAAC,cAAc;QACtD,IAAIG,mBAAmB,MAAM;YAC3B,OAAOH,SAAS,OAAO;YACvB,OAAO,OAAO,IAAIpB,iBAAiBA,CAAC;gBAClC,OAAO,IAAIsB,MAAM;gBACjB,SAAS;YACX;QACF;QACA,OAAQC,eAAe,IAAI;YACzB,KAAK;gBACHR,iBAAiB,MAAM,CACrB,IAAIf,iBAAiBA,CAAC;oBACpB,OAAOuB,eAAe,KAAK;oBAC3B,SAAS;gBACX;gBAEF;YACF,KAAK;gBACHR,iBAAiB,OAAO,CAACQ,eAAe,KAAK;gBAC7C;QACJ;QACA,yFAAyF;QACzF,4FAA4F;QAC5F,OAAOrC,cAAc,CAAC,IACpB6B,iBAAiB,OAAO,CAAC,IAAI,CAC3B,IAAMS,WACN,IAAMA;QAGV,IAAIC,gBAAgBhB,oBAAoBC;QACxC,IAAIe,kBAAkB,YAAY;YAChC,OAAOlB,eAAe,4BAA4B;YAClD,sFAAsF;YACtFkB,gBAAgBhB,oBAAoBC;QACtC;QAEA,IAAIe,kBAAkB,gBAAgB;YACpC,OAAOL,SAAS,OAAO;YACvB,OAAOb,eAAe,mBAAmB,CAAC;YAC1C;QACF;QACA,MAAMmB,gBAAgBpB,YAAY,cAAc,CAACc,SAAS,OAAO,CAAC,SAAS;QAC3E,IAAIO;QACJ,OAAOzC,WAAW,CAAC;YACjBI,eAAeA,CAAC;gBACdD,iBAAiBA,CAAC;gBAClB,2FAA2F;gBAC3F,iCAAiC;gBACjCsC,YAAYzB,gBAAgB,OAAO,CAACkB,SAAS,OAAO,CAAC,SAAS;YAChE;QACF;QACA,OAAOlC,gBAAgB,CACrBA,UAAU,CAAC;YAACkC,SAAS,SAAS;YAAElC,cAAc,CAAC,IAAMyC,UAAU,SAAS;SAAE,EAAE;YAC1E,aAAa;YACb,SAAS;QACX,GAAG,IAAI,CAACzC,cAAc,CAACA,WAAW,CAACwC,kBACnCxC,cAAc,CAAC,IAAMyC,UAAU,OAAO,GACtC,IAAI,CAACzC,eAAe,CAACkC,SAAS,OAAO,GAAGlC,iBAAiB,CAAC;YAAE,kBAAkB;QAAK;IACvF;IAEA,OAAOA,WAAW,CAAC;QACjBO,iBAAiBA,CAAC,CAACoB,IAAIC;YACrB,MAAMC,mBAAmBa,QAAQ,aAAa;YAC9C,KAAKxB,IAAIQ,WAAWC,IAAIC,MAAMC,mBAAmB,KAAK,CAACA,iBAAiB,MAAM;YAC9E,OAAOA,iBAAiB,OAAO;QACjC;IACF;AACF,GAAG"}
@@ -20,6 +20,21 @@ import { RouteLoader } from "./route-loader.js";
20
20
 
21
21
 
22
22
 
23
+ const reservedTransitionTypes = new Set([
24
+ 'navigation',
25
+ 'server-function',
26
+ 'hmr-refresh'
27
+ ]);
28
+ const isApplicationTransitionType = (type)=>!reservedTransitionTypes.has(type) && !type.startsWith('navigation-');
29
+ const getLinkTransitionTypes = (event)=>{
30
+ if (event.navigationType !== 'push' && event.navigationType !== 'replace' || !(event.sourceElement instanceof HTMLAnchorElement)) {
31
+ return [];
32
+ }
33
+ const types = event.sourceElement.dataset['erscTransitionTypes']?.match(/\S+/g) ?? [];
34
+ return [
35
+ ...new Set(types.filter(isApplicationTransitionType))
36
+ ];
37
+ };
23
38
  const getNavigationTransitionTypes = (event, fromIndex)=>{
24
39
  const types = [
25
40
  'navigation',
@@ -51,10 +66,7 @@ const reduceRouterState = (state, event)=>{
51
66
  switch(event._tag){
52
67
  case 'RenderRetired':
53
68
  return {
54
- command: visible.flight._tag === 'Streaming' ? {
55
- _tag: 'ReleaseRoute',
56
- resource: visible.flight.resource
57
- } : null,
69
+ command: null,
58
70
  state: {
59
71
  ...state,
60
72
  visible: {
@@ -384,6 +396,7 @@ const installClientRouter = Effect.gen(function*() {
384
396
  return;
385
397
  }
386
398
  const destination = new URL(event.destination.url);
399
+ const linkTransitionTypes = getLinkTransitionTypes(event);
387
400
  const generation = Symbol('NavigationGeneration');
388
401
  const lifetime = new AbortController();
389
402
  const navigationSignal = AbortSignal.any([
@@ -463,6 +476,9 @@ const installClientRouter = Effect.gen(function*() {
463
476
  for (const type of getNavigationTransitionTypes(event, fromIndex)){
464
477
  addTransitionType(type);
465
478
  }
479
+ for (const type of linkTransitionTypes){
480
+ addTransitionType(type);
481
+ }
466
482
  navigation = browserRenderer.navigate(command.resource.routeTree);
467
483
  });
468
484
  return navigation;
@@ -538,12 +554,12 @@ const installClientRouter = Effect.gen(function*() {
538
554
  }
539
555
  const waitForRenderRetirement = Effect.gen(function*() {
540
556
  yield* Effect.promise(()=>rendererNavigation.retired);
541
- const transition = dispatch({
557
+ dispatch({
542
558
  _tag: 'RenderRetired',
543
559
  generation
544
560
  });
545
- yield* executeRouterCommand(transition.command);
546
- }).pipe(Effect.ignore);
561
+ }).pipe(// A newer generation may already be current when this render retires.
562
+ Effect.ensuring(resource.release), Effect.ignore);
547
563
  void run(waitForRenderRetirement).catch(()=>undefined);
548
564
  const waitForFlightCompletion = Effect.gen(function*() {
549
565
  const flightExit = yield* Effect.exit(resource.completed);
@@ -1 +1 @@
1
- {"version":3,"file":"client/client-router.js","sources":["../../src/client/client-router.ts"],"sourcesContent":["import { Effect, Exit, MutableRef } from 'effect';\nimport { addTransitionType, startTransition } from 'react';\n\nimport { BrowserEffectRunner } from './browser-effect-runner';\nimport { BrowserRenderer, type BrowserRendererNavigation } from './browser-renderer';\nimport { NavigationApi } from './navigation-api';\nimport {\n isRoutedNavigation,\n NativeDocumentNavigationInfo,\n preserveRequestedHash,\n} from './navigation-routing';\nimport { RouteLoader, type RouteLoad } from './route-loader';\n\ntype NavigationGeneration = symbol;\ntype RouteResource = Extract<RouteLoad, { readonly _tag: 'Route' }>;\n\nconst getNavigationTransitionTypes = (\n event: NavigateEvent,\n fromIndex: number | null,\n): ReadonlyArray<string> => {\n const types = [\n 'navigation',\n `navigation-${event.navigationType}`,\n ...(event.hasUAVisualTransition ? ['navigation-ua-visual-transition'] : []),\n ];\n if (event.navigationType === 'push') {\n return [...types, 'navigation-forward'];\n }\n if (event.navigationType !== 'traverse') {\n return types;\n }\n\n if (fromIndex === null || fromIndex === event.destination.index) {\n return types;\n }\n return [\n ...types,\n event.destination.index < fromIndex ? 'navigation-backward' : 'navigation-forward',\n ];\n};\n\ntype NavigationEntryState =\n | { readonly _tag: 'PendingCommit' }\n | {\n readonly _tag: 'Committed';\n readonly entry: NavigationHistoryEntry | null;\n };\n\ntype NavigationFlightState =\n | { readonly _tag: 'Streaming'; readonly resource: RouteResource }\n | { readonly _tag: 'Completed'; readonly cache: RouteResource['cache'] };\n\ntype NavigationCandidate =\n | {\n readonly _tag: 'Loading';\n readonly generation: NavigationGeneration;\n readonly lifetime: AbortController;\n }\n | {\n readonly _tag: 'Publishing';\n readonly generation: NavigationGeneration;\n readonly lifetime: AbortController;\n readonly resource: RouteResource;\n }\n | {\n readonly _tag: 'Rendering';\n readonly generation: NavigationGeneration;\n readonly lifetime: AbortController;\n readonly rendererNavigation: BrowserRendererNavigation;\n readonly resource: RouteResource;\n };\n\ntype VisibleNavigation =\n | { readonly _tag: 'Settled' }\n | {\n readonly _tag: 'Navigation';\n readonly entry: NavigationEntryState;\n readonly flight: NavigationFlightState;\n readonly generation: NavigationGeneration;\n };\n\ntype RouterState =\n | { readonly _tag: 'Ready'; readonly visible: VisibleNavigation }\n | {\n readonly _tag: 'Navigating';\n readonly candidate: NavigationCandidate;\n readonly visible: VisibleNavigation;\n };\n\ntype RouterEvent =\n | {\n readonly _tag: 'BeginNavigation';\n readonly generation: NavigationGeneration;\n readonly lifetime: AbortController;\n }\n | { readonly _tag: 'DocumentLoaded'; readonly generation: NavigationGeneration }\n | {\n readonly _tag: 'RouteLoaded';\n readonly generation: NavigationGeneration;\n readonly resource: RouteResource;\n }\n | {\n readonly _tag: 'RenderScheduled';\n readonly generation: NavigationGeneration;\n readonly rendererNavigation: BrowserRendererNavigation;\n readonly resource: RouteResource;\n }\n | { readonly _tag: 'RenderCommitted'; readonly generation: NavigationGeneration }\n | { readonly _tag: 'RenderRetired'; readonly generation: NavigationGeneration }\n | {\n readonly _tag: 'HistoryCommitted';\n readonly entry: NavigationHistoryEntry | null;\n readonly generation: NavigationGeneration;\n }\n | { readonly _tag: 'FlightCompleted'; readonly generation: NavigationGeneration }\n | { readonly _tag: 'FlightFailed'; readonly generation: NavigationGeneration }\n | { readonly _tag: 'NavigationAborted'; readonly generation: NavigationGeneration };\n\ntype RouterCommand =\n | { readonly _tag: 'SupersedeCandidate'; readonly candidate: NavigationCandidate }\n | {\n readonly _tag: 'PublishRoute';\n readonly generation: NavigationGeneration;\n readonly resource: RouteResource;\n }\n | { readonly _tag: 'ReleaseRoute'; readonly resource: RouteResource }\n | {\n readonly _tag: 'CacheRoute';\n readonly cache: RouteResource['cache'];\n readonly entry: NavigationHistoryEntry;\n }\n | {\n readonly _tag: 'CacheAndReleaseRoute';\n readonly entry: NavigationHistoryEntry;\n readonly resource: RouteResource;\n }\n | {\n readonly _tag: 'DiscardRoute';\n readonly rendererNavigation: BrowserRendererNavigation;\n readonly resource: RouteResource;\n };\n\ntype RouterTransition = {\n readonly command: RouterCommand | null;\n readonly state: RouterState;\n};\n\nconst reduceRouterState = (state: RouterState, event: RouterEvent): RouterTransition => {\n if (state.visible._tag === 'Navigation' && state.visible.generation === event.generation) {\n const visible = state.visible;\n switch (event._tag) {\n case 'RenderRetired':\n return {\n command:\n visible.flight._tag === 'Streaming'\n ? { _tag: 'ReleaseRoute', resource: visible.flight.resource }\n : null,\n state: { ...state, visible: { _tag: 'Settled' } },\n };\n case 'HistoryCommitted':\n if (visible.entry._tag === 'Committed') {\n throw new TypeError('A visible navigation history entry cannot commit twice.');\n }\n if (visible.flight._tag === 'Streaming') {\n return {\n command: null,\n state: {\n ...state,\n visible: {\n ...visible,\n entry: { _tag: 'Committed', entry: event.entry },\n },\n },\n };\n }\n return {\n command:\n event.entry === null\n ? null\n : { _tag: 'CacheRoute', cache: visible.flight.cache, entry: event.entry },\n state: { ...state, visible: { _tag: 'Settled' } },\n };\n case 'FlightCompleted':\n if (visible.flight._tag === 'Completed') {\n throw new TypeError('A visible navigation Flight stream cannot complete twice.');\n }\n if (visible.entry._tag === 'PendingCommit') {\n return {\n command: { _tag: 'ReleaseRoute', resource: visible.flight.resource },\n state: {\n ...state,\n visible: {\n ...visible,\n flight: { _tag: 'Completed', cache: visible.flight.resource.cache },\n },\n },\n };\n }\n return {\n command:\n visible.entry.entry === null\n ? { _tag: 'ReleaseRoute', resource: visible.flight.resource }\n : {\n _tag: 'CacheAndReleaseRoute',\n entry: visible.entry.entry,\n resource: visible.flight.resource,\n },\n state: { ...state, visible: { _tag: 'Settled' } },\n };\n case 'FlightFailed':\n if (visible.flight._tag === 'Completed') {\n throw new TypeError('A completed visible Flight stream cannot fail.');\n }\n return {\n command: { _tag: 'ReleaseRoute', resource: visible.flight.resource },\n state: { ...state, visible: { _tag: 'Settled' } },\n };\n }\n }\n\n if (\n event._tag === 'RenderRetired' ||\n event._tag === 'HistoryCommitted' ||\n event._tag === 'FlightCompleted'\n ) {\n return { command: null, state };\n }\n\n if (event._tag === 'BeginNavigation') {\n const nextState: RouterState = {\n _tag: 'Navigating',\n candidate: {\n _tag: 'Loading',\n generation: event.generation,\n lifetime: event.lifetime,\n },\n visible: state.visible,\n };\n if (state._tag === 'Ready') {\n return { command: null, state: nextState };\n }\n return {\n command: { _tag: 'SupersedeCandidate', candidate: state.candidate },\n state: nextState,\n };\n }\n\n if (state._tag === 'Ready' || state.candidate.generation !== event.generation) {\n switch (event._tag) {\n case 'RouteLoaded':\n return { command: { _tag: 'ReleaseRoute', resource: event.resource }, state };\n case 'RenderScheduled':\n return {\n command: {\n _tag: 'DiscardRoute',\n rendererNavigation: event.rendererNavigation,\n resource: event.resource,\n },\n state,\n };\n default:\n return { command: null, state };\n }\n }\n\n switch (event._tag) {\n case 'DocumentLoaded':\n case 'FlightFailed':\n if (state.candidate._tag !== 'Loading') {\n throw new TypeError(`${event._tag} cannot follow ${state.candidate._tag}.`);\n }\n return { command: null, state: { _tag: 'Ready', visible: state.visible } };\n case 'RouteLoaded':\n if (state.candidate._tag !== 'Loading') {\n throw new TypeError(`RouteLoaded cannot follow ${state.candidate._tag}.`);\n }\n return {\n command: {\n _tag: 'PublishRoute',\n generation: event.generation,\n resource: event.resource,\n },\n state: {\n _tag: 'Navigating',\n candidate: {\n _tag: 'Publishing',\n generation: event.generation,\n lifetime: state.candidate.lifetime,\n resource: event.resource,\n },\n visible: state.visible,\n },\n };\n case 'RenderScheduled':\n if (state.candidate._tag !== 'Publishing') {\n throw new TypeError(`RenderScheduled cannot follow ${state.candidate._tag}.`);\n }\n if (state.candidate.resource !== event.resource) {\n throw new TypeError('RenderScheduled must use the published route resource.');\n }\n return {\n command: null,\n state: {\n _tag: 'Navigating',\n candidate: {\n _tag: 'Rendering',\n generation: event.generation,\n lifetime: state.candidate.lifetime,\n rendererNavigation: event.rendererNavigation,\n resource: event.resource,\n },\n visible: state.visible,\n },\n };\n case 'RenderCommitted':\n if (state.candidate._tag !== 'Rendering') {\n throw new TypeError(`RenderCommitted cannot follow ${state.candidate._tag}.`);\n }\n return {\n command: null,\n state: {\n _tag: 'Ready',\n visible: {\n _tag: 'Navigation',\n entry: { _tag: 'PendingCommit' },\n flight: { _tag: 'Streaming', resource: state.candidate.resource },\n generation: event.generation,\n },\n },\n };\n case 'NavigationAborted':\n if (state.candidate._tag === 'Loading') {\n return { command: null, state: { _tag: 'Ready', visible: state.visible } };\n }\n if (state.candidate._tag === 'Publishing') {\n return {\n command: { _tag: 'ReleaseRoute', resource: state.candidate.resource },\n state: { _tag: 'Ready', visible: state.visible },\n };\n }\n return {\n command: {\n _tag: 'DiscardRoute',\n rendererNavigation: state.candidate.rendererNavigation,\n resource: state.candidate.resource,\n },\n state: { _tag: 'Ready', visible: state.visible },\n };\n }\n};\n\ntype NavigationPreparation =\n | { readonly _tag: 'Handled' }\n | {\n readonly _tag: 'Rendered';\n readonly rendererNavigation: BrowserRendererNavigation;\n readonly resolvedDestination: URL;\n readonly resource: RouteResource;\n };\n\nexport const installClientRouter = Effect.gen(function* () {\n const browserRenderer = yield* BrowserRenderer;\n const navigationApi = yield* NavigationApi;\n const routeLoader = yield* RouteLoader;\n const run = yield* BrowserEffectRunner;\n const routerState = MutableRef.make<RouterState>({\n _tag: 'Ready',\n visible: { _tag: 'Settled' },\n });\n\n const dispatch = (event: RouterEvent) => {\n const transition = reduceRouterState(MutableRef.get(routerState), event);\n MutableRef.set(routerState, transition.state);\n return transition;\n };\n\n const executeRouterCommand = Effect.fnUntraced(function* (command: RouterCommand | null) {\n if (command === null) {\n return;\n }\n switch (command._tag) {\n case 'SupersedeCandidate': {\n const candidate = command.candidate;\n yield* Effect.sync(() => candidate.lifetime.abort());\n if (candidate._tag === 'Loading') {\n break;\n }\n if (candidate._tag === 'Publishing') {\n yield* candidate.resource.release;\n break;\n }\n yield* Effect.promise(() => candidate.rendererNavigation.discard()).pipe(\n Effect.ensuring(candidate.resource.release),\n );\n break;\n }\n case 'ReleaseRoute':\n yield* command.resource.release;\n break;\n case 'CacheRoute':\n yield* Effect.sync(() => command.cache(command.entry));\n break;\n case 'CacheAndReleaseRoute':\n yield* Effect.sync(() => command.resource.cache(command.entry));\n yield* command.resource.release;\n break;\n case 'DiscardRoute':\n yield* Effect.promise(() => command.rendererNavigation.discard()).pipe(\n Effect.ensuring(command.resource.release),\n );\n break;\n default:\n throw new TypeError(`Cannot execute the ${command._tag} lifecycle command here.`);\n }\n });\n\n const openDocument = (event: NavigateEvent, destination: URL) => {\n if (event.navigationType === 'traverse') {\n navigationApi.replaceDocument(destination.href);\n return;\n }\n navigationApi.navigate(destination.href, {\n history: event.navigationType === 'replace' ? 'replace' : 'push',\n info: NativeDocumentNavigationInfo,\n });\n };\n\n const onNavigate = (event: NavigateEvent) => {\n if (!isRoutedNavigation(event)) {\n return;\n }\n\n const destination = new URL(event.destination.url);\n const generation: NavigationGeneration = Symbol('NavigationGeneration');\n const lifetime = new AbortController();\n const navigationSignal = AbortSignal.any([event.signal, lifetime.signal]);\n const begin = dispatch({\n _tag: 'BeginNavigation',\n generation,\n lifetime,\n });\n void run(executeRouterCommand(begin.command)).catch(() => undefined);\n // oxlint-disable-next-line effecttsgo/async-function -- Navigation handlers are native Promise boundaries.\n const handler = async (precommitController?: NavigationPrecommitController) => {\n const preparation = Promise.withResolvers<NavigationPreparation>();\n\n const navigationAction = Effect.gen(function* () {\n const resource = yield* routeLoader\n .load({\n destination: event.destination,\n navigationType: event.navigationType,\n })\n .pipe(\n Effect.onError(() =>\n Effect.sync(() => {\n dispatch({ _tag: 'FlightFailed', generation });\n }),\n ),\n );\n\n if (resource._tag === 'Document') {\n dispatch({ _tag: 'DocumentLoaded', generation });\n yield* resource.release;\n openDocument(event, destination);\n return { _tag: 'Handled' } as const;\n }\n\n const resolvedDestination = preserveRequestedHash(destination, resource.resolvedUrl);\n if (resolvedDestination.origin !== destination.origin) {\n dispatch({ _tag: 'DocumentLoaded', generation });\n yield* resource.release;\n openDocument(event, resolvedDestination);\n return { _tag: 'Handled' } as const;\n }\n\n if (\n destination.href !== resolvedDestination.href &&\n (precommitController === undefined || event.navigationType === 'traverse')\n ) {\n dispatch({ _tag: 'DocumentLoaded', generation });\n yield* resource.release;\n navigationApi.replaceDocument(resolvedDestination.href);\n return { _tag: 'Handled' } as const;\n }\n\n const transition = dispatch({ _tag: 'RouteLoaded', generation, resource });\n const command = transition.command;\n if (command?._tag === 'ReleaseRoute') {\n yield* command.resource.release;\n return { _tag: 'Handled' } as const;\n }\n if (command?._tag === 'PublishRoute') {\n const rendererNavigation = yield* Effect.sync(() => {\n let navigation!: BrowserRendererNavigation;\n startTransition(() => {\n const fromIndex =\n navigationApi.getTransition()?.from.index ??\n navigationApi.getCurrentEntry()?.index ??\n null;\n for (const type of getNavigationTransitionTypes(event, fromIndex)) {\n addTransitionType(type);\n }\n navigation = browserRenderer.navigate(command.resource.routeTree);\n });\n return navigation;\n });\n const scheduled = dispatch({\n _tag: 'RenderScheduled',\n generation: command.generation,\n rendererNavigation,\n resource: command.resource,\n });\n if (scheduled.command !== null) {\n yield* executeRouterCommand(scheduled.command);\n return { _tag: 'Handled' } as const;\n }\n return {\n _tag: 'Rendered',\n rendererNavigation,\n resolvedDestination,\n resource: command.resource,\n } as const;\n }\n\n throw new TypeError('A loaded route must be published or released.');\n });\n\n // oxlint-disable-next-line effecttsgo/async-function -- React Transition Actions are a native Promise boundary.\n startTransition(async () => {\n await run(navigationAction, { signal: navigationSignal })\n .then(preparation.resolve)\n .catch(preparation.reject);\n });\n\n const abortNavigation = Effect.suspend(() => {\n const transition = dispatch({ _tag: 'NavigationAborted', generation });\n return executeRouterCommand(transition.command);\n });\n const outcome = await preparation.promise.catch((cause) => {\n if (navigationSignal.aborted) {\n return run(abortNavigation.pipe(Effect.as({ _tag: 'Handled' } as NavigationPreparation)));\n }\n if (!event.cancelable && event.navigationType === 'traverse') {\n navigationApi.reloadDocument();\n return { _tag: 'Handled' } as NavigationPreparation;\n }\n throw cause;\n });\n if (outcome._tag === 'Handled') {\n return;\n }\n\n const { rendererNavigation, resolvedDestination, resource } = outcome;\n const waitForNavigationCommit = Effect.uninterruptibleMask((restore) =>\n restore(Effect.promise(() => rendererNavigation.committed)).pipe(\n Effect.tap(\n Effect.suspend(() => {\n const transition = dispatch({\n _tag: 'RenderCommitted',\n generation,\n });\n return executeRouterCommand(transition.command);\n }),\n ),\n Effect.onExit((exit) => (Exit.isFailure(exit) ? abortNavigation : Effect.void)),\n ),\n );\n try {\n await run(waitForNavigationCommit, { signal: navigationSignal });\n } catch (cause) {\n if (navigationSignal.aborted) {\n return;\n }\n throw cause;\n }\n\n const waitForRenderRetirement = Effect.gen(function* () {\n yield* Effect.promise(() => rendererNavigation.retired);\n const transition = dispatch({ _tag: 'RenderRetired', generation });\n yield* executeRouterCommand(transition.command);\n }).pipe(Effect.ignore);\n void run(waitForRenderRetirement).catch(() => undefined);\n\n const waitForFlightCompletion = Effect.gen(function* () {\n const flightExit = yield* Effect.exit(resource.completed);\n const transition = dispatch({\n _tag: Exit.isSuccess(flightExit) ? 'FlightCompleted' : 'FlightFailed',\n generation,\n });\n yield* executeRouterCommand(transition.command);\n });\n void run(waitForFlightCompletion).catch(() => undefined);\n\n if (destination.href !== resolvedDestination.href && precommitController !== undefined) {\n precommitController.redirect(resolvedDestination.href, { history: 'auto' });\n }\n const commitHistory = Effect.suspend(() => {\n const transition = dispatch({\n _tag: 'HistoryCommitted',\n entry: navigationApi.getCurrentEntry(),\n generation,\n });\n return executeRouterCommand(transition.command);\n });\n if (precommitController === undefined) {\n await run(commitHistory);\n } else {\n precommitController.addHandler(() => run(commitHistory));\n }\n };\n\n event.intercept(\n event.cancelable\n ? { precommitHandler: handler }\n : {\n // Browsers make some traversals non-cancelable so an application cannot trap users.\n handler,\n },\n );\n };\n\n yield* Effect.acquireRelease(\n Effect.sync(() => navigationApi.subscribe(onNavigate)),\n (unsubscribe) => Effect.sync(unsubscribe),\n );\n});\n"],"names":["Effect","Exit","MutableRef","addTransitionType","startTransition","BrowserEffectRunner","BrowserRenderer","NavigationApi","isRoutedNavigation","NativeDocumentNavigationInfo","preserveRequestedHash","RouteLoader","getNavigationTransitionTypes","event","fromIndex","types","reduceRouterState","state","visible","TypeError","nextState","installClientRouter","browserRenderer","navigationApi","routeLoader","run","routerState","dispatch","transition","executeRouterCommand","command","candidate","openDocument","destination","onNavigate","URL","generation","Symbol","lifetime","AbortController","navigationSignal","AbortSignal","begin","undefined","handler","precommitController","preparation","Promise","navigationAction","resource","resolvedDestination","rendererNavigation","navigation","type","scheduled","abortNavigation","outcome","cause","waitForNavigationCommit","restore","exit","waitForRenderRetirement","waitForFlightCompletion","flightExit","commitHistory","unsubscribe"],"mappings":"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"}
1
+ {"version":3,"file":"client/client-router.js","sources":["../../src/client/client-router.ts"],"sourcesContent":["import { Effect, Exit, MutableRef } from 'effect';\nimport { addTransitionType, startTransition } from 'react';\n\nimport { BrowserEffectRunner } from './browser-effect-runner';\nimport { BrowserRenderer, type BrowserRendererNavigation } from './browser-renderer';\nimport { NavigationApi } from './navigation-api';\nimport {\n isRoutedNavigation,\n NativeDocumentNavigationInfo,\n preserveRequestedHash,\n} from './navigation-routing';\nimport { RouteLoader, type RouteLoad } from './route-loader';\n\ntype NavigationGeneration = symbol;\ntype RouteResource = Extract<RouteLoad, { readonly _tag: 'Route' }>;\n\nconst reservedTransitionTypes = new Set(['navigation', 'server-function', 'hmr-refresh']);\n\nconst isApplicationTransitionType = (type: string) =>\n !reservedTransitionTypes.has(type) && !type.startsWith('navigation-');\n\nconst getLinkTransitionTypes = (event: NavigateEvent): ReadonlyArray<string> => {\n if (\n (event.navigationType !== 'push' && event.navigationType !== 'replace') ||\n !(event.sourceElement instanceof HTMLAnchorElement)\n ) {\n return [];\n }\n const types = event.sourceElement.dataset['erscTransitionTypes']?.match(/\\S+/g) ?? [];\n return [...new Set(types.filter(isApplicationTransitionType))];\n};\n\nconst getNavigationTransitionTypes = (\n event: NavigateEvent,\n fromIndex: number | null,\n): ReadonlyArray<string> => {\n const types = [\n 'navigation',\n `navigation-${event.navigationType}`,\n ...(event.hasUAVisualTransition ? ['navigation-ua-visual-transition'] : []),\n ];\n if (event.navigationType === 'push') {\n return [...types, 'navigation-forward'];\n }\n if (event.navigationType !== 'traverse') {\n return types;\n }\n\n if (fromIndex === null || fromIndex === event.destination.index) {\n return types;\n }\n return [\n ...types,\n event.destination.index < fromIndex ? 'navigation-backward' : 'navigation-forward',\n ];\n};\n\ntype NavigationEntryState =\n | { readonly _tag: 'PendingCommit' }\n | {\n readonly _tag: 'Committed';\n readonly entry: NavigationHistoryEntry | null;\n };\n\ntype NavigationFlightState =\n | { readonly _tag: 'Streaming'; readonly resource: RouteResource }\n | { readonly _tag: 'Completed'; readonly cache: RouteResource['cache'] };\n\ntype NavigationCandidate =\n | {\n readonly _tag: 'Loading';\n readonly generation: NavigationGeneration;\n readonly lifetime: AbortController;\n }\n | {\n readonly _tag: 'Publishing';\n readonly generation: NavigationGeneration;\n readonly lifetime: AbortController;\n readonly resource: RouteResource;\n }\n | {\n readonly _tag: 'Rendering';\n readonly generation: NavigationGeneration;\n readonly lifetime: AbortController;\n readonly rendererNavigation: BrowserRendererNavigation;\n readonly resource: RouteResource;\n };\n\ntype VisibleNavigation =\n | { readonly _tag: 'Settled' }\n | {\n readonly _tag: 'Navigation';\n readonly entry: NavigationEntryState;\n readonly flight: NavigationFlightState;\n readonly generation: NavigationGeneration;\n };\n\ntype RouterState =\n | { readonly _tag: 'Ready'; readonly visible: VisibleNavigation }\n | {\n readonly _tag: 'Navigating';\n readonly candidate: NavigationCandidate;\n readonly visible: VisibleNavigation;\n };\n\ntype RouterEvent =\n | {\n readonly _tag: 'BeginNavigation';\n readonly generation: NavigationGeneration;\n readonly lifetime: AbortController;\n }\n | { readonly _tag: 'DocumentLoaded'; readonly generation: NavigationGeneration }\n | {\n readonly _tag: 'RouteLoaded';\n readonly generation: NavigationGeneration;\n readonly resource: RouteResource;\n }\n | {\n readonly _tag: 'RenderScheduled';\n readonly generation: NavigationGeneration;\n readonly rendererNavigation: BrowserRendererNavigation;\n readonly resource: RouteResource;\n }\n | { readonly _tag: 'RenderCommitted'; readonly generation: NavigationGeneration }\n | { readonly _tag: 'RenderRetired'; readonly generation: NavigationGeneration }\n | {\n readonly _tag: 'HistoryCommitted';\n readonly entry: NavigationHistoryEntry | null;\n readonly generation: NavigationGeneration;\n }\n | { readonly _tag: 'FlightCompleted'; readonly generation: NavigationGeneration }\n | { readonly _tag: 'FlightFailed'; readonly generation: NavigationGeneration }\n | { readonly _tag: 'NavigationAborted'; readonly generation: NavigationGeneration };\n\ntype RouterCommand =\n | { readonly _tag: 'SupersedeCandidate'; readonly candidate: NavigationCandidate }\n | {\n readonly _tag: 'PublishRoute';\n readonly generation: NavigationGeneration;\n readonly resource: RouteResource;\n }\n | { readonly _tag: 'ReleaseRoute'; readonly resource: RouteResource }\n | {\n readonly _tag: 'CacheRoute';\n readonly cache: RouteResource['cache'];\n readonly entry: NavigationHistoryEntry;\n }\n | {\n readonly _tag: 'CacheAndReleaseRoute';\n readonly entry: NavigationHistoryEntry;\n readonly resource: RouteResource;\n }\n | {\n readonly _tag: 'DiscardRoute';\n readonly rendererNavigation: BrowserRendererNavigation;\n readonly resource: RouteResource;\n };\n\ntype RouterTransition = {\n readonly command: RouterCommand | null;\n readonly state: RouterState;\n};\n\nconst reduceRouterState = (state: RouterState, event: RouterEvent): RouterTransition => {\n if (state.visible._tag === 'Navigation' && state.visible.generation === event.generation) {\n const visible = state.visible;\n switch (event._tag) {\n case 'RenderRetired':\n return {\n command: null,\n state: { ...state, visible: { _tag: 'Settled' } },\n };\n case 'HistoryCommitted':\n if (visible.entry._tag === 'Committed') {\n throw new TypeError('A visible navigation history entry cannot commit twice.');\n }\n if (visible.flight._tag === 'Streaming') {\n return {\n command: null,\n state: {\n ...state,\n visible: {\n ...visible,\n entry: { _tag: 'Committed', entry: event.entry },\n },\n },\n };\n }\n return {\n command:\n event.entry === null\n ? null\n : { _tag: 'CacheRoute', cache: visible.flight.cache, entry: event.entry },\n state: { ...state, visible: { _tag: 'Settled' } },\n };\n case 'FlightCompleted':\n if (visible.flight._tag === 'Completed') {\n throw new TypeError('A visible navigation Flight stream cannot complete twice.');\n }\n if (visible.entry._tag === 'PendingCommit') {\n return {\n command: { _tag: 'ReleaseRoute', resource: visible.flight.resource },\n state: {\n ...state,\n visible: {\n ...visible,\n flight: { _tag: 'Completed', cache: visible.flight.resource.cache },\n },\n },\n };\n }\n return {\n command:\n visible.entry.entry === null\n ? { _tag: 'ReleaseRoute', resource: visible.flight.resource }\n : {\n _tag: 'CacheAndReleaseRoute',\n entry: visible.entry.entry,\n resource: visible.flight.resource,\n },\n state: { ...state, visible: { _tag: 'Settled' } },\n };\n case 'FlightFailed':\n if (visible.flight._tag === 'Completed') {\n throw new TypeError('A completed visible Flight stream cannot fail.');\n }\n return {\n command: { _tag: 'ReleaseRoute', resource: visible.flight.resource },\n state: { ...state, visible: { _tag: 'Settled' } },\n };\n }\n }\n\n if (\n event._tag === 'RenderRetired' ||\n event._tag === 'HistoryCommitted' ||\n event._tag === 'FlightCompleted'\n ) {\n return { command: null, state };\n }\n\n if (event._tag === 'BeginNavigation') {\n const nextState: RouterState = {\n _tag: 'Navigating',\n candidate: {\n _tag: 'Loading',\n generation: event.generation,\n lifetime: event.lifetime,\n },\n visible: state.visible,\n };\n if (state._tag === 'Ready') {\n return { command: null, state: nextState };\n }\n return {\n command: { _tag: 'SupersedeCandidate', candidate: state.candidate },\n state: nextState,\n };\n }\n\n if (state._tag === 'Ready' || state.candidate.generation !== event.generation) {\n switch (event._tag) {\n case 'RouteLoaded':\n return { command: { _tag: 'ReleaseRoute', resource: event.resource }, state };\n case 'RenderScheduled':\n return {\n command: {\n _tag: 'DiscardRoute',\n rendererNavigation: event.rendererNavigation,\n resource: event.resource,\n },\n state,\n };\n default:\n return { command: null, state };\n }\n }\n\n switch (event._tag) {\n case 'DocumentLoaded':\n case 'FlightFailed':\n if (state.candidate._tag !== 'Loading') {\n throw new TypeError(`${event._tag} cannot follow ${state.candidate._tag}.`);\n }\n return { command: null, state: { _tag: 'Ready', visible: state.visible } };\n case 'RouteLoaded':\n if (state.candidate._tag !== 'Loading') {\n throw new TypeError(`RouteLoaded cannot follow ${state.candidate._tag}.`);\n }\n return {\n command: {\n _tag: 'PublishRoute',\n generation: event.generation,\n resource: event.resource,\n },\n state: {\n _tag: 'Navigating',\n candidate: {\n _tag: 'Publishing',\n generation: event.generation,\n lifetime: state.candidate.lifetime,\n resource: event.resource,\n },\n visible: state.visible,\n },\n };\n case 'RenderScheduled':\n if (state.candidate._tag !== 'Publishing') {\n throw new TypeError(`RenderScheduled cannot follow ${state.candidate._tag}.`);\n }\n if (state.candidate.resource !== event.resource) {\n throw new TypeError('RenderScheduled must use the published route resource.');\n }\n return {\n command: null,\n state: {\n _tag: 'Navigating',\n candidate: {\n _tag: 'Rendering',\n generation: event.generation,\n lifetime: state.candidate.lifetime,\n rendererNavigation: event.rendererNavigation,\n resource: event.resource,\n },\n visible: state.visible,\n },\n };\n case 'RenderCommitted':\n if (state.candidate._tag !== 'Rendering') {\n throw new TypeError(`RenderCommitted cannot follow ${state.candidate._tag}.`);\n }\n return {\n command: null,\n state: {\n _tag: 'Ready',\n visible: {\n _tag: 'Navigation',\n entry: { _tag: 'PendingCommit' },\n flight: { _tag: 'Streaming', resource: state.candidate.resource },\n generation: event.generation,\n },\n },\n };\n case 'NavigationAborted':\n if (state.candidate._tag === 'Loading') {\n return { command: null, state: { _tag: 'Ready', visible: state.visible } };\n }\n if (state.candidate._tag === 'Publishing') {\n return {\n command: { _tag: 'ReleaseRoute', resource: state.candidate.resource },\n state: { _tag: 'Ready', visible: state.visible },\n };\n }\n return {\n command: {\n _tag: 'DiscardRoute',\n rendererNavigation: state.candidate.rendererNavigation,\n resource: state.candidate.resource,\n },\n state: { _tag: 'Ready', visible: state.visible },\n };\n }\n};\n\ntype NavigationPreparation =\n | { readonly _tag: 'Handled' }\n | {\n readonly _tag: 'Rendered';\n readonly rendererNavigation: BrowserRendererNavigation;\n readonly resolvedDestination: URL;\n readonly resource: RouteResource;\n };\n\nexport const installClientRouter = Effect.gen(function* () {\n const browserRenderer = yield* BrowserRenderer;\n const navigationApi = yield* NavigationApi;\n const routeLoader = yield* RouteLoader;\n const run = yield* BrowserEffectRunner;\n const routerState = MutableRef.make<RouterState>({\n _tag: 'Ready',\n visible: { _tag: 'Settled' },\n });\n\n const dispatch = (event: RouterEvent) => {\n const transition = reduceRouterState(MutableRef.get(routerState), event);\n MutableRef.set(routerState, transition.state);\n return transition;\n };\n\n const executeRouterCommand = Effect.fnUntraced(function* (command: RouterCommand | null) {\n if (command === null) {\n return;\n }\n switch (command._tag) {\n case 'SupersedeCandidate': {\n const candidate = command.candidate;\n yield* Effect.sync(() => candidate.lifetime.abort());\n if (candidate._tag === 'Loading') {\n break;\n }\n if (candidate._tag === 'Publishing') {\n yield* candidate.resource.release;\n break;\n }\n yield* Effect.promise(() => candidate.rendererNavigation.discard()).pipe(\n Effect.ensuring(candidate.resource.release),\n );\n break;\n }\n case 'ReleaseRoute':\n yield* command.resource.release;\n break;\n case 'CacheRoute':\n yield* Effect.sync(() => command.cache(command.entry));\n break;\n case 'CacheAndReleaseRoute':\n yield* Effect.sync(() => command.resource.cache(command.entry));\n yield* command.resource.release;\n break;\n case 'DiscardRoute':\n yield* Effect.promise(() => command.rendererNavigation.discard()).pipe(\n Effect.ensuring(command.resource.release),\n );\n break;\n default:\n throw new TypeError(`Cannot execute the ${command._tag} lifecycle command here.`);\n }\n });\n\n const openDocument = (event: NavigateEvent, destination: URL) => {\n if (event.navigationType === 'traverse') {\n navigationApi.replaceDocument(destination.href);\n return;\n }\n navigationApi.navigate(destination.href, {\n history: event.navigationType === 'replace' ? 'replace' : 'push',\n info: NativeDocumentNavigationInfo,\n });\n };\n\n const onNavigate = (event: NavigateEvent) => {\n if (!isRoutedNavigation(event)) {\n return;\n }\n\n const destination = new URL(event.destination.url);\n const linkTransitionTypes = getLinkTransitionTypes(event);\n const generation: NavigationGeneration = Symbol('NavigationGeneration');\n const lifetime = new AbortController();\n const navigationSignal = AbortSignal.any([event.signal, lifetime.signal]);\n const begin = dispatch({\n _tag: 'BeginNavigation',\n generation,\n lifetime,\n });\n void run(executeRouterCommand(begin.command)).catch(() => undefined);\n // oxlint-disable-next-line effecttsgo/async-function -- Navigation handlers are native Promise boundaries.\n const handler = async (precommitController?: NavigationPrecommitController) => {\n const preparation = Promise.withResolvers<NavigationPreparation>();\n\n const navigationAction = Effect.gen(function* () {\n const resource = yield* routeLoader\n .load({\n destination: event.destination,\n navigationType: event.navigationType,\n })\n .pipe(\n Effect.onError(() =>\n Effect.sync(() => {\n dispatch({ _tag: 'FlightFailed', generation });\n }),\n ),\n );\n\n if (resource._tag === 'Document') {\n dispatch({ _tag: 'DocumentLoaded', generation });\n yield* resource.release;\n openDocument(event, destination);\n return { _tag: 'Handled' } as const;\n }\n\n const resolvedDestination = preserveRequestedHash(destination, resource.resolvedUrl);\n if (resolvedDestination.origin !== destination.origin) {\n dispatch({ _tag: 'DocumentLoaded', generation });\n yield* resource.release;\n openDocument(event, resolvedDestination);\n return { _tag: 'Handled' } as const;\n }\n\n if (\n destination.href !== resolvedDestination.href &&\n (precommitController === undefined || event.navigationType === 'traverse')\n ) {\n dispatch({ _tag: 'DocumentLoaded', generation });\n yield* resource.release;\n navigationApi.replaceDocument(resolvedDestination.href);\n return { _tag: 'Handled' } as const;\n }\n\n const transition = dispatch({ _tag: 'RouteLoaded', generation, resource });\n const command = transition.command;\n if (command?._tag === 'ReleaseRoute') {\n yield* command.resource.release;\n return { _tag: 'Handled' } as const;\n }\n if (command?._tag === 'PublishRoute') {\n const rendererNavigation = yield* Effect.sync(() => {\n let navigation!: BrowserRendererNavigation;\n startTransition(() => {\n const fromIndex =\n navigationApi.getTransition()?.from.index ??\n navigationApi.getCurrentEntry()?.index ??\n null;\n for (const type of getNavigationTransitionTypes(event, fromIndex)) {\n addTransitionType(type);\n }\n for (const type of linkTransitionTypes) {\n addTransitionType(type);\n }\n navigation = browserRenderer.navigate(command.resource.routeTree);\n });\n return navigation;\n });\n const scheduled = dispatch({\n _tag: 'RenderScheduled',\n generation: command.generation,\n rendererNavigation,\n resource: command.resource,\n });\n if (scheduled.command !== null) {\n yield* executeRouterCommand(scheduled.command);\n return { _tag: 'Handled' } as const;\n }\n return {\n _tag: 'Rendered',\n rendererNavigation,\n resolvedDestination,\n resource: command.resource,\n } as const;\n }\n\n throw new TypeError('A loaded route must be published or released.');\n });\n\n // oxlint-disable-next-line effecttsgo/async-function -- React Transition Actions are a native Promise boundary.\n startTransition(async () => {\n await run(navigationAction, { signal: navigationSignal })\n .then(preparation.resolve)\n .catch(preparation.reject);\n });\n\n const abortNavigation = Effect.suspend(() => {\n const transition = dispatch({ _tag: 'NavigationAborted', generation });\n return executeRouterCommand(transition.command);\n });\n const outcome = await preparation.promise.catch((cause) => {\n if (navigationSignal.aborted) {\n return run(abortNavigation.pipe(Effect.as({ _tag: 'Handled' } as NavigationPreparation)));\n }\n if (!event.cancelable && event.navigationType === 'traverse') {\n navigationApi.reloadDocument();\n return { _tag: 'Handled' } as NavigationPreparation;\n }\n throw cause;\n });\n if (outcome._tag === 'Handled') {\n return;\n }\n\n const { rendererNavigation, resolvedDestination, resource } = outcome;\n const waitForNavigationCommit = Effect.uninterruptibleMask((restore) =>\n restore(Effect.promise(() => rendererNavigation.committed)).pipe(\n Effect.tap(\n Effect.suspend(() => {\n const transition = dispatch({\n _tag: 'RenderCommitted',\n generation,\n });\n return executeRouterCommand(transition.command);\n }),\n ),\n Effect.onExit((exit) => (Exit.isFailure(exit) ? abortNavigation : Effect.void)),\n ),\n );\n try {\n await run(waitForNavigationCommit, { signal: navigationSignal });\n } catch (cause) {\n if (navigationSignal.aborted) {\n return;\n }\n throw cause;\n }\n\n const waitForRenderRetirement = Effect.gen(function* () {\n yield* Effect.promise(() => rendererNavigation.retired);\n dispatch({ _tag: 'RenderRetired', generation });\n }).pipe(\n // A newer generation may already be current when this render retires.\n Effect.ensuring(resource.release),\n Effect.ignore,\n );\n void run(waitForRenderRetirement).catch(() => undefined);\n\n const waitForFlightCompletion = Effect.gen(function* () {\n const flightExit = yield* Effect.exit(resource.completed);\n const transition = dispatch({\n _tag: Exit.isSuccess(flightExit) ? 'FlightCompleted' : 'FlightFailed',\n generation,\n });\n yield* executeRouterCommand(transition.command);\n });\n void run(waitForFlightCompletion).catch(() => undefined);\n\n if (destination.href !== resolvedDestination.href && precommitController !== undefined) {\n precommitController.redirect(resolvedDestination.href, { history: 'auto' });\n }\n const commitHistory = Effect.suspend(() => {\n const transition = dispatch({\n _tag: 'HistoryCommitted',\n entry: navigationApi.getCurrentEntry(),\n generation,\n });\n return executeRouterCommand(transition.command);\n });\n if (precommitController === undefined) {\n await run(commitHistory);\n } else {\n precommitController.addHandler(() => run(commitHistory));\n }\n };\n\n event.intercept(\n event.cancelable\n ? { precommitHandler: handler }\n : {\n // Browsers make some traversals non-cancelable so an application cannot trap users.\n handler,\n },\n );\n };\n\n yield* Effect.acquireRelease(\n Effect.sync(() => navigationApi.subscribe(onNavigate)),\n (unsubscribe) => Effect.sync(unsubscribe),\n );\n});\n"],"names":["Effect","Exit","MutableRef","addTransitionType","startTransition","BrowserEffectRunner","BrowserRenderer","NavigationApi","isRoutedNavigation","NativeDocumentNavigationInfo","preserveRequestedHash","RouteLoader","reservedTransitionTypes","Set","isApplicationTransitionType","type","getLinkTransitionTypes","event","HTMLAnchorElement","types","getNavigationTransitionTypes","fromIndex","reduceRouterState","state","visible","TypeError","nextState","installClientRouter","browserRenderer","navigationApi","routeLoader","run","routerState","dispatch","transition","executeRouterCommand","command","candidate","openDocument","destination","onNavigate","URL","linkTransitionTypes","generation","Symbol","lifetime","AbortController","navigationSignal","AbortSignal","begin","undefined","handler","precommitController","preparation","Promise","navigationAction","resource","resolvedDestination","rendererNavigation","navigation","scheduled","abortNavigation","outcome","cause","waitForNavigationCommit","restore","exit","waitForRenderRetirement","waitForFlightCompletion","flightExit","commitHistory","unsubscribe"],"mappings":"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"}
@@ -88,15 +88,14 @@ class FlightClient extends Context.Service()('ersc/client/FlightClient', {
88
88
  reason: 'UnexpectedResponse'
89
89
  });
90
90
  }
91
- const contentLocation = response.headers['content-location'];
92
- if (contentLocation === undefined) {
91
+ if (response.url === '') {
93
92
  return yield* new FlightLoadError({
94
- cause: new Error('Expected the Flight response to include a Content-Location header.'),
93
+ cause: new Error('Expected the Flight response to include a resolved URL.'),
95
94
  reason: 'UnexpectedResponse'
96
95
  });
97
96
  }
98
97
  const resolvedUrl = yield* Effect["try"]({
99
- try: ()=>new URL(contentLocation, flightRequest.destination),
98
+ try: ()=>new URL(response.url),
100
99
  catch: (cause)=>new FlightLoadError({
101
100
  cause,
102
101
  reason: 'UnexpectedResponse'
@@ -1 +1 @@
1
- {"version":3,"file":"client/flight-client.js","sources":["../../src/client/flight-client.ts"],"sourcesContent":["// oxlint-disable effecttsgo/process-env-in-effect -- Rspack replaces NODE_ENV at compile time.\nimport { Context, Deferred, Effect, Exit, Layer, Schema, Scope, Stream } from 'effect';\nimport { HttpBody, HttpClient, HttpClientRequest } from 'effect/unstable/http';\nimport {\n createFromReadableStream,\n type TemporaryReferenceSet,\n} from 'react-server-dom-rspack/client.browser';\n\nimport { FlightMediaType, ServerFnIdHeader, type FlightPayload } from '../rsc/flight';\nimport { InitialFlightStream } from './initial-flight-stream';\n\nexport class FlightLoadError extends Schema.TaggedError<FlightLoadError>()('FlightLoadError', {\n cause: Schema.Defect(),\n reason: Schema.Literals(['RequestFailed', 'UnexpectedResponse', 'DecodeFailed']),\n}) {}\n\nexport type FlightRequest =\n | {\n readonly _tag: 'Navigation';\n readonly destination: URL;\n }\n | {\n readonly _tag: 'ServerFunction';\n readonly body: BodyInit;\n readonly destination: URL;\n readonly id: string;\n readonly temporaryReferences: TemporaryReferenceSet;\n };\n\ntype DecodedFlight = {\n readonly completed: Effect.Effect<void, FlightLoadError>;\n readonly payload: FlightPayload;\n};\n\ntype FlightResource = DecodedFlight & {\n readonly _tag: 'Flight';\n readonly release: Effect.Effect<void>;\n readonly resolvedUrl: URL;\n};\n\ntype DocumentResource = {\n readonly _tag: 'Document';\n readonly release: Effect.Effect<void>;\n};\n\nexport class FlightClient extends Context.Service<FlightClient>()('ersc/client/FlightClient', {\n make: Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const initialFlight = yield* InitialFlightStream;\n\n const loadInitial = Effect.gen(function* () {\n const completed = Promise.withResolvers<void>();\n const stream = initialFlight.stream.pipeThrough(\n new TransformStream({\n flush: () => completed.resolve(),\n transform: (chunk, controller) => controller.enqueue(chunk),\n }),\n );\n const payload = yield* Effect.tryPromise({\n try: () =>\n createFromReadableStream<FlightPayload>(\n stream,\n process.env.NODE_ENV === 'development' ? { startTime: 0 } : undefined,\n ),\n catch: (cause) => new FlightLoadError({ cause, reason: 'DecodeFailed' }),\n });\n\n return {\n completed: Effect.promise(() => completed.promise),\n payload,\n } satisfies DecodedFlight;\n });\n\n const load = Effect.fnUntraced(function* (flightRequest: FlightRequest) {\n const parentScope = yield* Effect.scope;\n const responseScope = yield* Scope.fork(parentScope);\n const release = Scope.close(responseScope, Exit.void);\n\n return yield* Effect.gen(function* () {\n const client = httpClient.pipe(HttpClient.withScope);\n const request =\n flightRequest._tag === 'Navigation'\n ? HttpClientRequest.get(flightRequest.destination).pipe(\n HttpClientRequest.setHeader('accept', FlightMediaType),\n )\n : HttpClientRequest.post(flightRequest.destination).pipe(\n HttpClientRequest.setHeaders({\n accept: FlightMediaType,\n [ServerFnIdHeader]: flightRequest.id,\n }),\n HttpClientRequest.setBody(HttpBody.raw(flightRequest.body)),\n );\n const requestStartTime = process.env.NODE_ENV === 'development' ? performance.now() : 0;\n const response = yield* client.execute(request).pipe(\n Scope.provide(responseScope),\n Effect.mapError(\n (cause) =>\n new FlightLoadError({\n cause,\n reason: 'RequestFailed',\n }),\n ),\n );\n if (response.status < 200 || response.status >= 300) {\n if (flightRequest._tag === 'Navigation') {\n return { _tag: 'Document', release } satisfies DocumentResource;\n }\n return yield* new FlightLoadError({\n cause: new Error(`Flight request failed with status ${response.status}.`),\n reason: 'RequestFailed',\n });\n }\n const contentType = response.headers['content-type']\n ?.split(';', 1)[0]\n ?.trim()\n .toLowerCase();\n if (contentType !== FlightMediaType) {\n if (flightRequest._tag === 'Navigation') {\n return { _tag: 'Document', release } satisfies DocumentResource;\n }\n return yield* new FlightLoadError({\n cause: new Error(\n `Expected a ${FlightMediaType} response, received ${response.headers['content-type'] ?? 'no content type'}.`,\n ),\n reason: 'UnexpectedResponse',\n });\n }\n\n const contentLocation = response.headers['content-location'];\n if (contentLocation === undefined) {\n return yield* new FlightLoadError({\n cause: new Error('Expected the Flight response to include a Content-Location header.'),\n reason: 'UnexpectedResponse',\n });\n }\n const resolvedUrl = yield* Effect.try({\n try: () => new URL(contentLocation, flightRequest.destination),\n catch: (cause) =>\n new FlightLoadError({\n cause,\n reason: 'UnexpectedResponse',\n }),\n });\n\n const completed = yield* Deferred.make<void, FlightLoadError>();\n const responseBody = yield* Stream.toReadableStreamEffect(\n response.stream.pipe(\n Stream.onExit((exit) =>\n Deferred.done(\n completed,\n exit.pipe(\n Exit.mapError(\n (cause) =>\n new FlightLoadError({\n cause,\n reason: 'RequestFailed',\n }),\n ),\n Exit.asVoid,\n ),\n ),\n ),\n Stream.ensuring(release),\n ),\n );\n const decodeOptions =\n flightRequest._tag === 'ServerFunction'\n ? process.env.NODE_ENV === 'development'\n ? {\n startTime: requestStartTime,\n temporaryReferences: flightRequest.temporaryReferences,\n }\n : { temporaryReferences: flightRequest.temporaryReferences }\n : process.env.NODE_ENV === 'development'\n ? {\n startTime: requestStartTime,\n }\n : undefined;\n const payload = yield* Effect.tryPromise({\n try: () => createFromReadableStream<FlightPayload>(responseBody, decodeOptions),\n catch: (cause) =>\n new FlightLoadError({\n cause,\n reason: 'DecodeFailed',\n }),\n });\n\n return {\n _tag: 'Flight',\n completed: Deferred.await(completed),\n payload,\n release,\n resolvedUrl,\n } satisfies FlightResource;\n }).pipe(Effect.onError(() => release));\n });\n\n return { load, loadInitial };\n }),\n}) {\n static readonly layer = Layer.effect(this, this.make);\n\n static readonly layerTest = Layer.mock(this);\n}\n"],"names":["Context","Deferred","Effect","Exit","Layer","Schema","Scope","Stream","HttpBody","HttpClient","HttpClientRequest","createFromReadableStream","FlightMediaType","ServerFnIdHeader","InitialFlightStream","FlightLoadError","FlightClient","httpClient","initialFlight","loadInitial","completed","Promise","stream","TransformStream","chunk","controller","payload","process","undefined","cause","load","flightRequest","parentScope","responseScope","release","client","request","requestStartTime","performance","response","Error","contentType","contentLocation","resolvedUrl","URL","responseBody","exit","decodeOptions"],"mappings":"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"}
1
+ {"version":3,"file":"client/flight-client.js","sources":["../../src/client/flight-client.ts"],"sourcesContent":["// oxlint-disable effecttsgo/process-env-in-effect -- Rspack replaces NODE_ENV at compile time.\nimport { Context, Deferred, Effect, Exit, Layer, Schema, Scope, Stream } from 'effect';\nimport { HttpBody, HttpClient, HttpClientRequest } from 'effect/unstable/http';\nimport {\n createFromReadableStream,\n type TemporaryReferenceSet,\n} from 'react-server-dom-rspack/client.browser';\n\nimport { FlightMediaType, ServerFnIdHeader, type FlightPayload } from '../rsc/flight';\nimport { InitialFlightStream } from './initial-flight-stream';\n\nexport class FlightLoadError extends Schema.TaggedError<FlightLoadError>()('FlightLoadError', {\n cause: Schema.Defect(),\n reason: Schema.Literals(['RequestFailed', 'UnexpectedResponse', 'DecodeFailed']),\n}) {}\n\nexport type FlightRequest =\n | {\n readonly _tag: 'Navigation';\n readonly destination: URL;\n }\n | {\n readonly _tag: 'ServerFunction';\n readonly body: BodyInit;\n readonly destination: URL;\n readonly id: string;\n readonly temporaryReferences: TemporaryReferenceSet;\n };\n\ntype DecodedFlight = {\n readonly completed: Effect.Effect<void, FlightLoadError>;\n readonly payload: FlightPayload;\n};\n\ntype FlightResource = DecodedFlight & {\n readonly _tag: 'Flight';\n readonly release: Effect.Effect<void>;\n readonly resolvedUrl: URL;\n};\n\ntype DocumentResource = {\n readonly _tag: 'Document';\n readonly release: Effect.Effect<void>;\n};\n\nexport class FlightClient extends Context.Service<FlightClient>()('ersc/client/FlightClient', {\n make: Effect.gen(function* () {\n const httpClient = yield* HttpClient.HttpClient;\n const initialFlight = yield* InitialFlightStream;\n\n const loadInitial = Effect.gen(function* () {\n const completed = Promise.withResolvers<void>();\n const stream = initialFlight.stream.pipeThrough(\n new TransformStream({\n flush: () => completed.resolve(),\n transform: (chunk, controller) => controller.enqueue(chunk),\n }),\n );\n const payload = yield* Effect.tryPromise({\n try: () =>\n createFromReadableStream<FlightPayload>(\n stream,\n process.env.NODE_ENV === 'development' ? { startTime: 0 } : undefined,\n ),\n catch: (cause) => new FlightLoadError({ cause, reason: 'DecodeFailed' }),\n });\n\n return {\n completed: Effect.promise(() => completed.promise),\n payload,\n } satisfies DecodedFlight;\n });\n\n const load = Effect.fnUntraced(function* (flightRequest: FlightRequest) {\n const parentScope = yield* Effect.scope;\n const responseScope = yield* Scope.fork(parentScope);\n const release = Scope.close(responseScope, Exit.void);\n\n return yield* Effect.gen(function* () {\n const client = httpClient.pipe(HttpClient.withScope);\n const request =\n flightRequest._tag === 'Navigation'\n ? HttpClientRequest.get(flightRequest.destination).pipe(\n HttpClientRequest.setHeader('accept', FlightMediaType),\n )\n : HttpClientRequest.post(flightRequest.destination).pipe(\n HttpClientRequest.setHeaders({\n accept: FlightMediaType,\n [ServerFnIdHeader]: flightRequest.id,\n }),\n HttpClientRequest.setBody(HttpBody.raw(flightRequest.body)),\n );\n const requestStartTime = process.env.NODE_ENV === 'development' ? performance.now() : 0;\n const response = yield* client.execute(request).pipe(\n Scope.provide(responseScope),\n Effect.mapError(\n (cause) =>\n new FlightLoadError({\n cause,\n reason: 'RequestFailed',\n }),\n ),\n );\n if (response.status < 200 || response.status >= 300) {\n if (flightRequest._tag === 'Navigation') {\n return { _tag: 'Document', release } satisfies DocumentResource;\n }\n return yield* new FlightLoadError({\n cause: new Error(`Flight request failed with status ${response.status}.`),\n reason: 'RequestFailed',\n });\n }\n const contentType = response.headers['content-type']\n ?.split(';', 1)[0]\n ?.trim()\n .toLowerCase();\n if (contentType !== FlightMediaType) {\n if (flightRequest._tag === 'Navigation') {\n return { _tag: 'Document', release } satisfies DocumentResource;\n }\n return yield* new FlightLoadError({\n cause: new Error(\n `Expected a ${FlightMediaType} response, received ${response.headers['content-type'] ?? 'no content type'}.`,\n ),\n reason: 'UnexpectedResponse',\n });\n }\n\n if (response.url === '') {\n return yield* new FlightLoadError({\n cause: new Error('Expected the Flight response to include a resolved URL.'),\n reason: 'UnexpectedResponse',\n });\n }\n const resolvedUrl = yield* Effect.try({\n try: () => new URL(response.url),\n catch: (cause) =>\n new FlightLoadError({\n cause,\n reason: 'UnexpectedResponse',\n }),\n });\n\n const completed = yield* Deferred.make<void, FlightLoadError>();\n const responseBody = yield* Stream.toReadableStreamEffect(\n response.stream.pipe(\n Stream.onExit((exit) =>\n Deferred.done(\n completed,\n exit.pipe(\n Exit.mapError(\n (cause) =>\n new FlightLoadError({\n cause,\n reason: 'RequestFailed',\n }),\n ),\n Exit.asVoid,\n ),\n ),\n ),\n Stream.ensuring(release),\n ),\n );\n const decodeOptions =\n flightRequest._tag === 'ServerFunction'\n ? process.env.NODE_ENV === 'development'\n ? {\n startTime: requestStartTime,\n temporaryReferences: flightRequest.temporaryReferences,\n }\n : { temporaryReferences: flightRequest.temporaryReferences }\n : process.env.NODE_ENV === 'development'\n ? {\n startTime: requestStartTime,\n }\n : undefined;\n const payload = yield* Effect.tryPromise({\n try: () => createFromReadableStream<FlightPayload>(responseBody, decodeOptions),\n catch: (cause) =>\n new FlightLoadError({\n cause,\n reason: 'DecodeFailed',\n }),\n });\n\n return {\n _tag: 'Flight',\n completed: Deferred.await(completed),\n payload,\n release,\n resolvedUrl,\n } satisfies FlightResource;\n }).pipe(Effect.onError(() => release));\n });\n\n return { load, loadInitial };\n }),\n}) {\n static readonly layer = Layer.effect(this, this.make);\n\n static readonly layerTest = Layer.mock(this);\n}\n"],"names":["Context","Deferred","Effect","Exit","Layer","Schema","Scope","Stream","HttpBody","HttpClient","HttpClientRequest","createFromReadableStream","FlightMediaType","ServerFnIdHeader","InitialFlightStream","FlightLoadError","FlightClient","httpClient","initialFlight","loadInitial","completed","Promise","stream","TransformStream","chunk","controller","payload","process","undefined","cause","load","flightRequest","parentScope","responseScope","release","client","request","requestStartTime","performance","response","Error","contentType","resolvedUrl","URL","responseBody","exit","decodeOptions"],"mappings":"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"}
@@ -108,12 +108,13 @@ class ReactDOMRenderer extends Context.Service()('ersc/client/ReactDOMRenderer',
108
108
  }, [
109
109
  render
110
110
  ]);
111
+ const routeTree = render._tag === 'Discard' ? render.restore.routeTree : render.routeTree;
111
112
  return /*#__PURE__*/ jsx(BrowserErrorBoundary, {
112
113
  onError: reportError,
113
114
  onRendered: reportRendered,
114
115
  render: render,
115
116
  children: /*#__PURE__*/ jsx(RouteTree, {
116
- root: render.routeTree
117
+ root: routeTree
117
118
  })
118
119
  });
119
120
  }
@@ -1 +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 { BrowserRenderStatus } from './browser-render-status';\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 =\n | { readonly _tag: 'Uninitialized' }\n | { readonly _tag: 'Ready'; readonly render: BrowserRender }\n | { readonly _tag: 'Failed'; readonly render: BrowserRender };\ntype BrowserErrorBoundaryProps = {\n readonly children: ReactNode;\n readonly onError: (error: unknown, info: ErrorInfo) => void;\n readonly onRendered: () => void;\n readonly render: BrowserRender;\n};\n\nclass BrowserErrorBoundary extends Component<BrowserErrorBoundaryProps, BrowserErrorBoundaryState> {\n override readonly state: BrowserErrorBoundaryState = { _tag: 'Uninitialized' };\n\n static getDerivedStateFromError() {\n return { _tag: 'Failed' } as const;\n }\n\n static getDerivedStateFromProps(\n props: BrowserErrorBoundaryProps,\n state: BrowserErrorBoundaryState,\n ): BrowserErrorBoundaryState | null {\n if (state._tag !== 'Uninitialized' && props.render === state.render) {\n return null;\n }\n // Discard acknowledges a cancelled candidate, not a request to retry the failed tree.\n return state._tag === 'Failed' && props.render._tag === 'Discard'\n ? { _tag: 'Failed', render: props.render }\n : { _tag: 'Ready', render: props.render };\n }\n\n override componentDidCatch(error: unknown, info: ErrorInfo) {\n this.props.onError(error, info);\n }\n\n override componentDidMount() {\n if (this.state._tag === 'Ready') {\n this.props.onRendered();\n }\n }\n\n override componentDidUpdate() {\n if (this.state._tag === 'Ready') {\n this.props.onRendered();\n }\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 const renderStatus = yield* BrowserRenderStatus;\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(\n Effect.gen(function* () {\n yield* renderStatus.report({\n _tag: 'Failed',\n error,\n componentStack: info.componentStack ?? null,\n });\n yield* Effect.logError('Uncaught client render error.', error, info.componentStack);\n }),\n );\n };\n\n const reportRendered = () => {\n void run(renderStatus.report({ _tag: 'Rendered' }));\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} onRendered={reportRendered} render={render}>\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","BrowserRenderStatus","BrowserRenderer","BrowserFailureScreen","RouteTree","ReactDOMHydrationError","BrowserErrorBoundary","props","state","error","info","ReactDOMRenderer","browserRenderer","run","renderStatus","hydrate","container","initialPayload","browserRendererReady","Promise","reportError","reportRendered","Root","render","setRender","cause","root"],"mappings":"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"}
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 { BrowserRenderStatus } from './browser-render-status';\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 =\n | { readonly _tag: 'Uninitialized' }\n | { readonly _tag: 'Ready'; readonly render: BrowserRender }\n | { readonly _tag: 'Failed'; readonly render: BrowserRender };\ntype BrowserErrorBoundaryProps = {\n readonly children: ReactNode;\n readonly onError: (error: unknown, info: ErrorInfo) => void;\n readonly onRendered: () => void;\n readonly render: BrowserRender;\n};\n\nclass BrowserErrorBoundary extends Component<BrowserErrorBoundaryProps, BrowserErrorBoundaryState> {\n override readonly state: BrowserErrorBoundaryState = { _tag: 'Uninitialized' };\n\n static getDerivedStateFromError() {\n return { _tag: 'Failed' } as const;\n }\n\n static getDerivedStateFromProps(\n props: BrowserErrorBoundaryProps,\n state: BrowserErrorBoundaryState,\n ): BrowserErrorBoundaryState | null {\n if (state._tag !== 'Uninitialized' && props.render === state.render) {\n return null;\n }\n // Discard acknowledges a cancelled candidate, not a request to retry the failed tree.\n return state._tag === 'Failed' && props.render._tag === 'Discard'\n ? { _tag: 'Failed', render: props.render }\n : { _tag: 'Ready', render: props.render };\n }\n\n override componentDidCatch(error: unknown, info: ErrorInfo) {\n this.props.onError(error, info);\n }\n\n override componentDidMount() {\n if (this.state._tag === 'Ready') {\n this.props.onRendered();\n }\n }\n\n override componentDidUpdate() {\n if (this.state._tag === 'Ready') {\n this.props.onRendered();\n }\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 const renderStatus = yield* BrowserRenderStatus;\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(\n Effect.gen(function* () {\n yield* renderStatus.report({\n _tag: 'Failed',\n error,\n componentStack: info.componentStack ?? null,\n });\n yield* Effect.logError('Uncaught client render error.', error, info.componentStack);\n }),\n );\n };\n\n const reportRendered = () => {\n void run(renderStatus.report({ _tag: 'Rendered' }));\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 const routeTree = render._tag === 'Discard' ? render.restore.routeTree : render.routeTree;\n return (\n <BrowserErrorBoundary onError={reportError} onRendered={reportRendered} render={render}>\n <RouteTree root={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","BrowserRenderStatus","BrowserRenderer","BrowserFailureScreen","RouteTree","ReactDOMHydrationError","BrowserErrorBoundary","props","state","error","info","ReactDOMRenderer","browserRenderer","run","renderStatus","hydrate","container","initialPayload","browserRendererReady","Promise","reportError","reportRendered","Root","render","setRender","routeTree","cause","root"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { Context, Effect, Layer } from 'effect';
1
+ import { Context, Effect, Layer, Scope } from 'effect';
2
2
  import { BrowserRenderer } from './browser-renderer.js';
3
3
  import { NavigationApi } from './navigation-api.js';
4
4
  import { RouteLoader } from './route-loader.js';
@@ -26,5 +26,5 @@ export declare class RouteRefresher extends RouteRefresher_base {
26
26
  replace?: (replacement: RouteRefreshImplementation) => Effect.Effect<void, never, never>;
27
27
  }) => Layer.Layer<RouteRefresher, never, never>;
28
28
  }
29
- export declare const installRouteRefresh: Effect.Effect<void, never, BrowserRenderer | NavigationApi | RouteLoader | RouteRefresher | import("effect/Scope").Scope>;
29
+ export declare const installRouteRefresh: Effect.Effect<void, never, BrowserRenderer | NavigationApi | RouteLoader | RouteRefresher | Scope.Scope>;
30
30
  export {};
@@ -1,4 +1,4 @@
1
- import { Context, Effect, FiberMap, Layer, Ref } from "effect";
1
+ import { Context, Effect, Exit, FiberHandle, Layer, Ref, Scope } from "effect";
2
2
  import { addTransitionType, startTransition } from "react";
3
3
  import { BrowserRenderer } from "./browser-renderer.js";
4
4
  import { NavigationApi } from "./navigation-api.js";
@@ -17,7 +17,6 @@ import { RouteLoader } from "./route-loader.js";
17
17
 
18
18
 
19
19
 
20
- const CurrentRouteRefreshKey = 'CurrentRouteRefresh';
21
20
  class RouteRefresher extends Context.Service()('ersc/client/RouteRefresher', {
22
21
  make: Effect.gen(function*() {
23
22
  const navigationApi = yield* NavigationApi;
@@ -48,7 +47,8 @@ const installRouteRefresh = Effect.gen(function*() {
48
47
  const navigationApi = yield* NavigationApi;
49
48
  const routeLoader = yield* RouteLoader;
50
49
  const routeRefresher = yield* RouteRefresher;
51
- const refreshes = yield* FiberMap.make();
50
+ const refreshes = yield* FiberHandle.make();
51
+ const browserScope = yield* Effect.scope;
52
52
  const waitForNavigationIdle = Effect.suspend(()=>{
53
53
  const transition = navigationApi.getTransition();
54
54
  return transition === null ? Effect.succeed('Idle') : Effect.promise(()=>transition.finished.then(()=>undefined, ()=>undefined)).pipe(Effect.as('Settled'));
@@ -65,41 +65,56 @@ const installRouteRefresh = Effect.gen(function*() {
65
65
  return Effect.sync(unsubscribe);
66
66
  });
67
67
  const refreshRoute = Effect.fnUntraced(function*(transitionType) {
68
- const currentEntry = navigationApi.getCurrentEntry();
69
- const destination = new URL(currentEntry?.url ?? navigationApi.getCurrentUrl());
70
- const resource = yield* routeLoader.load({
71
- destination: {
72
- id: currentEntry?.id ?? '',
73
- url: destination.href
74
- },
75
- navigationType: 'replace'
76
- });
77
- if (resource._tag === 'Document') {
78
- yield* resource.release;
79
- yield* Effect.sync(navigationApi.reloadDocument);
80
- return;
81
- }
82
- const resolvedDestination = preserveRequestedHash(destination, resource.resolvedUrl);
83
- if (resolvedDestination.href !== destination.href) {
84
- yield* resource.release;
85
- yield* Effect.sync(()=>navigationApi.replaceDocument(resolvedDestination.href));
86
- return;
87
- }
88
- const commitRefresh = routeLoader.prepareRefresh(resource.routeTree);
89
- let renderCommitted;
90
- yield* Effect.sync(()=>{
91
- startTransition(()=>{
92
- addTransitionType(transitionType);
93
- renderCommitted = browserRenderer.refresh(resource.routeTree);
68
+ const responseScope = yield* Scope.make();
69
+ const render = yield* Effect.uninterruptibleMask(Effect.fnUntraced(function*(restore) {
70
+ const currentEntry = navigationApi.getCurrentEntry();
71
+ const destination = new URL(currentEntry?.url ?? navigationApi.getCurrentUrl());
72
+ const resource = yield* restore(routeLoader.load({
73
+ destination: {
74
+ id: currentEntry?.id ?? '',
75
+ url: destination.href
76
+ },
77
+ navigationType: 'replace'
78
+ }).pipe(Scope.provide(responseScope)));
79
+ const release = resource.release.pipe(Scope.use(responseScope));
80
+ if (resource._tag === 'Document') {
81
+ yield* release;
82
+ yield* Effect.sync(navigationApi.reloadDocument);
83
+ return;
84
+ }
85
+ const resolvedDestination = preserveRequestedHash(destination, resource.resolvedUrl);
86
+ if (resolvedDestination.href !== destination.href) {
87
+ yield* release;
88
+ yield* Effect.sync(()=>navigationApi.replaceDocument(resolvedDestination.href));
89
+ return;
90
+ }
91
+ const commitRefresh = routeLoader.prepareRefresh(resource.routeTree);
92
+ let published;
93
+ yield* Effect.sync(()=>{
94
+ startTransition(()=>{
95
+ addTransitionType(transitionType);
96
+ published = browserRenderer.refresh(resource.routeTree);
97
+ });
94
98
  });
95
- });
96
- yield* Effect.all([
97
- Effect.promise(()=>renderCommitted),
98
- resource.completed
99
- ], {
100
- concurrency: 'unbounded',
101
- discard: true
102
- }).pipe(Effect.andThen(Effect.sync(commitRefresh)), Effect.ensuring(resource.release));
99
+ // Finish publication and install its browser-owned lifetime before allowing cancellation.
100
+ yield* Effect.raceFirst(Effect.all([
101
+ Effect.promise(()=>published.committed),
102
+ resource.completed
103
+ ], {
104
+ concurrency: 'unbounded',
105
+ discard: true
106
+ }).pipe(Effect.andThen(Effect.sync(commitRefresh))), Effect.promise(()=>published.retired)).pipe(Effect.ensuring(release), Effect["catch"]((cause)=>Effect.logError('Failed to stream the refreshed route.', cause)), Effect.forkIn(browserScope, {
107
+ startImmediately: true
108
+ }));
109
+ yield* Effect.addFinalizer(()=>Effect.sync(()=>{
110
+ // The stream fiber awaits retirement; waiting here could block the replacement render.
111
+ void published.discard();
112
+ }));
113
+ return published;
114
+ }, Effect.onError((cause)=>Scope.close(responseScope, Exit.failCause(cause)))));
115
+ if (render !== undefined) {
116
+ yield* Effect.promise(()=>render.committed);
117
+ }
103
118
  });
104
119
  const refreshCurrentRoute = Effect.fnUntraced(function*(transitionType) {
105
120
  routeLoader.invalidate();
@@ -109,8 +124,8 @@ const installRouteRefresh = Effect.gen(function*() {
109
124
  yield* Effect.raceFirst(refreshRoute(transitionType), waitForRoutedNavigation);
110
125
  }, Effect.scoped, Effect["catch"]((cause)=>Effect.logError('Failed to refresh the current route.', cause)));
111
126
  yield* routeRefresher.replace({
112
- interruptCurrentRouteRefresh: FiberMap.remove(refreshes, CurrentRouteRefreshKey),
113
- refreshCurrentRoute: (transitionType)=>FiberMap.run(refreshes, CurrentRouteRefreshKey, refreshCurrentRoute(transitionType)).pipe(Effect.asVoid)
127
+ interruptCurrentRouteRefresh: FiberHandle.clear(refreshes),
128
+ refreshCurrentRoute: (transitionType)=>FiberHandle.run(refreshes, refreshCurrentRoute(transitionType)).pipe(Effect.asVoid)
114
129
  });
115
130
  });
116
131