effective-rsc 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LLMS.md +54 -10
- package/README.md +3 -3
- package/dist/application/page.d.ts +14 -7
- package/dist/application/page.js +5 -3
- package/dist/application/page.js.map +1 -1
- package/dist/application/route-graph.d.ts +1 -1
- package/dist/application/route-graph.js.map +1 -1
- package/dist/application/server-fn.d.ts +10 -6
- package/dist/application/server-fn.js +9 -4
- package/dist/application/server-fn.js.map +1 -1
- package/dist/build/dev.d.ts +11 -11
- package/dist/build/dev.js +21 -5
- package/dist/build/dev.js.map +1 -1
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/client/application.js +12 -9
- package/dist/client/application.js.map +1 -1
- package/dist/client/browser-capabilities.d.ts +2 -9
- package/dist/client/browser-capabilities.js +3 -14
- package/dist/client/browser-capabilities.js.map +1 -1
- package/dist/client/browser-render-status.d.ts +25 -0
- package/dist/client/browser-render-status.js +20 -0
- package/dist/client/browser-render-status.js.map +1 -0
- package/dist/client/call-server.js +7 -2
- package/dist/client/call-server.js.map +1 -1
- package/dist/client/navigation-api.js +5 -4
- package/dist/client/navigation-api.js.map +1 -1
- package/dist/client/react-dom-renderer.d.ts +3 -2
- package/dist/client/react-dom-renderer.js +43 -2
- package/dist/client/react-dom-renderer.js.map +1 -1
- package/dist/client/route-refresh.d.ts +1 -2
- package/dist/client/route-refresh.js +5 -18
- package/dist/client/route-refresh.js.map +1 -1
- package/dist/dev/client.d.ts +2 -1
- package/dist/dev/client.js +46 -6
- package/dist/dev/client.js.map +1 -1
- package/dist/dev/panel.d.ts +12 -1
- package/dist/dev/panel.js +73 -5
- package/dist/dev/panel.js.map +1 -1
- package/dist/dev/runtime-failure.d.ts +1 -0
- package/dist/dev/runtime-failure.js +7 -1
- package/dist/dev/runtime-failure.js.map +1 -1
- package/dist/rsc/render-route-tree.d.ts +3 -3
- package/dist/rsc/render-route-tree.js +2 -2
- package/dist/rsc/render-route-tree.js.map +1 -1
- package/dist/server/application.js +54 -35
- package/dist/server/application.js.map +1 -1
- package/dist/server/server-fn-request.js +3 -1
- package/dist/server/server-fn-request.js.map +1 -1
- package/docs/02-guides/01-server-functions/50_greet.ts +18 -0
- package/docs/02-guides/01-server-functions/60_greeting-form.tsx +23 -0
- package/docs/02-guides/01-server-functions/index.md +7 -0
- package/docs/02-guides/03-routing/index.md +5 -1
- package/docs/03-advanced/02-client-navigation/index.md +6 -3
- package/docs/03-advanced/03-server-function-execution-and-refresh/index.md +3 -1
- package/docs/04-api-reference/02-page/index.md +8 -3
- package/docs/04-api-reference/06-middleware/index.md +2 -2
- package/docs/04-api-reference/08-server-fn/index.md +23 -0
- package/package.json +1 -1
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["import * as BunHttpServer from '@effect/platform-bun/BunHttpServer';\nimport * as BunRuntime from '@effect/platform-bun/BunRuntime';\nimport * as BunServices from '@effect/platform-bun/BunServices';\nimport { Config, Effect, Layer, Schema } from 'effect';\nimport * as Command from 'effect/unstable/cli/Command';\nimport * as Flag from 'effect/unstable/cli/Flag';\n\nimport PackageJson from '../package.json' with { type: 'json' };\nimport { loadCompiledServer, makeRunnableServerLayer } from './build/compiled-server';\nimport { EnvironmentConfig } from './build/contract';\nimport {\n ApplicationIdleTimeoutSeconds,\n ApplicationMaxRequestBodySizeBytes,\n DefaultApplicationHostname,\n DefaultApplicationPort,\n} from './server/server-config';\n\nexport class BuildModuleLoadError extends Schema.TaggedError<BuildModuleLoadError>()(\n 'BuildModuleLoadError',\n {\n message: Schema.String,\n cause: Schema.Defect(),\n },\n) {}\n\nexport class DevModuleLoadError extends Schema.TaggedError<DevModuleLoadError>()(\n 'DevModuleLoadError',\n {\n message: Schema.String,\n cause: Schema.Defect(),\n },\n) {}\n\nconst start = Effect.fn('ersc/cli/start')(function* ({\n hostname,\n port,\n root,\n}: {\n readonly hostname: string;\n readonly port: number;\n readonly root: string;\n}) {\n const bundle = yield* loadCompiledServer(root);\n const ServerLayer = yield* makeRunnableServerLayer({\n bundle,\n clientAssetsCacheControl: EnvironmentConfig.production.clientAssetsCacheControl,\n clientOutputDir: EnvironmentConfig.production.clientOutputDir,\n hostname,\n port,\n root,\n });\n\n return yield* Layer.launch(ServerLayer);\n});\n\nconst runBuild = Effect.fnUntraced(function* () {\n const { buildApplication } = yield* Effect.tryPromise({\n try: () => import('./build/build'),\n catch: (cause) =>\n new BuildModuleLoadError({\n message: 'Failed to load the effective-rsc application compiler.',\n cause,\n }),\n });\n\n yield* buildApplication({ root: process.cwd() });\n});\n\nconst buildCommand = Command.make('build').pipe(\n Command.withDescription('Compile an effective-rsc application with Rspack.'),\n Command.withHandler(runBuild),\n);\n\nconst hostname = Flag.string('hostname').pipe(\n Flag.withDescription('Hostname to bind (defaults to HOST or localhost)'),\n Flag.withFallbackConfig(\n Config.string('HOST').pipe(Config.withDefault(DefaultApplicationHostname)),\n ),\n Flag.withSchema(Schema.NonEmptyString),\n);\n\nconst port = Flag.integer('port').pipe(\n Flag.withDescription(`Port to bind (defaults to PORT or ${DefaultApplicationPort})`),\n Flag.withFallbackConfig(Config.int('PORT').pipe(Config.withDefault(DefaultApplicationPort))),\n Flag.withSchema(\n Schema.Int.check(\n Schema.isBetween({\n minimum: 1,\n maximum: 65_535,\n }),\n ),\n ),\n);\n\nconst runDev = Effect.fnUntraced(function* ({\n hostname,\n port,\n}: {\n readonly hostname: string;\n readonly port: number;\n}) {\n const { devApplication } = yield* Effect.tryPromise({\n try: () => import('./build/dev'),\n catch: (cause) =>\n new DevModuleLoadError({\n message: 'Failed to load the effective-rsc development compiler.',\n cause,\n }),\n });\n\n yield* devApplication({\n hostname,\n port,\n root: process.cwd(),\n }).pipe(\n Effect.provide(\n BunHttpServer.layer({\n development: true,\n hostname,\n idleTimeout: ApplicationIdleTimeoutSeconds,\n maxRequestBodySize: ApplicationMaxRequestBodySizeBytes,\n port,\n }),\n ),\n Effect.scoped,\n );\n});\n\nconst devCommand = Command.make('dev', { hostname, port }).pipe(\n Command.withDescription('Start an effective-rsc application in development mode.'),\n Command.withHandler(runDev),\n);\n\nconst startCommand = Command.make('start', { hostname, port }).pipe(\n Command.withDescription('Start the compiled application with Bun.'),\n Command.withHandler(({ hostname, port }) => start({ hostname, port, root: process.cwd() })),\n);\n\nconst cli = Command.make('ersc').pipe(\n Command.withDescription('Build and run an effective-rsc application.'),\n Command.withSubcommands([devCommand, buildCommand, startCommand]),\n);\n\nconst program = Command.run(cli, { version: PackageJson.version }).pipe(\n Effect.provide(BunServices.layer),\n);\n\nBunRuntime.runMain(program);\n"],"names":["BunHttpServer","BunRuntime","BunServices","Config","Effect","Layer","Schema","Command","Flag","PackageJson","loadCompiledServer","makeRunnableServerLayer","EnvironmentConfig","ApplicationIdleTimeoutSeconds","ApplicationMaxRequestBodySizeBytes","DefaultApplicationHostname","DefaultApplicationPort","BuildModuleLoadError","DevModuleLoadError","start","hostname","port","root","bundle","ServerLayer","runBuild","buildApplication","cause","process","buildCommand","runDev","devApplication","devCommand","startCommand","cli","program"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAoE;AACN;AACE;AACT;AACA;AACN;AAEe;AACsB;AACjC;AAMrB;AAEzB,MAAMiB,oBAAoBA,SAASX,kBAAkB,GAC1D,wBACA;IACE,SAASA,aAAa;IACtB,OAAOA,aAAa;AACtB;AACC;AAEI,MAAMY,kBAAkBA,SAASZ,kBAAkB,GACxD,sBACA;IACE,SAASA,aAAa;IACtB,OAAOA,aAAa;AACtB;AACC;AAEH,MAAMa,KAAKA,GAAGf,SAAS,CAAC,kBAAkB,UAAW,EACnDgB,QAAQ,EACRC,IAAI,EACJC,IAAI,EAKL;IACC,MAAMC,SAAS,OAAOb,kBAAkBA,CAACY;IACzC,MAAME,cAAc,OAAOb,uBAAuBA,CAAC;QACjDY;QACA,0BAA0BX,qDAAqD;QAC/E,iBAAiBA,4CAA4C;QAC7DQ;QACAC;QACAC;IACF;IAEA,OAAO,OAAOjB,YAAY,CAACmB;AAC7B;AAEA,MAAMC,QAAQA,GAAGrB,iBAAiB,CAAC;IACjC,MAAM,EAAEsB,gBAAgB,EAAE,GAAG,OAAOtB,iBAAiB,CAAC;QACpD,KAAK,IAAM,0BAAuB;QAClC,OAAO,CAACuB,QACN,IAAIV,oBAAoBA,CAAC;gBACvB,SAAS;gBACTU;YACF;IACJ;IAEA,OAAOD,iBAAiB;QAAE,MAAME,QAAQ,GAAG;IAAG;AAChD;AAEA,MAAMC,YAAYA,GAAGtB,2DAAY,CAAC,SAAS,IAAI,CAC7CA,sEAAuB,CAAC,sDACxBA,kEAAmB,CAACkB,QAAQA;AAG9B,MAAML,YAAQA,GAAGZ,0DAAW,CAAC,YAAY,IAAI,CAC3CA,mEAAoB,CAAC,qDACrBA,sEAAuB,CACrBL,aAAa,CAAC,QAAQ,IAAI,CAACA,kBAAkB,CAACY,0BAA0BA,KAE1EP,8DAAe,CAACF,qBAAqB;AAGvC,MAAMe,QAAIA,GAAGb,2DAAY,CAAC,QAAQ,IAAI,CACpCA,mEAAoB,CAAC,CAAC,kCAAkC,EAAEQ,sBAAsBA,CAAC,CAAC,CAAC,GACnFR,sEAAuB,CAACL,UAAU,CAAC,QAAQ,IAAI,CAACA,kBAAkB,CAACa,sBAAsBA,KACzFR,8DAAe,CACbF,gBAAgB,CACdA,gBAAgB,CAAC;IACf,SAAS;IACT,SAAS;AACX;AAKN,MAAMwB,MAAMA,GAAG1B,iBAAiB,CAAC,UAAW,EAC1CgB,QAAQ,EACRC,IAAI,EAIL;IACC,MAAM,EAAEU,cAAc,EAAE,GAAG,OAAO3B,iBAAiB,CAAC;QAClD,KAAK,IAAM,wBAAqB;QAChC,OAAO,CAACuB,QACN,IAAIT,kBAAkBA,CAAC;gBACrB,SAAS;gBACTS;YACF;IACJ;IAEA,OAAOI,eAAe;QACpBX;QACAC;QACA,MAAMO,QAAQ,GAAG;IACnB,GAAG,IAAI,CACLxB,cAAc,CACZJ,mEAAmB,CAAC;QAClB,aAAa;
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["import * as BunHttpServer from '@effect/platform-bun/BunHttpServer';\nimport * as BunRuntime from '@effect/platform-bun/BunRuntime';\nimport * as BunServices from '@effect/platform-bun/BunServices';\nimport { Config, Effect, Layer, Schema } from 'effect';\nimport * as Command from 'effect/unstable/cli/Command';\nimport * as Flag from 'effect/unstable/cli/Flag';\n\nimport PackageJson from '../package.json' with { type: 'json' };\nimport { loadCompiledServer, makeRunnableServerLayer } from './build/compiled-server';\nimport { EnvironmentConfig } from './build/contract';\nimport {\n ApplicationIdleTimeoutSeconds,\n ApplicationMaxRequestBodySizeBytes,\n DefaultApplicationHostname,\n DefaultApplicationPort,\n} from './server/server-config';\n\nexport class BuildModuleLoadError extends Schema.TaggedError<BuildModuleLoadError>()(\n 'BuildModuleLoadError',\n {\n message: Schema.String,\n cause: Schema.Defect(),\n },\n) {}\n\nexport class DevModuleLoadError extends Schema.TaggedError<DevModuleLoadError>()(\n 'DevModuleLoadError',\n {\n message: Schema.String,\n cause: Schema.Defect(),\n },\n) {}\n\nconst start = Effect.fn('ersc/cli/start')(function* ({\n hostname,\n port,\n root,\n}: {\n readonly hostname: string;\n readonly port: number;\n readonly root: string;\n}) {\n const bundle = yield* loadCompiledServer(root);\n const ServerLayer = yield* makeRunnableServerLayer({\n bundle,\n clientAssetsCacheControl: EnvironmentConfig.production.clientAssetsCacheControl,\n clientOutputDir: EnvironmentConfig.production.clientOutputDir,\n hostname,\n port,\n root,\n });\n\n return yield* Layer.launch(ServerLayer);\n});\n\nconst runBuild = Effect.fnUntraced(function* () {\n const { buildApplication } = yield* Effect.tryPromise({\n try: () => import('./build/build'),\n catch: (cause) =>\n new BuildModuleLoadError({\n message: 'Failed to load the effective-rsc application compiler.',\n cause,\n }),\n });\n\n yield* buildApplication({ root: process.cwd() });\n});\n\nconst buildCommand = Command.make('build').pipe(\n Command.withDescription('Compile an effective-rsc application with Rspack.'),\n Command.withHandler(runBuild),\n);\n\nconst hostname = Flag.string('hostname').pipe(\n Flag.withDescription('Hostname to bind (defaults to HOST or localhost)'),\n Flag.withFallbackConfig(\n Config.string('HOST').pipe(Config.withDefault(DefaultApplicationHostname)),\n ),\n Flag.withSchema(Schema.NonEmptyString),\n);\n\nconst port = Flag.integer('port').pipe(\n Flag.withDescription(`Port to bind (defaults to PORT or ${DefaultApplicationPort})`),\n Flag.withFallbackConfig(Config.int('PORT').pipe(Config.withDefault(DefaultApplicationPort))),\n Flag.withSchema(\n Schema.Int.check(\n Schema.isBetween({\n minimum: 1,\n maximum: 65_535,\n }),\n ),\n ),\n);\n\nconst runDev = Effect.fnUntraced(function* ({\n hostname,\n port,\n}: {\n readonly hostname: string;\n readonly port: number;\n}) {\n const { devApplication } = yield* Effect.tryPromise({\n try: () => import('./build/dev'),\n catch: (cause) =>\n new DevModuleLoadError({\n message: 'Failed to load the effective-rsc development compiler.',\n cause,\n }),\n });\n\n yield* devApplication({\n hostname,\n port,\n root: process.cwd(),\n }).pipe(\n Effect.provide(\n BunHttpServer.layer({\n development: true,\n // Explicit dev shutdown interrupts request scopes before releasing their generations.\n disablePreemptiveShutdown: true,\n hostname,\n idleTimeout: ApplicationIdleTimeoutSeconds,\n maxRequestBodySize: ApplicationMaxRequestBodySizeBytes,\n port,\n }),\n ),\n Effect.scoped,\n );\n});\n\nconst devCommand = Command.make('dev', { hostname, port }).pipe(\n Command.withDescription('Start an effective-rsc application in development mode.'),\n Command.withHandler(runDev),\n);\n\nconst startCommand = Command.make('start', { hostname, port }).pipe(\n Command.withDescription('Start the compiled application with Bun.'),\n Command.withHandler(({ hostname, port }) => start({ hostname, port, root: process.cwd() })),\n);\n\nconst cli = Command.make('ersc').pipe(\n Command.withDescription('Build and run an effective-rsc application.'),\n Command.withSubcommands([devCommand, buildCommand, startCommand]),\n);\n\nconst program = Command.run(cli, { version: PackageJson.version }).pipe(\n Effect.provide(BunServices.layer),\n);\n\nBunRuntime.runMain(program);\n"],"names":["BunHttpServer","BunRuntime","BunServices","Config","Effect","Layer","Schema","Command","Flag","PackageJson","loadCompiledServer","makeRunnableServerLayer","EnvironmentConfig","ApplicationIdleTimeoutSeconds","ApplicationMaxRequestBodySizeBytes","DefaultApplicationHostname","DefaultApplicationPort","BuildModuleLoadError","DevModuleLoadError","start","hostname","port","root","bundle","ServerLayer","runBuild","buildApplication","cause","process","buildCommand","runDev","devApplication","devCommand","startCommand","cli","program"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Effect, Layer } from "effect";
|
|
2
|
-
import {
|
|
2
|
+
import { navigationMode } from "./browser-capabilities.js";
|
|
3
3
|
import { BrowserEffectRunner } from "./browser-effect-runner.js";
|
|
4
|
+
import { BrowserRenderStatus } from "./browser-render-status.js";
|
|
4
5
|
import { BrowserRenderer } from "./browser-renderer.js";
|
|
5
6
|
import { showBrowserFailure } from "./browser-screen.js";
|
|
6
7
|
import { installCallServer } from "./call-server.js";
|
|
@@ -27,6 +28,7 @@ import * as __rspack_external__effect_platform_browser_BrowserHttpClient_04160dc
|
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
|
|
31
|
+
|
|
30
32
|
// oxlint-disable effecttsgo/process-env, effecttsgo/process-env-in-effect -- Rspack replaces NODE_ENV at compile time.
|
|
31
33
|
|
|
32
34
|
|
|
@@ -42,28 +44,29 @@ import * as __rspack_external__effect_platform_browser_BrowserHttpClient_04160dc
|
|
|
42
44
|
|
|
43
45
|
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
|
|
48
|
+
const BrowserServicesLayer = Layer.mergeAll(BrowserEffectRunner.layer, BrowserRenderer.layer, BrowserRenderStatus.layer, FlightClient.layer, NavigationApi.layer).pipe(Layer.provide(InitialFlightStream.layer));
|
|
46
49
|
const BrowserLayer = Layer.mergeAll(ReactDOMRenderer.layer, RouteLoader.layer, RouteRefresher.layer).pipe(Layer.provideMerge(BrowserServicesLayer), Layer.provide(__rspack_external__effect_platform_browser_BrowserHttpClient_04160dce.layerFetch));
|
|
47
50
|
const renderBrowserFailure = Effect.sync(showBrowserFailure);
|
|
48
|
-
const
|
|
49
|
-
const activateClientNavigation = Effect.gen(function*() {
|
|
51
|
+
const activateBrowser = Effect.gen(function*() {
|
|
50
52
|
const routeLoader = yield* RouteLoader;
|
|
51
53
|
const reactDOMRenderer = yield* ReactDOMRenderer;
|
|
52
54
|
const initialPayload = yield* routeLoader.loadInitial;
|
|
53
55
|
yield* reactDOMRenderer.hydrate(document, initialPayload);
|
|
54
|
-
yield* installClientRouter;
|
|
55
56
|
yield* installRouteRefresh;
|
|
56
57
|
yield* installCallServer;
|
|
58
|
+
const mode = yield* navigationMode;
|
|
59
|
+
if (mode === 'Client') {
|
|
60
|
+
yield* installClientRouter;
|
|
61
|
+
}
|
|
57
62
|
});
|
|
58
63
|
const browserMain = Effect.scoped(Effect.gen(function*() {
|
|
59
64
|
if (process.env.NODE_ENV === 'development') {
|
|
60
65
|
yield* Effect.tryPromise(()=>import("../dev/client.js")).pipe(Effect.flatMap(({ startDevClient })=>startDevClient), Effect["catch"]((cause)=>Effect.logError('Development client stopped.', cause)), Effect.forkScoped);
|
|
61
66
|
}
|
|
62
|
-
yield*
|
|
67
|
+
yield* activateBrowser.pipe(Effect.catchTags({
|
|
63
68
|
FlightLoadError: ()=>renderBrowserFailure,
|
|
64
|
-
ReactDOMHydrationError: ()=>renderBrowserFailure
|
|
65
|
-
NavigationApiUnavailableError: ()=>skipHydration('the Navigation API'),
|
|
66
|
-
NavigationPrecommitUnavailableError: ()=>skipHydration('NavigationPrecommitController')
|
|
69
|
+
ReactDOMHydrationError: ()=>renderBrowserFailure
|
|
67
70
|
}));
|
|
68
71
|
return yield* Effect.never;
|
|
69
72
|
})).pipe(Effect.provide(BrowserLayer));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client/application.js","sources":["../../src/client/application.ts"],"sourcesContent":["// oxlint-disable effecttsgo/process-env, effecttsgo/process-env-in-effect -- Rspack replaces NODE_ENV at compile time.\nimport * as BrowserHttpClient from '@effect/platform-browser/BrowserHttpClient';\nimport { Effect, Layer } from 'effect';\n\nimport {
|
|
1
|
+
{"version":3,"file":"client/application.js","sources":["../../src/client/application.ts"],"sourcesContent":["// oxlint-disable effecttsgo/process-env, effecttsgo/process-env-in-effect -- Rspack replaces NODE_ENV at compile time.\nimport * as BrowserHttpClient from '@effect/platform-browser/BrowserHttpClient';\nimport { Effect, Layer } from 'effect';\n\nimport { navigationMode } from './browser-capabilities';\nimport { BrowserEffectRunner } from './browser-effect-runner';\nimport { BrowserRenderStatus } from './browser-render-status';\nimport { BrowserRenderer } from './browser-renderer';\nimport { showBrowserFailure } from './browser-screen';\nimport { installCallServer } from './call-server';\nimport { installClientRouter } from './client-router';\nimport { FlightClient } from './flight-client';\nimport { InitialFlightStream } from './initial-flight-stream';\nimport { NavigationApi } from './navigation-api';\nimport { ReactDOMRenderer } from './react-dom-renderer';\nimport { RouteLoader } from './route-loader';\nimport { installRouteRefresh, RouteRefresher } from './route-refresh';\n\nconst BrowserServicesLayer = Layer.mergeAll(\n BrowserEffectRunner.layer,\n BrowserRenderer.layer,\n BrowserRenderStatus.layer,\n FlightClient.layer,\n NavigationApi.layer,\n).pipe(Layer.provide(InitialFlightStream.layer));\n\nconst BrowserLayer = Layer.mergeAll(\n ReactDOMRenderer.layer,\n RouteLoader.layer,\n RouteRefresher.layer,\n).pipe(Layer.provideMerge(BrowserServicesLayer), Layer.provide(BrowserHttpClient.layerFetch));\n\nconst renderBrowserFailure = Effect.sync(showBrowserFailure);\n\nconst activateBrowser = Effect.gen(function* () {\n const routeLoader = yield* RouteLoader;\n const reactDOMRenderer = yield* ReactDOMRenderer;\n\n const initialPayload = yield* routeLoader.loadInitial;\n yield* reactDOMRenderer.hydrate(document, initialPayload);\n yield* installRouteRefresh;\n yield* installCallServer;\n const mode = yield* navigationMode;\n if (mode === 'Client') {\n yield* installClientRouter;\n }\n});\n\nexport const browserMain = Effect.scoped(\n Effect.gen(function* () {\n if (process.env.NODE_ENV === 'development') {\n yield* Effect.tryPromise(() => import('../dev/client')).pipe(\n Effect.flatMap(({ startDevClient }) => startDevClient),\n Effect.catch((cause) => Effect.logError('Development client stopped.', cause)),\n Effect.forkScoped,\n );\n }\n\n yield* activateBrowser.pipe(\n Effect.catchTags({\n FlightLoadError: () => renderBrowserFailure,\n ReactDOMHydrationError: () => renderBrowserFailure,\n }),\n );\n return yield* Effect.never;\n }),\n).pipe(Effect.provide(BrowserLayer));\n"],"names":["BrowserHttpClient","Effect","Layer","navigationMode","BrowserEffectRunner","BrowserRenderStatus","BrowserRenderer","showBrowserFailure","installCallServer","installClientRouter","FlightClient","InitialFlightStream","NavigationApi","ReactDOMRenderer","RouteLoader","installRouteRefresh","RouteRefresher","BrowserServicesLayer","BrowserLayer","renderBrowserFailure","activateBrowser","routeLoader","reactDOMRenderer","initialPayload","document","mode","browserMain","process","startDevClient","cause"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uHAAuH;AACvC;AACzC;AAEiB;AACM;AACA;AACT;AACC;AACJ;AACI;AACP;AACe;AACb;AACO;AACX;AACyB;AAEtE,MAAMiB,oBAAoBA,GAAGf,cAAc,CACzCE,yBAAyB,EACzBE,qBAAqB,EACrBD,yBAAyB,EACzBK,kBAAkB,EAClBE,mBAAmB,EACnB,IAAI,CAACV,aAAa,CAACS,yBAAyB;AAE9C,MAAMO,YAAYA,GAAGhB,cAAc,CACjCW,sBAAsB,EACtBC,iBAAiB,EACjBE,oBAAoB,EACpB,IAAI,CAACd,kBAAkB,CAACe,oBAAoBA,GAAGf,aAAa,CAACF,gFAA4B;AAE3F,MAAMmB,oBAAoBA,GAAGlB,WAAW,CAACM,kBAAkBA;AAE3D,MAAMa,eAAeA,GAAGnB,UAAU,CAAC;IACjC,MAAMoB,cAAc,OAAOP,WAAWA;IACtC,MAAMQ,mBAAmB,OAAOT,gBAAgBA;IAEhD,MAAMU,iBAAiB,OAAOF,YAAY,WAAW;IACrD,OAAOC,iBAAiB,OAAO,CAACE,UAAUD;IAC1C,OAAOR,mBAAmBA;IAC1B,OAAOP,iBAAiBA;IACxB,MAAMiB,OAAO,OAAOtB,cAAcA;IAClC,IAAIsB,SAAS,UAAU;QACrB,OAAOhB,mBAAmBA;IAC5B;AACF;AAEO,MAAMiB,WAAWA,GAAGzB,aAAa,CACtCA,UAAU,CAAC;IACT,IAAI0B,QAAQ,GAAG,CAAC,QAAQ,KAAK,eAAe;QAC1C,OAAO1B,iBAAiB,CAAC,IAAM,0BAAuB,EAAE,IAAI,CAC1DA,cAAc,CAAC,CAAC,EAAE2B,cAAc,EAAE,GAAKA,iBACvC3B,eAAY,CAAC,CAAC4B,QAAU5B,eAAe,CAAC,+BAA+B4B,SACvE5B,iBAAiB;IAErB;IAEA,OAAOmB,eAAeA,CAAC,IAAI,CACzBnB,gBAAgB,CAAC;QACf,iBAAiB,IAAMkB,oBAAoBA;QAC3C,wBAAwB,IAAMA,oBAAoBA;IACpD;IAEF,OAAO,OAAOlB,YAAY;AAC5B,IACA,IAAI,CAACA,cAAc,CAACiB,YAAYA,GAAG"}
|
|
@@ -1,9 +1,2 @@
|
|
|
1
|
-
import { Effect
|
|
2
|
-
declare const
|
|
3
|
-
export declare class NavigationApiUnavailableError extends NavigationApiUnavailableError_base {
|
|
4
|
-
}
|
|
5
|
-
declare const NavigationPrecommitUnavailableError_base: Schema.Class<NavigationPrecommitUnavailableError, Schema.TaggedStruct<"NavigationPrecommitUnavailableError", {}>, import("effect/Cause").YieldableError>;
|
|
6
|
-
export declare class NavigationPrecommitUnavailableError extends NavigationPrecommitUnavailableError_base {
|
|
7
|
-
}
|
|
8
|
-
export declare const checkBrowserCapabilities: Effect.Effect<undefined, NavigationApiUnavailableError | NavigationPrecommitUnavailableError, never>;
|
|
9
|
-
export {};
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
export declare const navigationMode: Effect.Effect<"Client" | "Document", never, never>;
|
|
@@ -1,20 +1,9 @@
|
|
|
1
|
-
import { Effect
|
|
1
|
+
import { Effect } from "effect";
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
}
|
|
7
|
-
class NavigationPrecommitUnavailableError extends Schema.TaggedError()('NavigationPrecommitUnavailableError', {}) {
|
|
8
|
-
}
|
|
9
|
-
const checkBrowserCapabilities = Effect.gen(function*() {
|
|
10
|
-
if (window.navigation === undefined) {
|
|
11
|
-
return yield* new NavigationApiUnavailableError();
|
|
12
|
-
}
|
|
13
|
-
if (window.NavigationPrecommitController === undefined) {
|
|
14
|
-
return yield* new NavigationPrecommitUnavailableError();
|
|
15
|
-
}
|
|
16
|
-
});
|
|
5
|
+
const navigationMode = Effect.sync(()=>window.navigation !== undefined && window.NavigationPrecommitController !== undefined ? 'Client' : 'Document');
|
|
17
6
|
|
|
18
|
-
export {
|
|
7
|
+
export { navigationMode };
|
|
19
8
|
|
|
20
9
|
//# sourceMappingURL=browser-capabilities.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client/browser-capabilities.js","sources":["../../src/client/browser-capabilities.ts"],"sourcesContent":["import { Effect
|
|
1
|
+
{"version":3,"file":"client/browser-capabilities.js","sources":["../../src/client/browser-capabilities.ts"],"sourcesContent":["import { Effect } from 'effect';\n\nexport const navigationMode = Effect.sync(() =>\n window.navigation !== undefined && window.NavigationPrecommitController !== undefined\n ? ('Client' as const)\n : ('Document' as const),\n);\n"],"names":["Effect","navigationMode","window","undefined"],"mappings":";;;AAAgC;AAEzB,MAAMC,cAAcA,GAAGD,WAAW,CAAC,IACxCE,OAAO,UAAU,KAAKC,aAAaD,OAAO,6BAA6B,KAAKC,YACvE,WACA,YACL"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Context, Effect, Layer } from 'effect';
|
|
2
|
+
type RenderStatus = {
|
|
3
|
+
readonly _tag: 'Waiting';
|
|
4
|
+
} | {
|
|
5
|
+
readonly _tag: 'Rendered';
|
|
6
|
+
} | {
|
|
7
|
+
readonly _tag: 'Failed';
|
|
8
|
+
readonly error: unknown;
|
|
9
|
+
readonly componentStack: string | null;
|
|
10
|
+
};
|
|
11
|
+
declare const BrowserRenderStatus_base: Context.ServiceClass<BrowserRenderStatus, "ersc/client/BrowserRenderStatus", {
|
|
12
|
+
changes: import("effect/Stream").Stream<RenderStatus, never, never>;
|
|
13
|
+
get: Effect.Effect<RenderStatus, never, never>;
|
|
14
|
+
report: (value: RenderStatus) => Effect.Effect<void, never, never>;
|
|
15
|
+
}> & {
|
|
16
|
+
readonly make: Effect.Effect<{
|
|
17
|
+
changes: import("effect/Stream").Stream<RenderStatus, never, never>;
|
|
18
|
+
get: Effect.Effect<RenderStatus, never, never>;
|
|
19
|
+
report: (value: RenderStatus) => Effect.Effect<void, never, never>;
|
|
20
|
+
}, never, never>;
|
|
21
|
+
};
|
|
22
|
+
export declare class BrowserRenderStatus extends BrowserRenderStatus_base {
|
|
23
|
+
static readonly layer: Layer.Layer<BrowserRenderStatus, never, never>;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Context, Effect, Layer, SubscriptionRef } from "effect";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
// Replay the latest status: diagnostics may start after hydration has already failed.
|
|
6
|
+
class BrowserRenderStatus extends Context.Service()('ersc/client/BrowserRenderStatus', {
|
|
7
|
+
make: SubscriptionRef.make({
|
|
8
|
+
_tag: 'Waiting'
|
|
9
|
+
}).pipe(Effect.map((status)=>({
|
|
10
|
+
changes: SubscriptionRef.changes(status),
|
|
11
|
+
get: SubscriptionRef.get(status),
|
|
12
|
+
report: (value)=>SubscriptionRef.set(status, value)
|
|
13
|
+
})))
|
|
14
|
+
}) {
|
|
15
|
+
static layer = Layer.effect(this, this.make);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { BrowserRenderStatus };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=browser-render-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client/browser-render-status.js","sources":["../../src/client/browser-render-status.ts"],"sourcesContent":["import { Context, Effect, Layer, SubscriptionRef } from 'effect';\n\ntype RenderStatus =\n | { readonly _tag: 'Waiting' }\n | { readonly _tag: 'Rendered' }\n | { readonly _tag: 'Failed'; readonly error: unknown; readonly componentStack: string | null };\n\n// Replay the latest status: diagnostics may start after hydration has already failed.\nexport class BrowserRenderStatus extends Context.Service<BrowserRenderStatus>()(\n 'ersc/client/BrowserRenderStatus',\n {\n make: SubscriptionRef.make<RenderStatus>({ _tag: 'Waiting' }).pipe(\n Effect.map((status) => ({\n changes: SubscriptionRef.changes(status),\n get: SubscriptionRef.get(status),\n report: (value: RenderStatus) => SubscriptionRef.set(status, value),\n })),\n ),\n },\n) {\n static readonly layer = Layer.effect(this, this.make);\n}\n"],"names":["Context","Effect","Layer","SubscriptionRef","BrowserRenderStatus","status","value"],"mappings":";;;AAAiE;AAOjE,sFAAsF;AAC/E,MAAMI,mBAAmBA,SAASJ,eAAe,GACtD,mCACA;IACE,MAAMG,oBAAoB,CAAe;QAAE,MAAM;IAAU,GAAG,IAAI,CAChEF,UAAU,CAAC,CAACI,SAAY;YACtB,SAASF,uBAAuB,CAACE;YACjC,KAAKF,mBAAmB,CAACE;YACzB,QAAQ,CAACC,QAAwBH,mBAAmB,CAACE,QAAQC;QAC/D;AAEJ;IAEA,OAAgB,QAAQJ,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;AACxD"}
|
|
@@ -113,12 +113,17 @@ const installCallServer = Effect.gen(function*() {
|
|
|
113
113
|
// React registered its Action reactions before the request completed. Registering ERSC's
|
|
114
114
|
// continuation after settlement lets React close that Action before the refresh Transition.
|
|
115
115
|
yield* Effect.promise(()=>invocationResult.promise.then(()=>undefined, ()=>undefined));
|
|
116
|
-
|
|
116
|
+
let refreshSource = selectRefreshSource(invocation);
|
|
117
|
+
if (refreshSource === 'Response') {
|
|
118
|
+
yield* routeRefresher.interruptCurrentRouteRefresh;
|
|
119
|
+
// Interruption awaits cleanup, during which navigation or another invocation can win.
|
|
120
|
+
refreshSource = selectRefreshSource(invocation);
|
|
121
|
+
}
|
|
122
|
+
if (refreshSource === 'CurrentRoute') {
|
|
117
123
|
yield* resource.release;
|
|
118
124
|
yield* routeRefresher.refreshCurrentRoute('server-function');
|
|
119
125
|
return;
|
|
120
126
|
}
|
|
121
|
-
yield* routeRefresher.interruptCurrentRouteRefresh;
|
|
122
127
|
const commitRefresh = routeLoader.prepareRefresh(resource.payload.routeTree);
|
|
123
128
|
let renderCommitted;
|
|
124
129
|
yield* Effect.sync(()=>{
|
|
@@ -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 if (selectRefreshSource(invocation) === 'CurrentRoute') {\n yield* resource.release;\n yield* routeRefresher.refreshCurrentRoute('server-function');\n return;\n }\n
|
|
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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"}
|
|
@@ -4,15 +4,16 @@ import { Context, Effect, Layer } from "effect";
|
|
|
4
4
|
|
|
5
5
|
class NavigationApi extends Context.Service()('ersc/client/NavigationApi', {
|
|
6
6
|
make: Effect.succeed({
|
|
7
|
-
getCurrentEntry: ()=>window.navigation
|
|
7
|
+
getCurrentEntry: ()=>window.navigation?.currentEntry ?? null,
|
|
8
8
|
getCurrentUrl: ()=>window.location.href,
|
|
9
|
-
getTransition: ()=>window.navigation
|
|
9
|
+
getTransition: ()=>window.navigation?.transition ?? null,
|
|
10
10
|
navigate: (url, options)=>window.navigation.navigate(url, options),
|
|
11
11
|
reloadDocument: ()=>window.location.reload(),
|
|
12
12
|
replaceDocument: (url)=>window.location.replace(url),
|
|
13
13
|
subscribe: (listener)=>{
|
|
14
|
-
window.navigation
|
|
15
|
-
|
|
14
|
+
const navigation = window.navigation;
|
|
15
|
+
navigation?.addEventListener('navigate', listener);
|
|
16
|
+
return ()=>navigation?.removeEventListener('navigate', listener);
|
|
16
17
|
}
|
|
17
18
|
})
|
|
18
19
|
}) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client/navigation-api.js","sources":["../../src/client/navigation-api.ts"],"sourcesContent":["import { Context, Effect, Layer } from 'effect';\n\ntype NavigateListener = (event: NavigateEvent) => void;\n\nexport class NavigationApi extends Context.Service<NavigationApi>()('ersc/client/NavigationApi', {\n make: Effect.succeed({\n getCurrentEntry: () => window.navigation
|
|
1
|
+
{"version":3,"file":"client/navigation-api.js","sources":["../../src/client/navigation-api.ts"],"sourcesContent":["import { Context, Effect, Layer } from 'effect';\n\ntype NavigateListener = (event: NavigateEvent) => void;\n\nexport class NavigationApi extends Context.Service<NavigationApi>()('ersc/client/NavigationApi', {\n make: Effect.succeed({\n getCurrentEntry: () => window.navigation?.currentEntry ?? null,\n getCurrentUrl: () => window.location.href,\n getTransition: () => window.navigation?.transition ?? null,\n navigate: (url: string | URL, options?: NavigationNavigateOptions) =>\n window.navigation.navigate(url, options),\n reloadDocument: () => window.location.reload(),\n replaceDocument: (url: string) => window.location.replace(url),\n subscribe: (listener: NavigateListener) => {\n const navigation = window.navigation;\n navigation?.addEventListener('navigate', listener);\n return () => navigation?.removeEventListener('navigate', listener);\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","NavigationApi","window","url","options","listener","navigation"],"mappings":";;;AAAgD;AAIzC,MAAMG,aAAaA,SAASH,eAAe,GAAkB,6BAA6B;IAC/F,MAAMC,cAAc,CAAC;QACnB,iBAAiB,IAAMG,OAAO,UAAU,EAAE,gBAAgB;QAC1D,eAAe,IAAMA,OAAO,QAAQ,CAAC,IAAI;QACzC,eAAe,IAAMA,OAAO,UAAU,EAAE,cAAc;QACtD,UAAU,CAACC,KAAmBC,UAC5BF,OAAO,UAAU,CAAC,QAAQ,CAACC,KAAKC;QAClC,gBAAgB,IAAMF,OAAO,QAAQ,CAAC,MAAM;QAC5C,iBAAiB,CAACC,MAAgBD,OAAO,QAAQ,CAAC,OAAO,CAACC;QAC1D,WAAW,CAACE;YACV,MAAMC,aAAaJ,OAAO,UAAU;YACpCI,YAAY,iBAAiB,YAAYD;YACzC,OAAO,IAAMC,YAAY,oBAAoB,YAAYD;QAC3D;IACF;AACF;IACE,OAAgB,QAAQL,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;IAEtD,OAAgB,YAAYA,UAAU,CAAC,IAAI,EAAE;AAC/C"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Context, Effect, Layer, Schema } from 'effect';
|
|
2
2
|
import type { FlightPayload } from '../rsc/flight.js';
|
|
3
3
|
import { BrowserEffectRunner } from './browser-effect-runner.js';
|
|
4
|
+
import { BrowserRenderStatus } from './browser-render-status.js';
|
|
4
5
|
import { BrowserRenderer } from './browser-renderer.js';
|
|
5
6
|
declare const ReactDOMHydrationError_base: Schema.Class<ReactDOMHydrationError, Schema.TaggedStruct<"ReactDOMHydrationError", {
|
|
6
7
|
readonly cause: Schema.Defect;
|
|
@@ -12,9 +13,9 @@ declare const ReactDOMRenderer_base: Context.ServiceClass<ReactDOMRenderer, "ers
|
|
|
12
13
|
}> & {
|
|
13
14
|
readonly make: Effect.Effect<{
|
|
14
15
|
hydrate: (container: Document | Element, initialPayload: FlightPayload) => Effect.Effect<void, ReactDOMHydrationError, import("effect/Scope").Scope>;
|
|
15
|
-
}, never, BrowserEffectRunner | BrowserRenderer>;
|
|
16
|
+
}, never, BrowserEffectRunner | BrowserRenderStatus | BrowserRenderer>;
|
|
16
17
|
};
|
|
17
18
|
export declare class ReactDOMRenderer extends ReactDOMRenderer_base {
|
|
18
|
-
static readonly layer: Layer.Layer<ReactDOMRenderer, never, BrowserEffectRunner | BrowserRenderer>;
|
|
19
|
+
static readonly layer: Layer.Layer<ReactDOMRenderer, never, BrowserEffectRunner | BrowserRenderStatus | BrowserRenderer>;
|
|
19
20
|
}
|
|
20
21
|
export {};
|
|
@@ -3,6 +3,7 @@ import { Context, Effect, Layer, Schema } from "effect";
|
|
|
3
3
|
import { Component, StrictMode, useLayoutEffect, useState } from "react";
|
|
4
4
|
import { hydrateRoot } from "react-dom/client";
|
|
5
5
|
import { BrowserEffectRunner } from "./browser-effect-runner.js";
|
|
6
|
+
import { BrowserRenderStatus } from "./browser-render-status.js";
|
|
6
7
|
import { BrowserRenderer } from "./browser-renderer.js";
|
|
7
8
|
import { BrowserFailureScreen } from "./browser-screen.js";
|
|
8
9
|
import { RouteTree } from "./route-tree.js";
|
|
@@ -23,22 +24,47 @@ import { RouteTree } from "./route-tree.js";
|
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
|
|
27
|
+
|
|
28
|
+
|
|
26
29
|
class ReactDOMHydrationError extends Schema.TaggedError()('ReactDOMHydrationError', {
|
|
27
30
|
cause: Schema.Defect()
|
|
28
31
|
}) {
|
|
29
32
|
}
|
|
30
33
|
class BrowserErrorBoundary extends Component {
|
|
31
34
|
state = {
|
|
32
|
-
_tag: '
|
|
35
|
+
_tag: 'Uninitialized'
|
|
33
36
|
};
|
|
34
37
|
static getDerivedStateFromError() {
|
|
35
38
|
return {
|
|
36
39
|
_tag: 'Failed'
|
|
37
40
|
};
|
|
38
41
|
}
|
|
42
|
+
static getDerivedStateFromProps(props, state) {
|
|
43
|
+
if (state._tag !== 'Uninitialized' && props.render === state.render) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
// Discard acknowledges a cancelled candidate, not a request to retry the failed tree.
|
|
47
|
+
return state._tag === 'Failed' && props.render._tag === 'Discard' ? {
|
|
48
|
+
_tag: 'Failed',
|
|
49
|
+
render: props.render
|
|
50
|
+
} : {
|
|
51
|
+
_tag: 'Ready',
|
|
52
|
+
render: props.render
|
|
53
|
+
};
|
|
54
|
+
}
|
|
39
55
|
componentDidCatch(error, info) {
|
|
40
56
|
this.props.onError(error, info);
|
|
41
57
|
}
|
|
58
|
+
componentDidMount() {
|
|
59
|
+
if (this.state._tag === 'Ready') {
|
|
60
|
+
this.props.onRendered();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
componentDidUpdate() {
|
|
64
|
+
if (this.state._tag === 'Ready') {
|
|
65
|
+
this.props.onRendered();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
42
68
|
render() {
|
|
43
69
|
if (this.state._tag === 'Failed') {
|
|
44
70
|
return /*#__PURE__*/ jsx(BrowserFailureScreen, {});
|
|
@@ -50,10 +76,23 @@ class ReactDOMRenderer extends Context.Service()('ersc/client/ReactDOMRenderer',
|
|
|
50
76
|
make: Effect.gen(function*() {
|
|
51
77
|
const browserRenderer = yield* BrowserRenderer;
|
|
52
78
|
const run = yield* BrowserEffectRunner;
|
|
79
|
+
const renderStatus = yield* BrowserRenderStatus;
|
|
53
80
|
const hydrate = Effect.fnUntraced(function*(container, initialPayload) {
|
|
54
81
|
const browserRendererReady = Promise.withResolvers();
|
|
55
82
|
const reportError = (error, info)=>{
|
|
56
|
-
void run(Effect.
|
|
83
|
+
void run(Effect.gen(function*() {
|
|
84
|
+
yield* renderStatus.report({
|
|
85
|
+
_tag: 'Failed',
|
|
86
|
+
error,
|
|
87
|
+
componentStack: info.componentStack ?? null
|
|
88
|
+
});
|
|
89
|
+
yield* Effect.logError('Uncaught client render error.', error, info.componentStack);
|
|
90
|
+
}));
|
|
91
|
+
};
|
|
92
|
+
const reportRendered = ()=>{
|
|
93
|
+
void run(renderStatus.report({
|
|
94
|
+
_tag: 'Rendered'
|
|
95
|
+
}));
|
|
57
96
|
};
|
|
58
97
|
function Root() {
|
|
59
98
|
const [render, setRender] = useState(()=>({
|
|
@@ -71,6 +110,8 @@ class ReactDOMRenderer extends Context.Service()('ersc/client/ReactDOMRenderer',
|
|
|
71
110
|
]);
|
|
72
111
|
return /*#__PURE__*/ jsx(BrowserErrorBoundary, {
|
|
73
112
|
onError: reportError,
|
|
113
|
+
onRendered: reportRendered,
|
|
114
|
+
render: render,
|
|
74
115
|
children: /*#__PURE__*/ jsx(RouteTree, {
|
|
75
116
|
root: render.routeTree
|
|
76
117
|
})
|
|
@@ -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 { 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
|
|
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":";;;;;;;;;;;;;;;;;;;;AAAwD;AAQzC;AACgC;AAGe;AACA;AACW;AACjB;AACf;AAElC,MAAMc,sBAAsBA,SAASX,kBAAkB,GAC5D,0BACA;IAAE,OAAOA,aAAa;AAAG;AACxB;AAaH,MAAMY,oBAAoBA,SAASX,SAASA;IACxB,QAAmC;QAAE,MAAM;IAAgB,EAAE;IAE/E,OAAO,2BAA2B;QAChC,OAAO;YAAE,MAAM;QAAS;IAC1B;IAEA,OAAO,yBACLY,KAAgC,EAChCC,KAAgC,EACE;QAClC,IAAIA,MAAM,IAAI,KAAK,mBAAmBD,MAAM,MAAM,KAAKC,MAAM,MAAM,EAAE;YACnE,OAAO;QACT;QACA,sFAAsF;QACtF,OAAOA,MAAM,IAAI,KAAK,YAAYD,MAAM,MAAM,CAAC,IAAI,KAAK,YACpD;YAAE,MAAM;YAAU,QAAQA,MAAM,MAAM;QAAC,IACvC;YAAE,MAAM;YAAS,QAAQA,MAAM,MAAM;QAAC;IAC5C;IAES,kBAAkBE,KAAc,EAAEC,IAAe,EAAE;QAC1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAACD,OAAOC;IAC5B;IAES,oBAAoB;QAC3B,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS;YAC/B,IAAI,CAAC,KAAK,CAAC,UAAU;QACvB;IACF;IAES,qBAAqB;QAC5B,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS;YAC/B,IAAI,CAAC,KAAK,CAAC,UAAU;QACvB;IACF;IAES,SAAS;QAChB,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,UAAU;YAChC,qBAAO,IAACP,oBAAoBA;QAC9B;QAEA,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ;IAC5B;AACF;AAEO,MAAMQ,gBAAgBA,SAASpB,eAAe,GACnD,gCACA;IACE,MAAMC,UAAU,CAAC;QACf,MAAMoB,kBAAkB,OAAOV,eAAeA;QAC9C,MAAMW,MAAM,OAAOb,mBAAmBA;QACtC,MAAMc,eAAe,OAAOb,mBAAmBA;QAE/C,MAAMc,UAAUvB,iBAAiB,CAAC,UAChCwB,SAA6B,EAC7BC,cAA6B;YAE7B,MAAMC,uBAAuBC,QAAQ,aAAa;YAClD,MAAMC,cAAc,CAACX,OAAgBC;gBACnC,KAAKG,IACHrB,UAAU,CAAC;oBACT,OAAOsB,aAAa,MAAM,CAAC;wBACzB,MAAM;wBACNL;wBACA,gBAAgBC,KAAK,cAAc,IAAI;oBACzC;oBACA,OAAOlB,eAAe,CAAC,iCAAiCiB,OAAOC,KAAK,cAAc;gBACpF;YAEJ;YAEA,MAAMW,iBAAiB;gBACrB,KAAKR,IAAIC,aAAa,MAAM,CAAC;oBAAE,MAAM;gBAAW;YAClD;YAEA,SAASQ;gBACP,MAAM,CAACC,QAAQC,UAAU,GAAG1B,QAAQA,CAAgB,IAAO;wBACzD,MAAM;wBACN,WAAWmB,eAAe,SAAS;oBACrC;gBAEApB,eAAeA,CAAC;oBACde,gBAAgB,UAAU,CAACK,eAAe,SAAS,EAAEO;oBACrDN,qBAAqB,OAAO;gBAC9B,GAAG,EAAE;gBAELrB,eAAeA,CAAC;oBACde,gBAAgB,MAAM,CAACW;gBACzB,GAAG;oBAACA;iBAAO;gBAEX,qBACE,IAACjB,oBAAoBA;oBAAC,SAASc;oBAAa,YAAYC;oBAAgB,QAAQE;8BAC9E,kBAACnB,SAASA;wBAAC,MAAMmB,OAAO,SAAS;;;YAGvC;YAEA,OAAO/B,qBAAqB,CAC1BA,aAAU,CAAC;gBACT,KAAK,IACHO,WAAWA,CACTiB,yBACA,IAACpB,UAAUA;kCACT,kBAAC0B;wBAEH;wBAAE,WAAWL,eAAe,SAAS;oBAAC;gBAE1C,OAAO,CAACQ,QAAU,IAAIpB,sBAAsBA,CAAC;wBAAEoB;oBAAM;YACvD,IACA,CAACC,OAASlC,WAAW,CAAC,IAAMkC,KAAK,OAAO;YAE1C,OAAOlC,cAAc,CAAC,IAAM0B,qBAAqB,OAAO;QAC1D;QAEA,OAAO;YAAEH;QAAQ;IACnB;AACF;IAEA,OAAgB,QAAQtB,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;AACxD"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Context, Effect, Layer } from 'effect';
|
|
2
|
-
import { BrowserEffectRunner } from './browser-effect-runner.js';
|
|
3
2
|
import { BrowserRenderer } from './browser-renderer.js';
|
|
4
3
|
import { NavigationApi } from './navigation-api.js';
|
|
5
4
|
import { RouteLoader } from './route-loader.js';
|
|
@@ -27,5 +26,5 @@ export declare class RouteRefresher extends RouteRefresher_base {
|
|
|
27
26
|
replace?: (replacement: RouteRefreshImplementation) => Effect.Effect<void, never, never>;
|
|
28
27
|
}) => Layer.Layer<RouteRefresher, never, never>;
|
|
29
28
|
}
|
|
30
|
-
export declare const installRouteRefresh: Effect.Effect<void, never,
|
|
29
|
+
export declare const installRouteRefresh: Effect.Effect<void, never, BrowserRenderer | NavigationApi | RouteLoader | RouteRefresher | import("effect/Scope").Scope>;
|
|
31
30
|
export {};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Context, Effect, FiberMap, Layer, Ref
|
|
1
|
+
import { Context, Effect, FiberMap, Layer, Ref } from "effect";
|
|
2
2
|
import { addTransitionType, startTransition } from "react";
|
|
3
|
-
import { BrowserEffectRunner } from "./browser-effect-runner.js";
|
|
4
3
|
import { BrowserRenderer } from "./browser-renderer.js";
|
|
5
4
|
import { NavigationApi } from "./navigation-api.js";
|
|
6
5
|
import { isRoutedNavigation, preserveRequestedHash } from "./navigation-routing.js";
|
|
@@ -18,13 +17,7 @@ import { RouteLoader } from "./route-loader.js";
|
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
|
|
21
|
-
|
|
22
|
-
|
|
23
20
|
const CurrentRouteRefreshKey = 'CurrentRouteRefresh';
|
|
24
|
-
class RouteRefreshError extends Schema.TaggedError()('RouteRefreshError', {
|
|
25
|
-
cause: Schema.Defect()
|
|
26
|
-
}) {
|
|
27
|
-
}
|
|
28
21
|
class RouteRefresher extends Context.Service()('ersc/client/RouteRefresher', {
|
|
29
22
|
make: Effect.gen(function*() {
|
|
30
23
|
const navigationApi = yield* NavigationApi;
|
|
@@ -55,7 +48,6 @@ const installRouteRefresh = Effect.gen(function*() {
|
|
|
55
48
|
const navigationApi = yield* NavigationApi;
|
|
56
49
|
const routeLoader = yield* RouteLoader;
|
|
57
50
|
const routeRefresher = yield* RouteRefresher;
|
|
58
|
-
const run = yield* BrowserEffectRunner;
|
|
59
51
|
const refreshes = yield* FiberMap.make();
|
|
60
52
|
const waitForNavigationIdle = Effect.suspend(()=>{
|
|
61
53
|
const transition = navigationApi.getTransition();
|
|
@@ -109,18 +101,13 @@ const installRouteRefresh = Effect.gen(function*() {
|
|
|
109
101
|
discard: true
|
|
110
102
|
}).pipe(Effect.andThen(Effect.sync(commitRefresh)), Effect.ensuring(resource.release));
|
|
111
103
|
});
|
|
112
|
-
const refreshInReactTransition = (transitionType)=>Effect.callback((resume, signal)=>{
|
|
113
|
-
startTransition(()=>run(refreshRoute(transitionType), {
|
|
114
|
-
signal
|
|
115
|
-
}).then(()=>resume(Effect["void"]), (cause)=>resume(Effect.fail(new RouteRefreshError({
|
|
116
|
-
cause
|
|
117
|
-
})))));
|
|
118
|
-
});
|
|
119
104
|
const refreshCurrentRoute = Effect.fnUntraced(function*(transitionType) {
|
|
120
105
|
routeLoader.invalidate();
|
|
121
106
|
yield* waitForNavigationIdle;
|
|
122
|
-
|
|
123
|
-
|
|
107
|
+
// Only publication belongs to a React Transition. An async Action waiting for this
|
|
108
|
+
// effect would prevent the very UI commit that completes the refresh.
|
|
109
|
+
yield* Effect.raceFirst(refreshRoute(transitionType), waitForRoutedNavigation);
|
|
110
|
+
}, Effect.scoped, Effect["catch"]((cause)=>Effect.logError('Failed to refresh the current route.', cause)));
|
|
124
111
|
yield* routeRefresher.replace({
|
|
125
112
|
interruptCurrentRouteRefresh: FiberMap.remove(refreshes, CurrentRouteRefreshKey),
|
|
126
113
|
refreshCurrentRoute: (transitionType)=>FiberMap.run(refreshes, CurrentRouteRefreshKey, refreshCurrentRoute(transitionType)).pipe(Effect.asVoid)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client/route-refresh.js","sources":["../../src/client/route-refresh.ts"],"sourcesContent":["import { Context, Effect, FiberMap, Layer, Ref
|
|
1
|
+
{"version":3,"file":"client/route-refresh.js","sources":["../../src/client/route-refresh.ts"],"sourcesContent":["import { Context, Effect, FiberMap, Layer, Ref } from 'effect';\nimport { addTransitionType, startTransition } from 'react';\n\nimport { BrowserRenderer } from './browser-renderer';\nimport { NavigationApi } from './navigation-api';\nimport { isRoutedNavigation, preserveRequestedHash } from './navigation-routing';\nimport { RouteLoader } from './route-loader';\n\nconst CurrentRouteRefreshKey = 'CurrentRouteRefresh';\n\nexport type RouteRefreshTransitionType = 'hmr-refresh' | 'server-function';\n\ntype RouteRefreshImplementation = {\n readonly interruptCurrentRouteRefresh: Effect.Effect<void>;\n readonly refreshCurrentRoute: (transitionType: RouteRefreshTransitionType) => Effect.Effect<void>;\n};\n\nexport class RouteRefresher extends Context.Service<RouteRefresher>()(\n 'ersc/client/RouteRefresher',\n {\n make: Effect.gen(function* () {\n const navigationApi = yield* NavigationApi;\n const implementation = yield* Ref.make<RouteRefreshImplementation>({\n interruptCurrentRouteRefresh: Effect.void,\n refreshCurrentRoute: () => Effect.sync(navigationApi.reloadDocument),\n });\n\n const interruptCurrentRouteRefresh = Effect.gen(function* () {\n const current = yield* Ref.get(implementation);\n yield* current.interruptCurrentRouteRefresh;\n });\n\n const refreshCurrentRoute = Effect.fn('RouteRefresher.refreshCurrentRoute')(function* (\n transitionType: RouteRefreshTransitionType,\n ) {\n const current = yield* Ref.get(implementation);\n yield* current.refreshCurrentRoute(transitionType);\n });\n\n return {\n interruptCurrentRouteRefresh,\n refreshCurrentRoute,\n replace: (replacement: RouteRefreshImplementation) => Ref.set(implementation, replacement),\n };\n }),\n },\n) {\n static readonly layer = Layer.effect(this, this.make);\n\n static readonly layerTest = Layer.mock(this);\n}\n\nexport const installRouteRefresh = Effect.gen(function* () {\n const browserRenderer = yield* BrowserRenderer;\n const navigationApi = yield* NavigationApi;\n const routeLoader = yield* RouteLoader;\n const routeRefresher = yield* RouteRefresher;\n const refreshes = yield* FiberMap.make<typeof CurrentRouteRefreshKey>();\n\n const waitForNavigationIdle = Effect.suspend(() => {\n const transition = navigationApi.getTransition();\n return transition === null\n ? Effect.succeed('Idle' as const)\n : Effect.promise(() =>\n transition.finished.then(\n () => undefined,\n () => undefined,\n ),\n ).pipe(Effect.as('Settled' as const));\n }).pipe(Effect.repeat({ while: (state) => state === 'Settled' }), Effect.asVoid);\n\n const waitForRoutedNavigation = Effect.callback<void>((resume) => {\n const onNavigate = (event: NavigateEvent) => {\n if (isRoutedNavigation(event)) {\n resume(Effect.void);\n }\n };\n const unsubscribe = navigationApi.subscribe(onNavigate);\n return Effect.sync(unsubscribe);\n });\n\n const refreshRoute = Effect.fnUntraced(function* (transitionType: RouteRefreshTransitionType) {\n const currentEntry = navigationApi.getCurrentEntry();\n const destination = new URL(currentEntry?.url ?? navigationApi.getCurrentUrl());\n const resource = yield* routeLoader.load({\n destination: {\n id: currentEntry?.id ?? '',\n url: destination.href,\n },\n navigationType: 'replace',\n });\n\n if (resource._tag === 'Document') {\n yield* resource.release;\n yield* Effect.sync(navigationApi.reloadDocument);\n return;\n }\n\n const resolvedDestination = preserveRequestedHash(destination, resource.resolvedUrl);\n if (resolvedDestination.href !== destination.href) {\n yield* resource.release;\n yield* Effect.sync(() => navigationApi.replaceDocument(resolvedDestination.href));\n return;\n }\n\n const commitRefresh = routeLoader.prepareRefresh(resource.routeTree);\n let renderCommitted!: Promise<void>;\n yield* Effect.sync(() => {\n startTransition(() => {\n addTransitionType(transitionType);\n renderCommitted = browserRenderer.refresh(resource.routeTree);\n });\n });\n yield* Effect.all([Effect.promise(() => renderCommitted), resource.completed], {\n concurrency: 'unbounded',\n discard: true,\n }).pipe(Effect.andThen(Effect.sync(commitRefresh)), Effect.ensuring(resource.release));\n });\n\n const refreshCurrentRoute = Effect.fnUntraced(\n function* (transitionType: RouteRefreshTransitionType) {\n routeLoader.invalidate();\n yield* waitForNavigationIdle;\n // Only publication belongs to a React Transition. An async Action waiting for this\n // effect would prevent the very UI commit that completes the refresh.\n yield* Effect.raceFirst(refreshRoute(transitionType), waitForRoutedNavigation);\n },\n Effect.scoped,\n Effect.catch((cause) => Effect.logError('Failed to refresh the current route.', cause)),\n );\n\n yield* routeRefresher.replace({\n interruptCurrentRouteRefresh: FiberMap.remove(refreshes, CurrentRouteRefreshKey),\n refreshCurrentRoute: (transitionType) =>\n FiberMap.run(refreshes, CurrentRouteRefreshKey, refreshCurrentRoute(transitionType)).pipe(\n Effect.asVoid,\n ),\n });\n});\n"],"names":["Context","Effect","FiberMap","Layer","Ref","addTransitionType","startTransition","BrowserRenderer","NavigationApi","isRoutedNavigation","preserveRequestedHash","RouteLoader","CurrentRouteRefreshKey","RouteRefresher","navigationApi","implementation","interruptCurrentRouteRefresh","current","refreshCurrentRoute","transitionType","replacement","installRouteRefresh","browserRenderer","routeLoader","routeRefresher","refreshes","waitForNavigationIdle","transition","undefined","state","waitForRoutedNavigation","resume","onNavigate","event","unsubscribe","refreshRoute","currentEntry","destination","URL","resource","resolvedDestination","commitRefresh","renderCommitted","cause"],"mappings":"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"}
|