effective-rsc 0.1.3 → 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.
- package/LLMS.md +17 -0
- package/README.md +5 -5
- package/dist/application/routes.d.ts +10 -10
- package/dist/application/routes.js.map +1 -1
- package/dist/build/dev.d.ts +4 -4
- package/dist/build/dev.js +22 -7
- package/dist/build/dev.js.map +1 -1
- package/dist/cli.js +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/client/browser-renderer.d.ts +25 -25
- package/dist/client/browser-renderer.js +80 -94
- package/dist/client/browser-renderer.js.map +1 -1
- package/dist/client/call-server.js +7 -5
- package/dist/client/call-server.js.map +1 -1
- package/dist/client/client-router.js +23 -7
- package/dist/client/client-router.js.map +1 -1
- package/dist/client/flight-client.js +3 -4
- package/dist/client/flight-client.js.map +1 -1
- package/dist/client/react-dom-renderer.js +2 -1
- package/dist/client/react-dom-renderer.js.map +1 -1
- package/dist/client/route-refresh.d.ts +2 -2
- package/dist/client/route-refresh.js +54 -39
- package/dist/client/route-refresh.js.map +1 -1
- package/dist/dev/panel.js +14 -14
- package/dist/dev/panel.js.map +1 -1
- package/dist/server/application.d.ts +2 -1
- package/dist/server/application.js +8 -6
- package/dist/server/application.js.map +1 -1
- package/docs/03-advanced/02-client-navigation/index.md +17 -0
- package/package.json +19 -19
|
@@ -2,24 +2,12 @@ import { Context, Effect, Layer, MutableRef } from "effect";
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
const getNavigationPhase = (lifecycle, navigation)=>{
|
|
6
|
-
const phase = lifecycle.phases.get(navigation);
|
|
7
|
-
if (phase === undefined) {
|
|
8
|
-
throw new TypeError('Browser navigation does not belong to this root.');
|
|
9
|
-
}
|
|
10
|
-
return phase;
|
|
11
|
-
};
|
|
12
|
-
const retireNavigation = (lifecycle, navigation)=>{
|
|
13
|
-
if (getNavigationPhase(lifecycle, navigation) !== 'Retired') {
|
|
14
|
-
lifecycle.phases.set(navigation, 'Retired');
|
|
15
|
-
navigation.retired.resolve();
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
5
|
class BrowserRenderer extends Context.Service()('ersc/client/BrowserRenderer', {
|
|
19
6
|
make: Effect.sync(()=>{
|
|
20
7
|
const state = MutableRef.make({
|
|
21
8
|
_tag: 'Uninitialized'
|
|
22
9
|
});
|
|
10
|
+
const publications = new WeakSet();
|
|
23
11
|
const getReadyState = ()=>{
|
|
24
12
|
const current = MutableRef.get(state);
|
|
25
13
|
if (current._tag === 'Uninitialized') {
|
|
@@ -37,109 +25,107 @@ class BrowserRenderer extends Context.Service()('ersc/client/BrowserRenderer', {
|
|
|
37
25
|
}
|
|
38
26
|
MutableRef.set(state, {
|
|
39
27
|
_tag: 'Ready',
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
},
|
|
44
|
-
phases: new WeakMap(),
|
|
45
|
-
stableRouteTree: initialRouteTree,
|
|
46
|
-
visible: {
|
|
47
|
-
_tag: 'Stable'
|
|
48
|
-
}
|
|
28
|
+
current: {
|
|
29
|
+
_tag: 'Initial',
|
|
30
|
+
routeTree: initialRouteTree
|
|
49
31
|
},
|
|
32
|
+
publicationOrder: 0,
|
|
33
|
+
liveRenders: new Map(),
|
|
50
34
|
publish
|
|
51
35
|
});
|
|
52
36
|
};
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
37
|
+
const publish = (render)=>{
|
|
38
|
+
publications.add(render);
|
|
39
|
+
getReadyState().publish(render);
|
|
40
|
+
};
|
|
41
|
+
const schedule = (routeTree, kind)=>{
|
|
42
|
+
const ready = getReadyState();
|
|
43
|
+
const order = ++ready.publicationOrder;
|
|
44
|
+
const render = {
|
|
45
|
+
_tag: kind,
|
|
46
|
+
order,
|
|
56
47
|
committed: Promise.withResolvers(),
|
|
57
48
|
retired: Promise.withResolvers(),
|
|
58
49
|
routeTree
|
|
59
50
|
};
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
navigation
|
|
64
|
-
};
|
|
65
|
-
publish({
|
|
66
|
-
_tag: 'Navigation',
|
|
67
|
-
navigation,
|
|
68
|
-
routeTree: navigation.routeTree
|
|
51
|
+
ready.liveRenders.set(render, {
|
|
52
|
+
_tag: 'Scheduled',
|
|
53
|
+
lastPublicationOrder: order
|
|
69
54
|
});
|
|
55
|
+
publish(render);
|
|
70
56
|
return {
|
|
71
|
-
committed:
|
|
57
|
+
committed: render.committed.promise,
|
|
72
58
|
discard: ()=>{
|
|
73
|
-
|
|
74
|
-
|
|
59
|
+
const live = ready.liveRenders.get(render);
|
|
60
|
+
// Cancellation can arrive before the caller observes a commit or retirement.
|
|
61
|
+
if (live?._tag !== 'Scheduled') {
|
|
62
|
+
return render.retired.promise;
|
|
75
63
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
64
|
+
ready.liveRenders.set(render, {
|
|
65
|
+
_tag: 'DiscardRequested',
|
|
66
|
+
lastPublicationOrder: order
|
|
67
|
+
});
|
|
68
|
+
const current = ready.current;
|
|
69
|
+
const restore = current._tag === 'Discard' ? current.restore : current;
|
|
70
|
+
const discardOrder = ++ready.publicationOrder;
|
|
71
|
+
if (restore._tag !== 'Initial') {
|
|
72
|
+
// Keep the tree alive even if another render commits before this discard.
|
|
73
|
+
// Reinsertion keeps the map ordered by each render's last publication.
|
|
74
|
+
ready.liveRenders.delete(restore);
|
|
75
|
+
ready.liveRenders.set(restore, {
|
|
76
|
+
_tag: 'Committed',
|
|
77
|
+
lastPublicationOrder: discardOrder
|
|
78
|
+
});
|
|
82
79
|
}
|
|
83
80
|
publish({
|
|
84
81
|
_tag: 'Discard',
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
visible: lifecycle.visible
|
|
82
|
+
order: discardOrder,
|
|
83
|
+
restore
|
|
88
84
|
});
|
|
89
|
-
return
|
|
85
|
+
return render.retired.promise;
|
|
90
86
|
},
|
|
91
|
-
retired:
|
|
87
|
+
retired: render.retired.promise
|
|
92
88
|
};
|
|
93
89
|
};
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
const committed = Promise.withResolvers();
|
|
97
|
-
lifecycle.active = {
|
|
98
|
-
_tag: 'Stable'
|
|
99
|
-
};
|
|
100
|
-
publish({
|
|
101
|
-
_tag: 'Refresh',
|
|
102
|
-
committed,
|
|
103
|
-
routeTree
|
|
104
|
-
});
|
|
105
|
-
return committed.promise;
|
|
106
|
-
};
|
|
90
|
+
const navigate = (routeTree)=>schedule(routeTree, 'Navigation');
|
|
91
|
+
const refresh = (routeTree)=>schedule(routeTree, 'Refresh');
|
|
107
92
|
const commit = (render)=>{
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
_tag: 'Navigation',
|
|
112
|
-
navigation: render.navigation
|
|
113
|
-
} : render._tag === 'Discard' ? render.visible : {
|
|
114
|
-
_tag: 'Stable'
|
|
115
|
-
};
|
|
116
|
-
lifecycle.visible = visible;
|
|
117
|
-
if (previousVisible._tag === 'Navigation' && (visible._tag !== 'Navigation' || visible.navigation !== previousVisible.navigation)) {
|
|
118
|
-
retireNavigation(lifecycle, previousVisible.navigation);
|
|
93
|
+
const ready = getReadyState();
|
|
94
|
+
if (render._tag === 'Initial') {
|
|
95
|
+
return;
|
|
119
96
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
97
|
+
if (!publications.has(render)) {
|
|
98
|
+
throw new TypeError('Browser render does not belong to this root.');
|
|
99
|
+
}
|
|
100
|
+
const current = ready.current;
|
|
101
|
+
if (current._tag !== 'Initial' && render.order < current.order) {
|
|
102
|
+
throw new TypeError('Browser renders must commit in publication order.');
|
|
103
|
+
}
|
|
104
|
+
const visible = render._tag === 'Discard' ? render.restore : render;
|
|
105
|
+
if (visible._tag !== 'Initial') {
|
|
106
|
+
const live = ready.liveRenders.get(visible);
|
|
107
|
+
if (live === undefined) {
|
|
108
|
+
throw new TypeError('A retired browser tree cannot commit.');
|
|
109
|
+
}
|
|
110
|
+
ready.liveRenders.set(visible, {
|
|
111
|
+
_tag: 'Committed',
|
|
112
|
+
lastPublicationOrder: live.lastPublicationOrder
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
ready.current = render;
|
|
116
|
+
if (render._tag !== 'Discard') {
|
|
117
|
+
render.committed.resolve();
|
|
118
|
+
}
|
|
119
|
+
// A later replacement commit supersedes earlier publications. A tree stays alive
|
|
120
|
+
// while visible or referenced by a newer publication, including a pending discard.
|
|
121
|
+
for (const [retained, live] of ready.liveRenders){
|
|
122
|
+
if (live.lastPublicationOrder > render.order) {
|
|
142
123
|
break;
|
|
124
|
+
}
|
|
125
|
+
if (retained !== visible) {
|
|
126
|
+
ready.liveRenders.delete(retained);
|
|
127
|
+
retained.retired.resolve();
|
|
128
|
+
}
|
|
143
129
|
}
|
|
144
130
|
};
|
|
145
131
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client/browser-renderer.js","sources":["../../src/client/browser-renderer.ts"],"sourcesContent":["import { Context, Effect, Layer, MutableRef } from 'effect';\n\nimport type { RouteTreeModel } from '../rsc/route-tree';\n\nexport type BrowserRendererNavigation = {\n readonly committed: Promise<void>;\n readonly discard: () => Promise<void>;\n readonly retired: Promise<void>;\n};\n\ntype BrowserRenderNavigationState = {\n readonly committed: PromiseWithResolvers<void>;\n readonly retired: PromiseWithResolvers<void>;\n readonly routeTree: RouteTreeModel;\n};\n\ntype BrowserRenderNavigationPhase =\n | 'Scheduled'\n | 'DiscardRequested'\n | 'Visible'\n | 'Completed'\n | 'Retired';\n\ntype BrowserRenderOwner =\n | { readonly _tag: 'Stable' }\n | { readonly _tag: 'Navigation'; readonly navigation: BrowserRenderNavigationState };\n\ntype BrowserRendererLifecycle = {\n active: BrowserRenderOwner;\n readonly phases: WeakMap<BrowserRenderNavigationState, BrowserRenderNavigationPhase>;\n stableRouteTree: RouteTreeModel;\n visible: BrowserRenderOwner;\n};\n\ntype BrowserRendererState =\n | { readonly _tag: 'Uninitialized' }\n | {\n readonly _tag: 'Ready';\n readonly lifecycle: BrowserRendererLifecycle;\n readonly publish: (render: BrowserRender) => void;\n };\n\nexport type BrowserRender =\n | { readonly _tag: 'Initial'; readonly routeTree: RouteTreeModel }\n | {\n readonly _tag: 'Navigation';\n readonly navigation: BrowserRenderNavigationState;\n readonly routeTree: RouteTreeModel;\n }\n | {\n readonly _tag: 'Discard';\n readonly navigation: BrowserRenderNavigationState;\n readonly routeTree: RouteTreeModel;\n readonly visible: BrowserRenderOwner;\n }\n | {\n readonly _tag: 'Refresh';\n readonly committed: PromiseWithResolvers<void>;\n readonly routeTree: RouteTreeModel;\n };\n\nconst getNavigationPhase = (\n lifecycle: BrowserRendererLifecycle,\n navigation: BrowserRenderNavigationState,\n) => {\n const phase = lifecycle.phases.get(navigation);\n if (phase === undefined) {\n throw new TypeError('Browser navigation does not belong to this root.');\n }\n return phase;\n};\n\nconst retireNavigation = (\n lifecycle: BrowserRendererLifecycle,\n navigation: BrowserRenderNavigationState,\n) => {\n if (getNavigationPhase(lifecycle, navigation) !== 'Retired') {\n lifecycle.phases.set(navigation, 'Retired');\n navigation.retired.resolve();\n }\n};\n\nexport class BrowserRenderer extends Context.Service<BrowserRenderer>()(\n 'ersc/client/BrowserRenderer',\n {\n make: Effect.sync(() => {\n const state = MutableRef.make<BrowserRendererState>({ _tag: 'Uninitialized' });\n const getReadyState = () => {\n const current = MutableRef.get(state);\n if (current._tag === 'Uninitialized') {\n throw new TypeError('BrowserRenderer must be initialized by ReactDOMRenderer.');\n }\n return current;\n };\n\n const initialize = (\n initialRouteTree: RouteTreeModel,\n publish: (render: BrowserRender) => void,\n ) => {\n const current = MutableRef.get(state);\n if (current._tag === 'Ready') {\n if (current.publish === publish) {\n return;\n }\n throw new TypeError('BrowserRenderer cannot be initialized by more than one React root.');\n }\n\n MutableRef.set(state, {\n _tag: 'Ready',\n lifecycle: {\n active: { _tag: 'Stable' },\n phases: new WeakMap<BrowserRenderNavigationState, BrowserRenderNavigationPhase>(),\n stableRouteTree: initialRouteTree,\n visible: { _tag: 'Stable' },\n },\n publish,\n });\n };\n\n const navigate = (routeTree: RouteTreeModel) => {\n const { lifecycle, publish } = getReadyState();\n const navigation: BrowserRenderNavigationState = {\n committed: Promise.withResolvers<void>(),\n retired: Promise.withResolvers<void>(),\n routeTree,\n };\n lifecycle.phases.set(navigation, 'Scheduled');\n lifecycle.active = { _tag: 'Navigation', navigation };\n publish({ _tag: 'Navigation', navigation, routeTree: navigation.routeTree });\n\n return {\n committed: navigation.committed.promise,\n discard: () => {\n if (getNavigationPhase(lifecycle, navigation) !== 'Scheduled') {\n throw new TypeError('Only a scheduled browser navigation can be discarded.');\n }\n lifecycle.phases.set(navigation, 'DiscardRequested');\n if (\n lifecycle.active._tag === 'Navigation' &&\n lifecycle.active.navigation === navigation\n ) {\n const visible = lifecycle.visible;\n lifecycle.active =\n visible._tag === 'Navigation' &&\n getNavigationPhase(lifecycle, visible.navigation) === 'Visible'\n ? visible\n : { _tag: 'Stable' };\n }\n publish({\n _tag: 'Discard',\n navigation,\n routeTree:\n lifecycle.visible._tag === 'Navigation'\n ? lifecycle.visible.navigation.routeTree\n : lifecycle.stableRouteTree,\n visible: lifecycle.visible,\n });\n return navigation.retired.promise;\n },\n retired: navigation.retired.promise,\n };\n };\n\n const refresh = (routeTree: RouteTreeModel) => {\n const { lifecycle, publish } = getReadyState();\n const committed = Promise.withResolvers<void>();\n lifecycle.active = { _tag: 'Stable' };\n publish({ _tag: 'Refresh', committed, routeTree });\n return committed.promise;\n };\n\n const commit = (render: BrowserRender) => {\n const { lifecycle } = getReadyState();\n const previousVisible = lifecycle.visible;\n const visible: BrowserRenderOwner =\n render._tag === 'Navigation'\n ? { _tag: 'Navigation', navigation: render.navigation }\n : render._tag === 'Discard'\n ? render.visible\n : { _tag: 'Stable' };\n lifecycle.visible = visible;\n\n if (\n previousVisible._tag === 'Navigation' &&\n (visible._tag !== 'Navigation' || visible.navigation !== previousVisible.navigation)\n ) {\n retireNavigation(lifecycle, previousVisible.navigation);\n }\n\n switch (render._tag) {\n case 'Initial':\n break;\n case 'Discard':\n retireNavigation(lifecycle, render.navigation);\n break;\n case 'Navigation':\n if (getNavigationPhase(lifecycle, render.navigation) === 'Scheduled') {\n lifecycle.phases.set(render.navigation, 'Visible');\n }\n if (\n lifecycle.active._tag === 'Navigation' &&\n lifecycle.active.navigation === render.navigation\n ) {\n lifecycle.active = { _tag: 'Stable' };\n lifecycle.stableRouteTree = render.routeTree;\n lifecycle.phases.set(render.navigation, 'Completed');\n }\n render.navigation.committed.resolve();\n break;\n case 'Refresh':\n lifecycle.stableRouteTree = render.routeTree;\n render.committed.resolve();\n break;\n }\n };\n\n return { commit, initialize, navigate, refresh };\n }),\n },\n) {\n static readonly layer = Layer.effect(this, this.make);\n\n static readonly layerTest = Layer.mock(this);\n}\n"],"names":["Context","Effect","Layer","MutableRef","getNavigationPhase","lifecycle","navigation","phase","undefined","TypeError","retireNavigation","BrowserRenderer","state","getReadyState","current","initialize","initialRouteTree","publish","WeakMap","navigate","routeTree","Promise","visible","refresh","committed","commit","render","previousVisible"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client/browser-renderer.js","sources":["../../src/client/browser-renderer.ts"],"sourcesContent":["import { Context, Effect, Layer, MutableRef } from 'effect';\n\nimport type { RouteTreeModel } from '../rsc/route-tree';\n\nexport type BrowserRendererNavigation = {\n readonly committed: Promise<void>;\n readonly discard: () => Promise<void>;\n readonly retired: Promise<void>;\n};\n\ntype InitialRender = {\n readonly _tag: 'Initial';\n readonly routeTree: RouteTreeModel;\n};\n\ntype RouteRender = {\n readonly _tag: 'Navigation' | 'Refresh';\n readonly order: number;\n readonly committed: PromiseWithResolvers<void>;\n readonly retired: PromiseWithResolvers<void>;\n readonly routeTree: RouteTreeModel;\n};\n\nexport type BrowserRender =\n | InitialRender\n | RouteRender\n | {\n readonly _tag: 'Discard';\n readonly order: number;\n readonly restore: InitialRender | RouteRender;\n };\n\ntype LiveRender = {\n readonly _tag: 'Scheduled' | 'DiscardRequested' | 'Committed';\n readonly lastPublicationOrder: number;\n};\n\ntype BrowserRendererState =\n | { readonly _tag: 'Uninitialized' }\n | {\n readonly _tag: 'Ready';\n current: BrowserRender;\n publicationOrder: number;\n readonly liveRenders: Map<RouteRender, LiveRender>;\n readonly publish: (render: BrowserRender) => void;\n };\n\nexport class BrowserRenderer extends Context.Service<BrowserRenderer>()(\n 'ersc/client/BrowserRenderer',\n {\n make: Effect.sync(() => {\n const state = MutableRef.make<BrowserRendererState>({ _tag: 'Uninitialized' });\n const publications = new WeakSet<BrowserRender>();\n const getReadyState = () => {\n const current = MutableRef.get(state);\n if (current._tag === 'Uninitialized') {\n throw new TypeError('BrowserRenderer must be initialized by ReactDOMRenderer.');\n }\n return current;\n };\n\n const initialize = (\n initialRouteTree: RouteTreeModel,\n publish: (render: BrowserRender) => void,\n ) => {\n const current = MutableRef.get(state);\n if (current._tag === 'Ready') {\n if (current.publish === publish) {\n return;\n }\n throw new TypeError('BrowserRenderer cannot be initialized by more than one React root.');\n }\n\n MutableRef.set(state, {\n _tag: 'Ready',\n current: { _tag: 'Initial', routeTree: initialRouteTree },\n publicationOrder: 0,\n liveRenders: new Map(),\n publish,\n });\n };\n\n const publish = (render: BrowserRender) => {\n publications.add(render);\n getReadyState().publish(render);\n };\n\n const schedule = (routeTree: RouteTreeModel, kind: 'Navigation' | 'Refresh') => {\n const ready = getReadyState();\n const order = ++ready.publicationOrder;\n const render: RouteRender = {\n _tag: kind,\n order,\n committed: Promise.withResolvers<void>(),\n retired: Promise.withResolvers<void>(),\n routeTree,\n };\n ready.liveRenders.set(render, { _tag: 'Scheduled', lastPublicationOrder: order });\n publish(render);\n\n return {\n committed: render.committed.promise,\n discard: () => {\n const live = ready.liveRenders.get(render);\n // Cancellation can arrive before the caller observes a commit or retirement.\n if (live?._tag !== 'Scheduled') {\n return render.retired.promise;\n }\n ready.liveRenders.set(render, {\n _tag: 'DiscardRequested',\n lastPublicationOrder: order,\n });\n const current = ready.current;\n const restore = current._tag === 'Discard' ? current.restore : current;\n const discardOrder = ++ready.publicationOrder;\n if (restore._tag !== 'Initial') {\n // Keep the tree alive even if another render commits before this discard.\n // Reinsertion keeps the map ordered by each render's last publication.\n ready.liveRenders.delete(restore);\n ready.liveRenders.set(restore, {\n _tag: 'Committed',\n lastPublicationOrder: discardOrder,\n });\n }\n publish({ _tag: 'Discard', order: discardOrder, restore });\n return render.retired.promise;\n },\n retired: render.retired.promise,\n };\n };\n\n const navigate = (routeTree: RouteTreeModel) => schedule(routeTree, 'Navigation');\n const refresh = (routeTree: RouteTreeModel) => schedule(routeTree, 'Refresh');\n\n const commit = (render: BrowserRender) => {\n const ready = getReadyState();\n if (render._tag === 'Initial') {\n return;\n }\n if (!publications.has(render)) {\n throw new TypeError('Browser render does not belong to this root.');\n }\n const current = ready.current;\n if (current._tag !== 'Initial' && render.order < current.order) {\n throw new TypeError('Browser renders must commit in publication order.');\n }\n const visible = render._tag === 'Discard' ? render.restore : render;\n if (visible._tag !== 'Initial') {\n const live = ready.liveRenders.get(visible);\n if (live === undefined) {\n throw new TypeError('A retired browser tree cannot commit.');\n }\n ready.liveRenders.set(visible, {\n _tag: 'Committed',\n lastPublicationOrder: live.lastPublicationOrder,\n });\n }\n ready.current = render;\n if (render._tag !== 'Discard') {\n render.committed.resolve();\n }\n\n // A later replacement commit supersedes earlier publications. A tree stays alive\n // while visible or referenced by a newer publication, including a pending discard.\n for (const [retained, live] of ready.liveRenders) {\n if (live.lastPublicationOrder > render.order) {\n break;\n }\n if (retained !== visible) {\n ready.liveRenders.delete(retained);\n retained.retired.resolve();\n }\n }\n };\n\n return { commit, initialize, navigate, refresh };\n }),\n },\n) {\n static readonly layer = Layer.effect(this, this.make);\n\n static readonly layerTest = Layer.mock(this);\n}\n"],"names":["Context","Effect","Layer","MutableRef","BrowserRenderer","state","publications","WeakSet","getReadyState","current","TypeError","initialize","initialRouteTree","publish","Map","render","schedule","routeTree","kind","ready","order","Promise","live","restore","discardOrder","navigate","refresh","commit","visible","undefined","retained"],"mappings":"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"}
|
|
@@ -125,22 +125,24 @@ const installCallServer = Effect.gen(function*() {
|
|
|
125
125
|
return;
|
|
126
126
|
}
|
|
127
127
|
const commitRefresh = routeLoader.prepareRefresh(resource.payload.routeTree);
|
|
128
|
-
let
|
|
128
|
+
let published;
|
|
129
129
|
yield* Effect.sync(()=>{
|
|
130
130
|
startTransition(()=>{
|
|
131
131
|
addTransitionType('server-function');
|
|
132
132
|
// Do not return the commit Promise from React's Transition Action. React cannot commit the
|
|
133
133
|
// render until that Action ends.
|
|
134
|
-
|
|
134
|
+
published = browserRenderer.refresh(resource.payload.routeTree);
|
|
135
135
|
});
|
|
136
136
|
});
|
|
137
|
-
yield* Effect.all([
|
|
137
|
+
yield* Effect.raceFirst(Effect.all([
|
|
138
138
|
resource.completed,
|
|
139
|
-
Effect.promise(()=>
|
|
139
|
+
Effect.promise(()=>published.committed)
|
|
140
140
|
], {
|
|
141
141
|
concurrency: 'unbounded',
|
|
142
142
|
discard: true
|
|
143
|
-
}).pipe(Effect.andThen(Effect.sync(commitRefresh)), Effect.
|
|
143
|
+
}).pipe(Effect.andThen(Effect.sync(commitRefresh))), Effect.promise(()=>published.retired)).pipe(Effect.ensuring(resource.release), Effect.forkScoped({
|
|
144
|
+
startImmediately: true
|
|
145
|
+
}));
|
|
144
146
|
});
|
|
145
147
|
yield* Effect.sync(()=>{
|
|
146
148
|
setServerCallback((id, args)=>{
|
|
@@ -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
|
|
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":"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"}
|
|
@@ -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:
|
|
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
|
-
|
|
557
|
+
dispatch({
|
|
542
558
|
_tag: 'RenderRetired',
|
|
543
559
|
generation
|
|
544
560
|
});
|
|
545
|
-
|
|
546
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
98
|
+
try: ()=>new URL(response.url),
|
|
100
99
|
catch: (cause)=>new FlightLoadError({
|
|
101
100
|
cause,
|
|
102
101
|
reason: 'UnexpectedResponse'
|