effective-rsc 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/LLMS.md +85 -0
  2. package/README.md +14 -8
  3. package/dist/application/routes.d.ts +10 -10
  4. package/dist/application/routes.js.map +1 -1
  5. package/dist/build/build.d.ts +4 -2
  6. package/dist/build/build.js +19 -2
  7. package/dist/build/build.js.map +1 -1
  8. package/dist/build/deployment.d.ts +10 -0
  9. package/dist/build/deployment.js +59 -0
  10. package/dist/build/deployment.js.map +1 -0
  11. package/dist/build/dev.d.ts +4 -4
  12. package/dist/build/dev.js +22 -7
  13. package/dist/build/dev.js.map +1 -1
  14. package/dist/build/hook.d.ts +8 -0
  15. package/dist/build/hook.js +5 -0
  16. package/dist/build/hook.js.map +1 -0
  17. package/dist/build/rspack.js +1 -1
  18. package/dist/build/rspack.js.map +1 -1
  19. package/dist/cli.js +13 -24
  20. package/dist/cli.js.map +1 -1
  21. package/dist/client/browser-renderer.d.ts +25 -25
  22. package/dist/client/browser-renderer.js +80 -94
  23. package/dist/client/browser-renderer.js.map +1 -1
  24. package/dist/client/call-server.js +7 -5
  25. package/dist/client/call-server.js.map +1 -1
  26. package/dist/client/client-router.js +23 -7
  27. package/dist/client/client-router.js.map +1 -1
  28. package/dist/client/flight-client.js +3 -4
  29. package/dist/client/flight-client.js.map +1 -1
  30. package/dist/client/react-dom-renderer.js +2 -1
  31. package/dist/client/react-dom-renderer.js.map +1 -1
  32. package/dist/client/route-refresh.d.ts +2 -2
  33. package/dist/client/route-refresh.js +54 -39
  34. package/dist/client/route-refresh.js.map +1 -1
  35. package/dist/dev/panel.js +14 -14
  36. package/dist/dev/panel.js.map +1 -1
  37. package/dist/server/application.d.ts +2 -1
  38. package/dist/server/application.js +8 -6
  39. package/dist/server/application.js.map +1 -1
  40. package/dist/server/html-renderer.js +12 -11
  41. package/dist/server/html-renderer.js.map +1 -1
  42. package/dist/server/serve.d.ts +7 -0
  43. package/dist/server/serve.js +31 -0
  44. package/dist/server/serve.js.map +1 -0
  45. package/dist/server/start.d.ts +3 -0
  46. package/dist/server/start.js +24 -0
  47. package/dist/server/start.js.map +1 -0
  48. package/docs/02-guides/06-deploying-to-vercel/index.md +34 -0
  49. package/docs/02-guides/index.md +1 -0
  50. package/docs/03-advanced/02-client-navigation/index.md +17 -0
  51. package/docs/03-advanced/04-production-startup/01_server.ts +11 -0
  52. package/docs/03-advanced/04-production-startup/index.md +22 -0
  53. package/docs/03-advanced/index.md +1 -0
  54. package/package.json +27 -20
@@ -185,7 +185,7 @@ const reportStats = Effect.fnUntraced(function*(stats) {
185
185
  yield* Effect.logWarning(`${Terminal.yellow('▲')} Rspack compiled the application with warnings.\n${statsDiagnostics(stats)}`);
186
186
  }
187
187
  const duration = buildDuration(stats);
188
- yield* Effect.logInfo(duration === undefined ? `${Terminal.green('✓')} Build finished successfully.` : `${Terminal.green('✓')} Build finished successfully in ${formatDuration(duration)}.`);
188
+ yield* Effect.logInfo(duration === undefined ? `${Terminal.green('✓')} Compiled application.` : `${Terminal.green('✓')} Compiled application in ${formatDuration(duration)}.`);
189
189
  });
190
190
  const watchCompiler = (configs)=>Stream.callback((queue)=>Effect.gen(function*() {
191
191
  const compiler = yield* acquireCompiler(configs);
@@ -1 +1 @@
1
- {"version":3,"file":"build/rspack.js","sources":["../../src/build/rspack.ts"],"sourcesContent":["import rspack, {\n type Compiler,\n type Configuration,\n type MultiCompiler,\n type MultiStats,\n type Stats,\n} from '@rspack/core';\nimport { Context, Effect, Layer, Queue, Schema, Stream } from 'effect';\n\nimport { ServerEntryName } from './contract';\nimport { formatDuration, Terminal } from './terminal';\n\nexport class RspackError extends Schema.TaggedError<RspackError>()('RspackError', {\n message: Schema.String,\n cause: Schema.Defect(),\n reason: Schema.Literals(['CreateFailed', 'CompileFailed', 'BuildFailed', 'CloseFailed']),\n}) {}\n\ntype RspackCompiler = MultiCompiler;\ntype RspackStats = MultiStats;\ntype RspackWatching = ReturnType<RspackCompiler['watch']>;\n\nexport type RspackWatchEvent =\n | {\n readonly _tag: 'Building';\n readonly changedFiles: ReadonlyArray<string>;\n }\n | {\n readonly _tag: 'Compiled';\n readonly clientHash: string;\n readonly compilers: ReadonlyArray<{\n readonly duration?: number;\n readonly name: string;\n }>;\n readonly duration?: number;\n readonly hash: string;\n readonly serverBundle: {\n readonly filename: string;\n readonly outputPath: string;\n };\n readonly warnings?: string;\n }\n | {\n readonly _tag: 'Failed';\n readonly diagnostics: string;\n readonly error: RspackError;\n };\n\nconst failureMessage = (message: string) => `${Terminal.red('✗')} ${message}`;\n\nconst buildDuration = (stats: RspackStats) => {\n const compilations = stats.stats;\n const starts = compilations.flatMap(({ startTime }) =>\n startTime === undefined ? [] : [startTime],\n );\n const ends = compilations.flatMap(({ endTime }) => (endTime === undefined ? [] : [endTime]));\n\n if (starts.length !== compilations.length || ends.length !== compilations.length) {\n return undefined;\n }\n\n return Math.max(...ends) - Math.min(...starts);\n};\n\nconst compilerSummary = (stats: Stats) => {\n const { endTime, startTime } = stats;\n\n return {\n ...(startTime !== undefined && endTime !== undefined ? { duration: endTime - startTime } : {}),\n name: stats.compilation.name ?? 'compiler',\n };\n};\n\nconst closeCompiler = Effect.fnUntraced(function* (compiler: RspackCompiler) {\n yield* Effect.callback<void, RspackError>((resume) => {\n compiler.close((cause) => {\n resume(\n cause\n ? Effect.fail(\n new RspackError({\n message: failureMessage('Rspack failed to close the compiler.'),\n cause,\n reason: 'CloseFailed',\n }),\n )\n : Effect.void,\n );\n });\n });\n});\n\nconst closeWatching = Effect.fnUntraced(function* (watching: RspackWatching) {\n yield* Effect.callback<void, RspackError>((resume) => {\n watching.close((cause) => {\n resume(\n cause\n ? Effect.fail(\n new RspackError({\n message: failureMessage('Rspack failed to stop watching the application.'),\n cause,\n reason: 'CloseFailed',\n }),\n )\n : Effect.void,\n );\n });\n });\n});\n\nconst acquireCompiler = (configs: ReadonlyArray<Configuration>) =>\n Effect.acquireRelease(\n Effect.try({\n try: () => rspack([...configs]),\n catch: (cause) =>\n new RspackError({\n message: failureMessage('Rspack failed to create the application compiler.'),\n cause,\n reason: 'CreateFailed',\n }),\n }),\n (compiler) => closeCompiler(compiler).pipe(Effect.orDie),\n );\n\nconst compilationError = (cause: unknown) =>\n new RspackError({\n message: failureMessage('Rspack failed while compiling the application.'),\n cause,\n reason: 'CompileFailed',\n });\n\nconst missingStatsError = () =>\n new RspackError({\n message: failureMessage('Rspack completed without returning compilation statistics.'),\n cause: new Error('Missing Rspack compilation statistics.'),\n reason: 'CompileFailed',\n });\n\nconst statsDiagnostics = (stats: RspackStats, colors = true) =>\n stats.toString({\n colors,\n preset: 'errors-warnings',\n });\n\nconst failedWatchEvent = (\n error: RspackError,\n diagnostics = Bun.stripANSI(error.message),\n): RspackWatchEvent => ({\n _tag: 'Failed',\n diagnostics,\n error,\n});\n\nconst failedStatsError = (diagnostics: string) =>\n new RspackError({\n message: failureMessage('Rspack compiled the application with errors.'),\n cause: new Error(diagnostics),\n reason: 'BuildFailed',\n });\n\nconst emittedServerBundle = (stats: RspackStats) => {\n const serverStats = stats.stats.find(({ compilation }) => compilation.name === 'server');\n const output = serverStats?.toJson({\n all: false,\n chunks: true,\n entrypoints: true,\n ids: true,\n outputPath: true,\n });\n const entryChunkIds = output?.entrypoints?.[ServerEntryName]?.chunks ?? [];\n const filenames =\n output?.chunks?.flatMap((chunk) =>\n chunk.entry && chunk.id !== undefined && entryChunkIds.includes(chunk.id)\n ? (chunk.files ?? []).filter((filename) => filename.endsWith('.js'))\n : [],\n ) ?? [];\n const filename = filenames[0];\n\n return output?.outputPath && filename !== undefined && filenames.length === 1\n ? { filename, outputPath: output.outputPath }\n : undefined;\n};\n\nconst missingServerBundleError = () =>\n new RspackError({\n message: failureMessage('Rspack did not emit exactly one server entry bundle.'),\n cause: new Error('Missing or ambiguous server entry bundle in Rspack compilation statistics.'),\n reason: 'BuildFailed',\n });\n\nconst missingClientHashError = () =>\n new RspackError({\n message: failureMessage('Rspack did not emit a client compilation hash.'),\n cause: new Error('Missing client compilation hash in Rspack statistics.'),\n reason: 'BuildFailed',\n });\n\nconst clientCompilationHash = (stats: RspackStats) =>\n stats.stats.find(({ compilation }) => compilation.name === 'client')?.hash;\n\nconst watchEvent = (cause: Error | null, stats?: RspackStats): RspackWatchEvent => {\n if (cause) {\n return failedWatchEvent(compilationError(cause), Bun.stripANSI(cause.stack ?? cause.message));\n }\n if (!stats) {\n return failedWatchEvent(missingStatsError());\n }\n if (stats.hasErrors()) {\n return failedWatchEvent(\n failedStatsError(statsDiagnostics(stats)),\n statsDiagnostics(stats, false),\n );\n }\n const serverBundle = emittedServerBundle(stats);\n if (!serverBundle) {\n return failedWatchEvent(missingServerBundleError());\n }\n const clientHash = clientCompilationHash(stats);\n if (typeof clientHash !== 'string') {\n return failedWatchEvent(missingClientHashError());\n }\n const duration = buildDuration(stats);\n\n return {\n _tag: 'Compiled',\n clientHash,\n compilers: stats.stats.map(compilerSummary),\n ...(duration === undefined ? {} : { duration }),\n hash: stats.hash,\n serverBundle,\n ...(stats.hasWarnings() ? { warnings: statsDiagnostics(stats) } : {}),\n };\n};\n\nconst runCompiler = Effect.fnUntraced(function* (compiler: RspackCompiler) {\n return yield* Effect.callback<RspackStats, RspackError>((resume) => {\n compiler.run((cause, stats) => {\n if (cause) {\n resume(Effect.fail(compilationError(cause)));\n return;\n }\n if (!stats) {\n resume(Effect.fail(missingStatsError()));\n return;\n }\n\n resume(Effect.succeed(stats));\n });\n });\n});\n\nconst reportStats = Effect.fnUntraced(function* (stats: RspackStats) {\n if (stats.hasErrors()) {\n return yield* failedStatsError(statsDiagnostics(stats));\n }\n if (stats.hasWarnings()) {\n yield* Effect.logWarning(\n `${Terminal.yellow('▲')} Rspack compiled the application with warnings.\\n${statsDiagnostics(stats)}`,\n );\n }\n\n const duration = buildDuration(stats);\n\n yield* Effect.logInfo(\n duration === undefined\n ? `${Terminal.green('✓')} Build finished successfully.`\n : `${Terminal.green('✓')} Build finished successfully in ${formatDuration(duration)}.`,\n );\n});\n\nconst watchCompiler = (configs: ReadonlyArray<Configuration>) =>\n Stream.callback<RspackWatchEvent, RspackError>((queue) =>\n Effect.gen(function* () {\n const compiler = yield* acquireCompiler(configs);\n // The RSC client plugin mutates its own ignored predicate during watch setup.\n const watchOptions = configs.map(() => ({}));\n let watchState: 'Idle' | 'Building' = 'Idle';\n\n compiler.hooks.watchRun.tap(\n { name: 'ersc:watch-state', stage: -10_000 },\n (childCompiler: Compiler) => {\n if (watchState === 'Idle') {\n watchState = 'Building';\n Queue.offerUnsafe(queue, {\n _tag: 'Building',\n changedFiles: Array.from(childCompiler.modifiedFiles ?? []),\n });\n }\n },\n );\n\n yield* Effect.acquireRelease(\n Effect.try({\n try: () =>\n compiler.watch(watchOptions, (cause, stats) => {\n watchState = 'Idle';\n Queue.offerUnsafe(queue, watchEvent(cause, stats));\n }),\n catch: (cause) => compilationError(cause),\n }),\n (watching) => closeWatching(watching).pipe(Effect.orDie),\n );\n }),\n );\n\nexport class Rspack extends Context.Service<Rspack>()('ersc/build/Rspack', {\n make: Effect.succeed({\n build: Effect.fn('Rspack.build')(function* (configs: ReadonlyArray<Configuration>) {\n yield* Effect.logInfo(`${Terminal.cyan('●')} Building application with Rspack...`);\n\n const compiler = yield* acquireCompiler(configs);\n const stats = yield* runCompiler(compiler);\n\n yield* reportStats(stats);\n }),\n watch: watchCompiler,\n }),\n}) {\n static readonly layer = Layer.effect(this, this.make);\n}\n"],"names":["rspack","Context","Effect","Layer","Queue","Schema","Stream","ServerEntryName","formatDuration","Terminal","RspackError","failureMessage","message","buildDuration","stats","compilations","starts","startTime","undefined","ends","endTime","Math","compilerSummary","closeCompiler","compiler","resume","cause","closeWatching","watching","acquireCompiler","configs","compilationError","missingStatsError","Error","statsDiagnostics","colors","failedWatchEvent","error","diagnostics","Bun","failedStatsError","emittedServerBundle","serverStats","compilation","output","entryChunkIds","filenames","chunk","filename","missingServerBundleError","missingClientHashError","clientCompilationHash","watchEvent","serverBundle","clientHash","duration","runCompiler","reportStats","watchCompiler","queue","watchOptions","watchState","childCompiler","Array","Rspack"],"mappings":"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"}
1
+ {"version":3,"file":"build/rspack.js","sources":["../../src/build/rspack.ts"],"sourcesContent":["import rspack, {\n type Compiler,\n type Configuration,\n type MultiCompiler,\n type MultiStats,\n type Stats,\n} from '@rspack/core';\nimport { Context, Effect, Layer, Queue, Schema, Stream } from 'effect';\n\nimport { ServerEntryName } from './contract';\nimport { formatDuration, Terminal } from './terminal';\n\nexport class RspackError extends Schema.TaggedError<RspackError>()('RspackError', {\n message: Schema.String,\n cause: Schema.Defect(),\n reason: Schema.Literals(['CreateFailed', 'CompileFailed', 'BuildFailed', 'CloseFailed']),\n}) {}\n\ntype RspackCompiler = MultiCompiler;\ntype RspackStats = MultiStats;\ntype RspackWatching = ReturnType<RspackCompiler['watch']>;\n\nexport type RspackWatchEvent =\n | {\n readonly _tag: 'Building';\n readonly changedFiles: ReadonlyArray<string>;\n }\n | {\n readonly _tag: 'Compiled';\n readonly clientHash: string;\n readonly compilers: ReadonlyArray<{\n readonly duration?: number;\n readonly name: string;\n }>;\n readonly duration?: number;\n readonly hash: string;\n readonly serverBundle: {\n readonly filename: string;\n readonly outputPath: string;\n };\n readonly warnings?: string;\n }\n | {\n readonly _tag: 'Failed';\n readonly diagnostics: string;\n readonly error: RspackError;\n };\n\nconst failureMessage = (message: string) => `${Terminal.red('✗')} ${message}`;\n\nconst buildDuration = (stats: RspackStats) => {\n const compilations = stats.stats;\n const starts = compilations.flatMap(({ startTime }) =>\n startTime === undefined ? [] : [startTime],\n );\n const ends = compilations.flatMap(({ endTime }) => (endTime === undefined ? [] : [endTime]));\n\n if (starts.length !== compilations.length || ends.length !== compilations.length) {\n return undefined;\n }\n\n return Math.max(...ends) - Math.min(...starts);\n};\n\nconst compilerSummary = (stats: Stats) => {\n const { endTime, startTime } = stats;\n\n return {\n ...(startTime !== undefined && endTime !== undefined ? { duration: endTime - startTime } : {}),\n name: stats.compilation.name ?? 'compiler',\n };\n};\n\nconst closeCompiler = Effect.fnUntraced(function* (compiler: RspackCompiler) {\n yield* Effect.callback<void, RspackError>((resume) => {\n compiler.close((cause) => {\n resume(\n cause\n ? Effect.fail(\n new RspackError({\n message: failureMessage('Rspack failed to close the compiler.'),\n cause,\n reason: 'CloseFailed',\n }),\n )\n : Effect.void,\n );\n });\n });\n});\n\nconst closeWatching = Effect.fnUntraced(function* (watching: RspackWatching) {\n yield* Effect.callback<void, RspackError>((resume) => {\n watching.close((cause) => {\n resume(\n cause\n ? Effect.fail(\n new RspackError({\n message: failureMessage('Rspack failed to stop watching the application.'),\n cause,\n reason: 'CloseFailed',\n }),\n )\n : Effect.void,\n );\n });\n });\n});\n\nconst acquireCompiler = (configs: ReadonlyArray<Configuration>) =>\n Effect.acquireRelease(\n Effect.try({\n try: () => rspack([...configs]),\n catch: (cause) =>\n new RspackError({\n message: failureMessage('Rspack failed to create the application compiler.'),\n cause,\n reason: 'CreateFailed',\n }),\n }),\n (compiler) => closeCompiler(compiler).pipe(Effect.orDie),\n );\n\nconst compilationError = (cause: unknown) =>\n new RspackError({\n message: failureMessage('Rspack failed while compiling the application.'),\n cause,\n reason: 'CompileFailed',\n });\n\nconst missingStatsError = () =>\n new RspackError({\n message: failureMessage('Rspack completed without returning compilation statistics.'),\n cause: new Error('Missing Rspack compilation statistics.'),\n reason: 'CompileFailed',\n });\n\nconst statsDiagnostics = (stats: RspackStats, colors = true) =>\n stats.toString({\n colors,\n preset: 'errors-warnings',\n });\n\nconst failedWatchEvent = (\n error: RspackError,\n diagnostics = Bun.stripANSI(error.message),\n): RspackWatchEvent => ({\n _tag: 'Failed',\n diagnostics,\n error,\n});\n\nconst failedStatsError = (diagnostics: string) =>\n new RspackError({\n message: failureMessage('Rspack compiled the application with errors.'),\n cause: new Error(diagnostics),\n reason: 'BuildFailed',\n });\n\nconst emittedServerBundle = (stats: RspackStats) => {\n const serverStats = stats.stats.find(({ compilation }) => compilation.name === 'server');\n const output = serverStats?.toJson({\n all: false,\n chunks: true,\n entrypoints: true,\n ids: true,\n outputPath: true,\n });\n const entryChunkIds = output?.entrypoints?.[ServerEntryName]?.chunks ?? [];\n const filenames =\n output?.chunks?.flatMap((chunk) =>\n chunk.entry && chunk.id !== undefined && entryChunkIds.includes(chunk.id)\n ? (chunk.files ?? []).filter((filename) => filename.endsWith('.js'))\n : [],\n ) ?? [];\n const filename = filenames[0];\n\n return output?.outputPath && filename !== undefined && filenames.length === 1\n ? { filename, outputPath: output.outputPath }\n : undefined;\n};\n\nconst missingServerBundleError = () =>\n new RspackError({\n message: failureMessage('Rspack did not emit exactly one server entry bundle.'),\n cause: new Error('Missing or ambiguous server entry bundle in Rspack compilation statistics.'),\n reason: 'BuildFailed',\n });\n\nconst missingClientHashError = () =>\n new RspackError({\n message: failureMessage('Rspack did not emit a client compilation hash.'),\n cause: new Error('Missing client compilation hash in Rspack statistics.'),\n reason: 'BuildFailed',\n });\n\nconst clientCompilationHash = (stats: RspackStats) =>\n stats.stats.find(({ compilation }) => compilation.name === 'client')?.hash;\n\nconst watchEvent = (cause: Error | null, stats?: RspackStats): RspackWatchEvent => {\n if (cause) {\n return failedWatchEvent(compilationError(cause), Bun.stripANSI(cause.stack ?? cause.message));\n }\n if (!stats) {\n return failedWatchEvent(missingStatsError());\n }\n if (stats.hasErrors()) {\n return failedWatchEvent(\n failedStatsError(statsDiagnostics(stats)),\n statsDiagnostics(stats, false),\n );\n }\n const serverBundle = emittedServerBundle(stats);\n if (!serverBundle) {\n return failedWatchEvent(missingServerBundleError());\n }\n const clientHash = clientCompilationHash(stats);\n if (typeof clientHash !== 'string') {\n return failedWatchEvent(missingClientHashError());\n }\n const duration = buildDuration(stats);\n\n return {\n _tag: 'Compiled',\n clientHash,\n compilers: stats.stats.map(compilerSummary),\n ...(duration === undefined ? {} : { duration }),\n hash: stats.hash,\n serverBundle,\n ...(stats.hasWarnings() ? { warnings: statsDiagnostics(stats) } : {}),\n };\n};\n\nconst runCompiler = Effect.fnUntraced(function* (compiler: RspackCompiler) {\n return yield* Effect.callback<RspackStats, RspackError>((resume) => {\n compiler.run((cause, stats) => {\n if (cause) {\n resume(Effect.fail(compilationError(cause)));\n return;\n }\n if (!stats) {\n resume(Effect.fail(missingStatsError()));\n return;\n }\n\n resume(Effect.succeed(stats));\n });\n });\n});\n\nconst reportStats = Effect.fnUntraced(function* (stats: RspackStats) {\n if (stats.hasErrors()) {\n return yield* failedStatsError(statsDiagnostics(stats));\n }\n if (stats.hasWarnings()) {\n yield* Effect.logWarning(\n `${Terminal.yellow('▲')} Rspack compiled the application with warnings.\\n${statsDiagnostics(stats)}`,\n );\n }\n\n const duration = buildDuration(stats);\n\n yield* Effect.logInfo(\n duration === undefined\n ? `${Terminal.green('✓')} Compiled application.`\n : `${Terminal.green('✓')} Compiled application in ${formatDuration(duration)}.`,\n );\n});\n\nconst watchCompiler = (configs: ReadonlyArray<Configuration>) =>\n Stream.callback<RspackWatchEvent, RspackError>((queue) =>\n Effect.gen(function* () {\n const compiler = yield* acquireCompiler(configs);\n // The RSC client plugin mutates its own ignored predicate during watch setup.\n const watchOptions = configs.map(() => ({}));\n let watchState: 'Idle' | 'Building' = 'Idle';\n\n compiler.hooks.watchRun.tap(\n { name: 'ersc:watch-state', stage: -10_000 },\n (childCompiler: Compiler) => {\n if (watchState === 'Idle') {\n watchState = 'Building';\n Queue.offerUnsafe(queue, {\n _tag: 'Building',\n changedFiles: Array.from(childCompiler.modifiedFiles ?? []),\n });\n }\n },\n );\n\n yield* Effect.acquireRelease(\n Effect.try({\n try: () =>\n compiler.watch(watchOptions, (cause, stats) => {\n watchState = 'Idle';\n Queue.offerUnsafe(queue, watchEvent(cause, stats));\n }),\n catch: (cause) => compilationError(cause),\n }),\n (watching) => closeWatching(watching).pipe(Effect.orDie),\n );\n }),\n );\n\nexport class Rspack extends Context.Service<Rspack>()('ersc/build/Rspack', {\n make: Effect.succeed({\n build: Effect.fn('Rspack.build')(function* (configs: ReadonlyArray<Configuration>) {\n yield* Effect.logInfo(`${Terminal.cyan('●')} Building application with Rspack...`);\n\n const compiler = yield* acquireCompiler(configs);\n const stats = yield* runCompiler(compiler);\n\n yield* reportStats(stats);\n }),\n watch: watchCompiler,\n }),\n}) {\n static readonly layer = Layer.effect(this, this.make);\n}\n"],"names":["rspack","Context","Effect","Layer","Queue","Schema","Stream","ServerEntryName","formatDuration","Terminal","RspackError","failureMessage","message","buildDuration","stats","compilations","starts","startTime","undefined","ends","endTime","Math","compilerSummary","closeCompiler","compiler","resume","cause","closeWatching","watching","acquireCompiler","configs","compilationError","missingStatsError","Error","statsDiagnostics","colors","failedWatchEvent","error","diagnostics","Bun","failedStatsError","emittedServerBundle","serverStats","compilation","output","entryChunkIds","filenames","chunk","filename","missingServerBundleError","missingClientHashError","clientCompilationHash","watchEvent","serverBundle","clientHash","duration","runCompiler","reportStats","watchCompiler","queue","watchOptions","watchState","childCompiler","Array","Rspack"],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -1,7 +1,6 @@
1
- import { Config, Effect, Layer, Schema } from "effect";
1
+ import { Config, Effect, Schema } from "effect";
2
2
  import package_0 from "../package.json" with {"type":"json"};
3
- import { loadCompiledServer, makeRunnableServerLayer } from "./build/compiled-server.js";
4
- import { EnvironmentConfig } from "./build/contract.js";
3
+ import { serve } from "./server/serve.js";
5
4
  import { ApplicationIdleTimeoutSeconds, ApplicationMaxRequestBodySizeBytes, DefaultApplicationHostname, DefaultApplicationPort } from "./server/server-config.js";
6
5
 
7
6
  import * as __rspack_external__effect_platform_bun_BunHttpServer_0e4f7bbb from "@effect/platform-bun/BunHttpServer";
@@ -27,8 +26,6 @@ import * as __rspack_external_effect_unstable_cli_Flag_7320ac06 from "effect/uns
27
26
 
28
27
 
29
28
 
30
-
31
-
32
29
  class BuildModuleLoadError extends Schema.TaggedError()('BuildModuleLoadError', {
33
30
  message: Schema.String,
34
31
  cause: Schema.Defect()
@@ -39,19 +36,7 @@ class DevModuleLoadError extends Schema.TaggedError()('DevModuleLoadError', {
39
36
  cause: Schema.Defect()
40
37
  }) {
41
38
  }
42
- const start = Effect.fn('ersc/cli/start')(function*({ hostname, port, root }) {
43
- const bundle = yield* loadCompiledServer(root);
44
- const ServerLayer = yield* makeRunnableServerLayer({
45
- bundle,
46
- clientAssetsCacheControl: EnvironmentConfig.production.clientAssetsCacheControl,
47
- clientOutputDir: EnvironmentConfig.production.clientOutputDir,
48
- hostname,
49
- port,
50
- root
51
- });
52
- return yield* Layer.launch(ServerLayer);
53
- });
54
- const runBuild = Effect.fnUntraced(function*() {
39
+ const runBuild = Effect.fnUntraced(function*({ adapter }) {
55
40
  const { buildApplication } = yield* Effect.tryPromise({
56
41
  try: ()=>import("./build/build.js"),
57
42
  catch: (cause)=>new BuildModuleLoadError({
@@ -60,12 +45,16 @@ const runBuild = Effect.fnUntraced(function*() {
60
45
  })
61
46
  });
62
47
  yield* buildApplication({
63
- root: process.cwd()
48
+ root: process.cwd(),
49
+ adapter
64
50
  });
65
51
  });
66
- const buildCommand = __rspack_external_effect_unstable_cli_Command_ef1b8bde.make('build').pipe(__rspack_external_effect_unstable_cli_Command_ef1b8bde.withDescription('Compile an effective-rsc application with Rspack.'), __rspack_external_effect_unstable_cli_Command_ef1b8bde.withHandler(runBuild));
67
- const cli_hostname = __rspack_external_effect_unstable_cli_Flag_7320ac06.string('hostname').pipe(__rspack_external_effect_unstable_cli_Flag_7320ac06.withDescription('Hostname to bind (defaults to HOST or localhost)'), __rspack_external_effect_unstable_cli_Flag_7320ac06.withFallbackConfig(Config.string('HOST').pipe(Config.withDefault(DefaultApplicationHostname))), __rspack_external_effect_unstable_cli_Flag_7320ac06.withSchema(Schema.NonEmptyString));
68
- const cli_port = __rspack_external_effect_unstable_cli_Flag_7320ac06.integer('port').pipe(__rspack_external_effect_unstable_cli_Flag_7320ac06.withDescription(`Port to bind (defaults to PORT or ${DefaultApplicationPort})`), __rspack_external_effect_unstable_cli_Flag_7320ac06.withFallbackConfig(Config.int('PORT').pipe(Config.withDefault(DefaultApplicationPort))), __rspack_external_effect_unstable_cli_Flag_7320ac06.withSchema(Schema.Int.check(Schema.isBetween({
52
+ const cli_adapter = __rspack_external_effect_unstable_cli_Flag_7320ac06.String('adapter').pipe(__rspack_external_effect_unstable_cli_Flag_7320ac06.withDescription('Installed deployment adapter package to run after compilation'), __rspack_external_effect_unstable_cli_Flag_7320ac06.withSchema(Schema.NonEmptyString), __rspack_external_effect_unstable_cli_Flag_7320ac06.optional);
53
+ const buildCommand = __rspack_external_effect_unstable_cli_Command_ef1b8bde.make('build', {
54
+ adapter: cli_adapter
55
+ }).pipe(__rspack_external_effect_unstable_cli_Command_ef1b8bde.withDescription('Compile an effective-rsc application with Rspack.'), __rspack_external_effect_unstable_cli_Command_ef1b8bde.withHandler(runBuild));
56
+ const cli_hostname = __rspack_external_effect_unstable_cli_Flag_7320ac06.String('hostname').pipe(__rspack_external_effect_unstable_cli_Flag_7320ac06.withDescription('Hostname to bind (defaults to HOST or localhost)'), __rspack_external_effect_unstable_cli_Flag_7320ac06.withFallbackConfig(Config.String('HOST').pipe(Config.withDefault(DefaultApplicationHostname))), __rspack_external_effect_unstable_cli_Flag_7320ac06.withSchema(Schema.NonEmptyString));
57
+ const cli_port = __rspack_external_effect_unstable_cli_Flag_7320ac06.Int('port').pipe(__rspack_external_effect_unstable_cli_Flag_7320ac06.withDescription(`Port to bind (defaults to PORT or ${DefaultApplicationPort})`), __rspack_external_effect_unstable_cli_Flag_7320ac06.withFallbackConfig(Config.Int('PORT').pipe(Config.withDefault(DefaultApplicationPort))), __rspack_external_effect_unstable_cli_Flag_7320ac06.withSchema(Schema.Int.check(Schema.isBetween({
69
58
  minimum: 1,
70
59
  maximum: 65535
71
60
  }))));
@@ -98,11 +87,11 @@ const devCommand = __rspack_external_effect_unstable_cli_Command_ef1b8bde.make('
98
87
  const startCommand = __rspack_external_effect_unstable_cli_Command_ef1b8bde.make('start', {
99
88
  hostname: cli_hostname,
100
89
  port: cli_port
101
- }).pipe(__rspack_external_effect_unstable_cli_Command_ef1b8bde.withDescription('Start the compiled application with Bun.'), __rspack_external_effect_unstable_cli_Command_ef1b8bde.withHandler(({ hostname, port })=>start({
90
+ }).pipe(__rspack_external_effect_unstable_cli_Command_ef1b8bde.withDescription('Start the compiled application with Bun.'), __rspack_external_effect_unstable_cli_Command_ef1b8bde.withHandler(({ hostname, port })=>serve({
102
91
  hostname,
103
92
  port,
104
93
  root: process.cwd()
105
- })));
94
+ }).pipe(Effect.andThen(Effect.never), Effect.scoped)));
106
95
  const cli = __rspack_external_effect_unstable_cli_Command_ef1b8bde.make('ersc').pipe(__rspack_external_effect_unstable_cli_Command_ef1b8bde.withDescription('Build and run an effective-rsc application.'), __rspack_external_effect_unstable_cli_Command_ef1b8bde.withSubcommands([
107
96
  devCommand,
108
97
  buildCommand,
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 // 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
+ {"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, Option, 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 { serve } from './server/serve';\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 runBuild = Effect.fnUntraced(function* ({\n adapter,\n}: {\n readonly adapter: Option.Option<string>;\n}) {\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(), adapter });\n});\n\nconst adapter = Flag.String('adapter').pipe(\n Flag.withDescription('Installed deployment adapter package to run after compilation'),\n Flag.withSchema(Schema.NonEmptyString),\n Flag.optional,\n);\n\nconst buildCommand = Command.make('build', { adapter }).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.Int('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 }) =>\n serve({ hostname, port, root: process.cwd() }).pipe(\n Effect.andThen(Effect.never),\n Effect.scoped,\n ),\n ),\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","Schema","Command","Flag","PackageJson","serve","ApplicationIdleTimeoutSeconds","ApplicationMaxRequestBodySizeBytes","DefaultApplicationHostname","DefaultApplicationPort","BuildModuleLoadError","DevModuleLoadError","runBuild","adapter","buildApplication","cause","process","buildCommand","hostname","port","runDev","devApplication","devCommand","startCommand","cli","program"],"mappings":"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"}
@@ -5,33 +5,21 @@ export type BrowserRendererNavigation = {
5
5
  readonly discard: () => Promise<void>;
6
6
  readonly retired: Promise<void>;
7
7
  };
8
- type BrowserRenderNavigationState = {
8
+ type InitialRender = {
9
+ readonly _tag: 'Initial';
10
+ readonly routeTree: RouteTreeModel;
11
+ };
12
+ type RouteRender = {
13
+ readonly _tag: 'Navigation' | 'Refresh';
14
+ readonly order: number;
9
15
  readonly committed: PromiseWithResolvers<void>;
10
16
  readonly retired: PromiseWithResolvers<void>;
11
17
  readonly routeTree: RouteTreeModel;
12
18
  };
13
- type BrowserRenderOwner = {
14
- readonly _tag: 'Stable';
15
- } | {
16
- readonly _tag: 'Navigation';
17
- readonly navigation: BrowserRenderNavigationState;
18
- };
19
- export type BrowserRender = {
20
- readonly _tag: 'Initial';
21
- readonly routeTree: RouteTreeModel;
22
- } | {
23
- readonly _tag: 'Navigation';
24
- readonly navigation: BrowserRenderNavigationState;
25
- readonly routeTree: RouteTreeModel;
26
- } | {
19
+ export type BrowserRender = InitialRender | RouteRender | {
27
20
  readonly _tag: 'Discard';
28
- readonly navigation: BrowserRenderNavigationState;
29
- readonly routeTree: RouteTreeModel;
30
- readonly visible: BrowserRenderOwner;
31
- } | {
32
- readonly _tag: 'Refresh';
33
- readonly committed: PromiseWithResolvers<void>;
34
- readonly routeTree: RouteTreeModel;
21
+ readonly order: number;
22
+ readonly restore: InitialRender | RouteRender;
35
23
  };
36
24
  declare const BrowserRenderer_base: Context.ServiceClass<BrowserRenderer, "ersc/client/BrowserRenderer", {
37
25
  commit: (render: BrowserRender) => void;
@@ -41,7 +29,11 @@ declare const BrowserRenderer_base: Context.ServiceClass<BrowserRenderer, "ersc/
41
29
  discard: () => Promise<void>;
42
30
  retired: Promise<void>;
43
31
  };
44
- refresh: (routeTree: RouteTreeModel) => Promise<void>;
32
+ refresh: (routeTree: RouteTreeModel) => {
33
+ committed: Promise<void>;
34
+ discard: () => Promise<void>;
35
+ retired: Promise<void>;
36
+ };
45
37
  }> & {
46
38
  readonly make: Effect.Effect<{
47
39
  commit: (render: BrowserRender) => void;
@@ -51,7 +43,11 @@ declare const BrowserRenderer_base: Context.ServiceClass<BrowserRenderer, "ersc/
51
43
  discard: () => Promise<void>;
52
44
  retired: Promise<void>;
53
45
  };
54
- refresh: (routeTree: RouteTreeModel) => Promise<void>;
46
+ refresh: (routeTree: RouteTreeModel) => {
47
+ committed: Promise<void>;
48
+ discard: () => Promise<void>;
49
+ retired: Promise<void>;
50
+ };
55
51
  }, never, never>;
56
52
  };
57
53
  export declare class BrowserRenderer extends BrowserRenderer_base {
@@ -64,7 +60,11 @@ export declare class BrowserRenderer extends BrowserRenderer_base {
64
60
  discard: () => Promise<void>;
65
61
  retired: Promise<void>;
66
62
  };
67
- refresh: (routeTree: RouteTreeModel) => Promise<void>;
63
+ refresh: (routeTree: RouteTreeModel) => {
64
+ committed: Promise<void>;
65
+ discard: () => Promise<void>;
66
+ retired: Promise<void>;
67
+ };
68
68
  }) => Layer.Layer<BrowserRenderer, never, never>;
69
69
  }
70
70
  export {};
@@ -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
- lifecycle: {
41
- active: {
42
- _tag: 'Stable'
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 navigate = (routeTree)=>{
54
- const { lifecycle, publish } = getReadyState();
55
- const navigation = {
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
- lifecycle.phases.set(navigation, 'Scheduled');
61
- lifecycle.active = {
62
- _tag: 'Navigation',
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: navigation.committed.promise,
57
+ committed: render.committed.promise,
72
58
  discard: ()=>{
73
- if (getNavigationPhase(lifecycle, navigation) !== 'Scheduled') {
74
- throw new TypeError('Only a scheduled browser navigation can be discarded.');
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
- lifecycle.phases.set(navigation, 'DiscardRequested');
77
- if (lifecycle.active._tag === 'Navigation' && lifecycle.active.navigation === navigation) {
78
- const visible = lifecycle.visible;
79
- lifecycle.active = visible._tag === 'Navigation' && getNavigationPhase(lifecycle, visible.navigation) === 'Visible' ? visible : {
80
- _tag: 'Stable'
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
- navigation,
86
- routeTree: lifecycle.visible._tag === 'Navigation' ? lifecycle.visible.navigation.routeTree : lifecycle.stableRouteTree,
87
- visible: lifecycle.visible
82
+ order: discardOrder,
83
+ restore
88
84
  });
89
- return navigation.retired.promise;
85
+ return render.retired.promise;
90
86
  },
91
- retired: navigation.retired.promise
87
+ retired: render.retired.promise
92
88
  };
93
89
  };
94
- const refresh = (routeTree)=>{
95
- const { lifecycle, publish } = getReadyState();
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 { lifecycle } = getReadyState();
109
- const previousVisible = lifecycle.visible;
110
- const visible = render._tag === 'Navigation' ? {
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
- switch(render._tag){
121
- case 'Initial':
122
- break;
123
- case 'Discard':
124
- retireNavigation(lifecycle, render.navigation);
125
- break;
126
- case 'Navigation':
127
- if (getNavigationPhase(lifecycle, render.navigation) === 'Scheduled') {
128
- lifecycle.phases.set(render.navigation, 'Visible');
129
- }
130
- if (lifecycle.active._tag === 'Navigation' && lifecycle.active.navigation === render.navigation) {
131
- lifecycle.active = {
132
- _tag: 'Stable'
133
- };
134
- lifecycle.stableRouteTree = render.routeTree;
135
- lifecycle.phases.set(render.navigation, 'Completed');
136
- }
137
- render.navigation.committed.resolve();
138
- break;
139
- case 'Refresh':
140
- lifecycle.stableRouteTree = render.routeTree;
141
- render.committed.resolve();
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 renderCommitted;
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
- renderCommitted = browserRenderer.refresh(resource.payload.routeTree);
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(()=>renderCommitted)
139
+ Effect.promise(()=>published.committed)
140
140
  ], {
141
141
  concurrency: 'unbounded',
142
142
  discard: true
143
- }).pipe(Effect.andThen(Effect.sync(commitRefresh)), Effect.onError(()=>resource.release), Effect.forkScoped);
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)=>{