effective-rsc 0.1.2 → 0.1.3

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 CHANGED
@@ -159,6 +159,41 @@ reach.
159
159
 
160
160
  - **[Composing ERSC and userland HTTP](./docs/02-guides/05-http/10_application-layer.tsx)**: ERSC concerns and native HTTP routes share one application Layer.
161
161
 
162
+ ### Deploying to Vercel
163
+
164
+ Deploy to Vercel with Bun 1.4+. Match the adapter version to `effective-rsc`.
165
+
166
+ ```sh
167
+ bun add --dev @ersc/vercel
168
+ ```
169
+
170
+ Set the build script in `package.json`:
171
+
172
+ ```json
173
+ {
174
+ "scripts": {
175
+ "build": "ersc build --adapter @ersc/vercel"
176
+ }
177
+ }
178
+ ```
179
+
180
+ Commit `bun.lock`, connect your GitHub repository in Vercel, and set:
181
+
182
+ | Setting | Value |
183
+ | ---------------- | ------------------------------- |
184
+ | Framework Preset | Other |
185
+ | Root Directory | Application directory |
186
+ | Install Command | `bun install --frozen-lockfile` |
187
+ | Build Command | `bun run --bun build` |
188
+ | Output Directory | Leave the override disabled |
189
+
190
+ Add your environment variables and deploy. The adapter generates `.vercel/output/`; no custom
191
+ server entry or `vercel.json` is needed.
192
+
193
+ For [monorepos](https://vercel.com/docs/monorepos/monorepo-faq), enable **Include source files outside
194
+ of the Root Directory in the Build Step**. With Turborepo, use
195
+ `bun run --bun turbo run build --filter=your-app` to build the app and its workspace dependencies.
196
+
162
197
  ## Advanced
163
198
 
164
199
  These guides describe ERSC's runtime guarantees. See the
@@ -264,6 +299,39 @@ commit inside an async Action.
264
299
  After a successful mutation, ERSC clears the Back/Forward traversal cache because any route may have
265
300
  changed.
266
301
 
302
+ ## Production startup
303
+
304
+ Run `ersc build`, then `ersc start`. A custom Bun entry can await
305
+ `start({ root, hostname, port })` from `effective-rsc/server`. All options are required;
306
+ `root` is the application directory. Deploy its `.ersc/`, `public/`, and runtime dependencies.
307
+
308
+ The Promise resolves when ready; startup failures reject and exit. ERSC owns signal handling
309
+ and cleanup, so do not wrap it in `BunRuntime.runMain`.
310
+
311
+ ### Deployment adapters
312
+
313
+ `ersc build --adapter <package>` runs an installed adapter after compilation; it does not upload.
314
+ Without the flag, packaging is skipped and previous output remains.
315
+
316
+ Adapters export `build: BuildHook` from `./build`, with types from `effective-rsc/build`.
317
+ The hook receives absolute `root`, `serverDir`, `clientDir`, and `publicDir` paths and returns
318
+ `Effect<void, Error, Scope>`. Inputs are read-only; adapters provide dependencies and ERSC owns
319
+ cleanup/cancellation. Failures stop the build.
320
+
321
+ ### Server entry
322
+
323
+ Save this as `server.ts` in the application root and run it with `bun server.ts` after building.
324
+
325
+ ```ts
326
+ import { start } from 'effective-rsc/server';
327
+
328
+ await start({
329
+ hostname: 'localhost',
330
+ port: 18193,
331
+ root: import.meta.dir,
332
+ });
333
+ ```
334
+
267
335
  ## API reference
268
336
 
269
337
  Under the `react-server` condition, the package root exports `Application`.
package/README.md CHANGED
@@ -154,6 +154,10 @@ Run `bun run dev`, then open `http://localhost:18193`. For a production run, use
154
154
  For deployment, `ersc start` accepts `--hostname` and `--port`. Command-line flags take precedence
155
155
  over `HOST` and `PORT`; the defaults are `localhost` and `18193`.
156
156
 
157
+ For a custom Bun entry, await `start({ root, hostname, port })` from `effective-rsc/server`.
158
+ Use `ersc build --adapter <package>` to package deployment output without uploading it.
159
+ See the [production startup guide](https://github.com/nikhilsnayak/effective-rsc/blob/main/packages/effective-rsc/docs/03-advanced/04-production-startup/index.md).
160
+
157
161
  ## Styling
158
162
 
159
163
  Import stylesheets from the modules that use them; there is no framework stylesheet entry point:
@@ -199,10 +203,12 @@ The package-root API is available only under the `react-server` condition. The f
199
203
  enables that condition for application authoring modules; importing `effective-rsc` from another
200
204
  runtime, including a Client Component, throws immediately.
201
205
 
202
- ## Example and documentation
206
+ ## Examples and documentation
203
207
 
204
- The [event platform](https://github.com/nikhilsnayak/effective-rsc/tree/main/examples/event-platform)
205
- is the complete application example.
208
+ - [Hello world](https://github.com/nikhilsnayak/effective-rsc/tree/main/examples/hello-world): a small
209
+ example with streaming, navigation, a counter, and a Server Function form.
210
+ - [Event platform](https://github.com/nikhilsnayak/effective-rsc/tree/main/examples/event-platform):
211
+ the complete application example, using local SQLite persistence.
206
212
 
207
213
  - [Getting started](https://github.com/nikhilsnayak/effective-rsc/blob/main/packages/effective-rsc/docs/01-getting-started/index.md)
208
214
  - [Guides](https://github.com/nikhilsnayak/effective-rsc/blob/main/packages/effective-rsc/docs/02-guides/index.md)
@@ -1,4 +1,4 @@
1
- import { Effect, Path, Schema } from 'effect';
1
+ import { Effect, Option, Path, Schema } from 'effect';
2
2
  import { Rspack } from './rspack.js';
3
3
  export type BuildOptions = {
4
4
  readonly root: string;
@@ -22,5 +22,7 @@ export declare const resolveApplicationBuild: (args_0: ResolveApplicationBuildOp
22
22
  };
23
23
  }, BuildEntryError, Path.Path>;
24
24
  export declare const build: (options: BuildOptions) => Effect.Effect<void, BuildEntryError | import("./rspack.js").RspackError, Path.Path | Rspack | import("effect/Scope").Scope>;
25
- export declare const buildApplication: (options: BuildOptions) => Effect.Effect<void, BuildEntryError | import("./rspack.js").RspackError, Path.Path>;
25
+ export declare const buildApplication: (options: BuildOptions & {
26
+ readonly adapter: Option.Option<string>;
27
+ }) => Effect.Effect<void, BuildEntryError | import("./deployment.js").DeploymentBuildError | import("./rspack.js").RspackError, Path.Path>;
26
28
  export {};
@@ -1,7 +1,13 @@
1
- import { Effect, Path, Schema } from "effect";
2
- import { ApplicationEntryPath } from "./contract.js";
1
+ import { Effect, Option, Path, Schema } from "effect";
2
+ import { ApplicationEntryPath, EnvironmentConfig, PublicAssetsDir } from "./contract.js";
3
+ import { runDeploymentBuild } from "./deployment.js";
3
4
  import { Rspack } from "./rspack.js";
4
5
  import { makeRspackBuildConfig } from "./rspack-config.js";
6
+ import { Terminal } from "./terminal.js";
7
+
8
+
9
+
10
+
5
11
 
6
12
 
7
13
 
@@ -52,6 +58,17 @@ const build = Effect.fn('ersc/rspack/build')(function*(options) {
52
58
  });
53
59
  const buildApplication = Effect.fn('ersc/build/buildApplication')(function*(options) {
54
60
  yield* build(options).pipe(Effect.provide(Rspack.layer), Effect.scoped);
61
+ if (Option.isSome(options.adapter)) {
62
+ const path = yield* Path.Path;
63
+ const root = path.resolve(options.root);
64
+ yield* runDeploymentBuild(options.adapter.value, {
65
+ root,
66
+ serverDir: path.join(root, EnvironmentConfig.production.serverOutputDir),
67
+ clientDir: path.join(root, EnvironmentConfig.production.clientOutputDir),
68
+ publicDir: path.join(root, PublicAssetsDir)
69
+ });
70
+ }
71
+ yield* Effect.logInfo(`${Terminal.green('✓')} Build finished successfully.`);
55
72
  });
56
73
 
57
74
  export { BuildEntryError, build, buildApplication, resolveApplicationBuild };
@@ -1 +1 @@
1
- {"version":3,"file":"build/build.js","sources":["../../src/build/build.ts"],"sourcesContent":["import { Effect, Path, Schema } from 'effect';\n\nimport { ApplicationEntryPath } from './contract';\nimport { Rspack } from './rspack';\nimport { makeRspackBuildConfig } from './rspack-config';\n\nexport type BuildOptions = {\n readonly root: string;\n};\n\nexport type ResolveApplicationBuildOptions = BuildOptions & {\n readonly buildModuleUrl?: URL;\n};\n\nexport class BuildEntryError extends Schema.TaggedError<BuildEntryError>()('BuildEntryError', {\n message: Schema.String,\n cause: Schema.Defect(),\n}) {}\n\nconst ClientEntryPath = '../client/entry.js';\nconst RscEntryPath = './rsc-entry.js';\nconst SsrEntryPath = '../server/html-renderer.js';\n\nconst resolveFrameworkEntry = Effect.fnUntraced(function* (\n buildModuleUrl: URL,\n relativePath: string,\n) {\n const path = yield* Path.Path;\n\n const buildModulePath = yield* path.fromFileUrl(buildModuleUrl).pipe(\n Effect.mapError(\n (cause) =>\n new BuildEntryError({\n message: `Failed to convert the framework build module ${buildModuleUrl.href} to a file path.`,\n cause,\n }),\n ),\n );\n\n return path.resolve(path.dirname(buildModulePath), relativePath);\n});\n\nexport const resolveApplicationBuild = Effect.fnUntraced(function* ({\n root,\n buildModuleUrl = new URL(import.meta.url),\n}: ResolveApplicationBuildOptions) {\n const path = yield* Path.Path;\n const applicationRoot = path.resolve(root);\n const applicationPath = path.resolve(applicationRoot, ApplicationEntryPath);\n const clientEntry = yield* resolveFrameworkEntry(buildModuleUrl, ClientEntryPath);\n const rscEntry = yield* resolveFrameworkEntry(buildModuleUrl, RscEntryPath);\n const ssrEntry = yield* resolveFrameworkEntry(buildModuleUrl, SsrEntryPath);\n const entries = {\n application: applicationPath,\n client: clientEntry,\n rsc: rscEntry,\n ssr: ssrEntry,\n };\n\n return { applicationRoot, entries } as const;\n});\n\nexport const build = Effect.fn('ersc/rspack/build')(function* (options: BuildOptions) {\n const { applicationRoot, entries } = yield* resolveApplicationBuild(options);\n const rspack = yield* Rspack;\n\n yield* rspack.build(makeRspackBuildConfig(applicationRoot, entries));\n});\n\nexport const buildApplication = Effect.fn('ersc/build/buildApplication')(function* (\n options: BuildOptions,\n) {\n yield* build(options).pipe(Effect.provide(Rspack.layer), Effect.scoped);\n});\n"],"names":["Effect","Path","Schema","ApplicationEntryPath","Rspack","makeRspackBuildConfig","BuildEntryError","ClientEntryPath","RscEntryPath","SsrEntryPath","resolveFrameworkEntry","buildModuleUrl","relativePath","path","buildModulePath","cause","resolveApplicationBuild","root","URL","applicationRoot","applicationPath","clientEntry","rscEntry","ssrEntry","entries","build","options","rspack","buildApplication"],"mappings":";;;;;;;;;AAA8C;AAEI;AAChB;AACsB;AAUjD,MAAMM,eAAeA,SAASJ,kBAAkB,GAAoB,mBAAmB;IAC5F,SAASA,aAAa;IACtB,OAAOA,aAAa;AACtB;AAAI;AAEJ,MAAMK,eAAeA,GAAG;AACxB,MAAMC,YAAYA,GAAG;AACrB,MAAMC,YAAYA,GAAG;AAErB,MAAMC,qBAAqBA,GAAGV,iBAAiB,CAAC,UAC9CW,cAAmB,EACnBC,YAAoB;IAEpB,MAAMC,OAAO,OAAOZ,SAAS;IAE7B,MAAMa,kBAAkB,OAAOD,KAAK,WAAW,CAACF,gBAAgB,IAAI,CAClEX,eAAe,CACb,CAACe,QACC,IAAIT,eAAeA,CAAC;YAClB,SAAS,CAAC,6CAA6C,EAAEK,eAAe,IAAI,CAAC,gBAAgB,CAAC;YAC9FI;QACF;IAIN,OAAOF,KAAK,OAAO,CAACA,KAAK,OAAO,CAACC,kBAAkBF;AACrD;AAEO,MAAMI,uBAAuBA,GAAGhB,iBAAiB,CAAC,UAAW,EAClEiB,IAAI,EACJN,iBAAiB,IAAIO,IAAI,YAAY,GAAG,CAAC,EACV;IAC/B,MAAML,OAAO,OAAOZ,SAAS;IAC7B,MAAMkB,kBAAkBN,KAAK,OAAO,CAACI;IACrC,MAAMG,kBAAkBP,KAAK,OAAO,CAACM,iBAAiBhB,oBAAoBA;IAC1E,MAAMkB,cAAc,OAAOX,qBAAqBA,CAACC,gBAAgBJ,eAAeA;IAChF,MAAMe,WAAW,OAAOZ,qBAAqBA,CAACC,gBAAgBH,YAAYA;IAC1E,MAAMe,WAAW,OAAOb,qBAAqBA,CAACC,gBAAgBF,YAAYA;IAC1E,MAAMe,UAAU;QACd,aAAaJ;QACb,QAAQC;QACR,KAAKC;QACL,KAAKC;IACP;IAEA,OAAO;QAAEJ;QAAiBK;IAAQ;AACpC,GAAG;AAEI,MAAMC,KAAKA,GAAGzB,SAAS,CAAC,qBAAqB,UAAW0B,OAAqB;IAClF,MAAM,EAAEP,eAAe,EAAEK,OAAO,EAAE,GAAG,OAAOR,uBAAuBA,CAACU;IACpE,MAAMC,SAAS,OAAOvB,MAAMA;IAE5B,OAAOuB,OAAO,KAAK,CAACtB,qBAAqBA,CAACc,iBAAiBK;AAC7D,GAAG;AAEI,MAAMI,gBAAgBA,GAAG5B,SAAS,CAAC,+BAA+B,UACvE0B,OAAqB;IAErB,OAAOD,KAAKA,CAACC,SAAS,IAAI,CAAC1B,cAAc,CAACI,YAAY,GAAGJ,aAAa;AACxE,GAAG"}
1
+ {"version":3,"file":"build/build.js","sources":["../../src/build/build.ts"],"sourcesContent":["import { Effect, Option, Path, Schema } from 'effect';\n\nimport { ApplicationEntryPath, EnvironmentConfig, PublicAssetsDir } from './contract';\nimport { runDeploymentBuild } from './deployment';\nimport { Rspack } from './rspack';\nimport { makeRspackBuildConfig } from './rspack-config';\nimport { Terminal } from './terminal';\n\nexport type BuildOptions = {\n readonly root: string;\n};\n\nexport type ResolveApplicationBuildOptions = BuildOptions & {\n readonly buildModuleUrl?: URL;\n};\n\nexport class BuildEntryError extends Schema.TaggedError<BuildEntryError>()('BuildEntryError', {\n message: Schema.String,\n cause: Schema.Defect(),\n}) {}\n\nconst ClientEntryPath = '../client/entry.js';\nconst RscEntryPath = './rsc-entry.js';\nconst SsrEntryPath = '../server/html-renderer.js';\n\nconst resolveFrameworkEntry = Effect.fnUntraced(function* (\n buildModuleUrl: URL,\n relativePath: string,\n) {\n const path = yield* Path.Path;\n\n const buildModulePath = yield* path.fromFileUrl(buildModuleUrl).pipe(\n Effect.mapError(\n (cause) =>\n new BuildEntryError({\n message: `Failed to convert the framework build module ${buildModuleUrl.href} to a file path.`,\n cause,\n }),\n ),\n );\n\n return path.resolve(path.dirname(buildModulePath), relativePath);\n});\n\nexport const resolveApplicationBuild = Effect.fnUntraced(function* ({\n root,\n buildModuleUrl = new URL(import.meta.url),\n}: ResolveApplicationBuildOptions) {\n const path = yield* Path.Path;\n const applicationRoot = path.resolve(root);\n const applicationPath = path.resolve(applicationRoot, ApplicationEntryPath);\n const clientEntry = yield* resolveFrameworkEntry(buildModuleUrl, ClientEntryPath);\n const rscEntry = yield* resolveFrameworkEntry(buildModuleUrl, RscEntryPath);\n const ssrEntry = yield* resolveFrameworkEntry(buildModuleUrl, SsrEntryPath);\n const entries = {\n application: applicationPath,\n client: clientEntry,\n rsc: rscEntry,\n ssr: ssrEntry,\n };\n\n return { applicationRoot, entries } as const;\n});\n\nexport const build = Effect.fn('ersc/rspack/build')(function* (options: BuildOptions) {\n const { applicationRoot, entries } = yield* resolveApplicationBuild(options);\n const rspack = yield* Rspack;\n\n yield* rspack.build(makeRspackBuildConfig(applicationRoot, entries));\n});\n\nexport const buildApplication = Effect.fn('ersc/build/buildApplication')(function* (\n options: BuildOptions & { readonly adapter: Option.Option<string> },\n) {\n yield* build(options).pipe(Effect.provide(Rspack.layer), Effect.scoped);\n if (Option.isSome(options.adapter)) {\n const path = yield* Path.Path;\n const root = path.resolve(options.root);\n yield* runDeploymentBuild(options.adapter.value, {\n root,\n serverDir: path.join(root, EnvironmentConfig.production.serverOutputDir),\n clientDir: path.join(root, EnvironmentConfig.production.clientOutputDir),\n publicDir: path.join(root, PublicAssetsDir),\n });\n }\n yield* Effect.logInfo(`${Terminal.green('✓')} Build finished successfully.`);\n});\n"],"names":["Effect","Option","Path","Schema","ApplicationEntryPath","EnvironmentConfig","PublicAssetsDir","runDeploymentBuild","Rspack","makeRspackBuildConfig","Terminal","BuildEntryError","ClientEntryPath","RscEntryPath","SsrEntryPath","resolveFrameworkEntry","buildModuleUrl","relativePath","path","buildModulePath","cause","resolveApplicationBuild","root","URL","applicationRoot","applicationPath","clientEntry","rscEntry","ssrEntry","entries","build","options","rspack","buildApplication"],"mappings":";;;;;;;;;;;;;AAAsD;AAEgC;AACpC;AAChB;AACsB;AAClB;AAU/B,MAAMW,eAAeA,SAASR,kBAAkB,GAAoB,mBAAmB;IAC5F,SAASA,aAAa;IACtB,OAAOA,aAAa;AACtB;AAAI;AAEJ,MAAMS,eAAeA,GAAG;AACxB,MAAMC,YAAYA,GAAG;AACrB,MAAMC,YAAYA,GAAG;AAErB,MAAMC,qBAAqBA,GAAGf,iBAAiB,CAAC,UAC9CgB,cAAmB,EACnBC,YAAoB;IAEpB,MAAMC,OAAO,OAAOhB,SAAS;IAE7B,MAAMiB,kBAAkB,OAAOD,KAAK,WAAW,CAACF,gBAAgB,IAAI,CAClEhB,eAAe,CACb,CAACoB,QACC,IAAIT,eAAeA,CAAC;YAClB,SAAS,CAAC,6CAA6C,EAAEK,eAAe,IAAI,CAAC,gBAAgB,CAAC;YAC9FI;QACF;IAIN,OAAOF,KAAK,OAAO,CAACA,KAAK,OAAO,CAACC,kBAAkBF;AACrD;AAEO,MAAMI,uBAAuBA,GAAGrB,iBAAiB,CAAC,UAAW,EAClEsB,IAAI,EACJN,iBAAiB,IAAIO,IAAI,YAAY,GAAG,CAAC,EACV;IAC/B,MAAML,OAAO,OAAOhB,SAAS;IAC7B,MAAMsB,kBAAkBN,KAAK,OAAO,CAACI;IACrC,MAAMG,kBAAkBP,KAAK,OAAO,CAACM,iBAAiBpB,oBAAoBA;IAC1E,MAAMsB,cAAc,OAAOX,qBAAqBA,CAACC,gBAAgBJ,eAAeA;IAChF,MAAMe,WAAW,OAAOZ,qBAAqBA,CAACC,gBAAgBH,YAAYA;IAC1E,MAAMe,WAAW,OAAOb,qBAAqBA,CAACC,gBAAgBF,YAAYA;IAC1E,MAAMe,UAAU;QACd,aAAaJ;QACb,QAAQC;QACR,KAAKC;QACL,KAAKC;IACP;IAEA,OAAO;QAAEJ;QAAiBK;IAAQ;AACpC,GAAG;AAEI,MAAMC,KAAKA,GAAG9B,SAAS,CAAC,qBAAqB,UAAW+B,OAAqB;IAClF,MAAM,EAAEP,eAAe,EAAEK,OAAO,EAAE,GAAG,OAAOR,uBAAuBA,CAACU;IACpE,MAAMC,SAAS,OAAOxB,MAAMA;IAE5B,OAAOwB,OAAO,KAAK,CAACvB,qBAAqBA,CAACe,iBAAiBK;AAC7D,GAAG;AAEI,MAAMI,gBAAgBA,GAAGjC,SAAS,CAAC,+BAA+B,UACvE+B,OAAmE;IAEnE,OAAOD,KAAKA,CAACC,SAAS,IAAI,CAAC/B,cAAc,CAACQ,YAAY,GAAGR,aAAa;IACtE,IAAIC,aAAa,CAAC8B,QAAQ,OAAO,GAAG;QAClC,MAAMb,OAAO,OAAOhB,SAAS;QAC7B,MAAMoB,OAAOJ,KAAK,OAAO,CAACa,QAAQ,IAAI;QACtC,OAAOxB,kBAAkBA,CAACwB,QAAQ,OAAO,CAAC,KAAK,EAAE;YAC/CT;YACA,WAAWJ,KAAK,IAAI,CAACI,MAAMjB,4CAA4C;YACvE,WAAWa,KAAK,IAAI,CAACI,MAAMjB,4CAA4C;YACvE,WAAWa,KAAK,IAAI,CAACI,MAAMhB,eAAeA;QAC5C;IACF;IACA,OAAON,cAAc,CAAC,GAAGU,cAAc,CAAC,KAAK,6BAA6B,CAAC;AAC7E,GAAG"}
@@ -0,0 +1,10 @@
1
+ import { Effect, Path, Schema } from 'effect';
2
+ import type { BuildContext } from './hook.js';
3
+ declare const DeploymentBuildError_base: Schema.Class<DeploymentBuildError, Schema.TaggedStruct<"DeploymentBuildError", {
4
+ readonly message: Schema.String;
5
+ readonly cause: Schema.Defect;
6
+ }>, import("effect/Cause").YieldableError>;
7
+ export declare class DeploymentBuildError extends DeploymentBuildError_base {
8
+ }
9
+ export declare const runDeploymentBuild: (name: string, context: BuildContext) => Effect.Effect<void, DeploymentBuildError, Path.Path>;
10
+ export {};
@@ -0,0 +1,59 @@
1
+ import { Duration, Effect, Path, Predicate, Schema } from "effect";
2
+ import { Terminal, formatDuration } from "./terminal.js";
3
+
4
+
5
+
6
+
7
+
8
+ class DeploymentBuildError extends Schema.TaggedError()('DeploymentBuildError', {
9
+ message: Schema.String,
10
+ cause: Schema.Defect()
11
+ }) {
12
+ }
13
+ const decodeHookModule = Schema.decodeUnknownEffect(Schema.Struct({
14
+ build: Schema.declare((input)=>Predicate.isFunction(input))
15
+ }));
16
+ const runDeploymentBuild = Effect.fn('ersc/build/runDeploymentBuild')(function*(name, context) {
17
+ const path = yield* Path.Path;
18
+ yield* Effect.logInfo(`${Terminal.cyan('●')} Building deployment with ${name}...`);
19
+ const [duration] = yield* Effect.gen(function*() {
20
+ const entry = yield* Effect["try"]({
21
+ try: ()=>Bun.resolveSync(`${name}/build`, context.root),
22
+ catch: (cause)=>new DeploymentBuildError({
23
+ message: `Cannot resolve ${name}'s build hook.`,
24
+ cause
25
+ })
26
+ });
27
+ const url = yield* path.toFileUrl(entry);
28
+ const loaded = yield* Effect.tryPromise({
29
+ try: ()=>import(url.href),
30
+ catch: (cause)=>new DeploymentBuildError({
31
+ message: `Cannot load ${name}'s build hook.`,
32
+ cause
33
+ })
34
+ });
35
+ const module = yield* decodeHookModule(loaded);
36
+ const buildEffect = yield* Effect["try"]({
37
+ try: ()=>module.build(context),
38
+ catch: (cause)=>new DeploymentBuildError({
39
+ message: `${name}'s build hook threw.`,
40
+ cause
41
+ })
42
+ });
43
+ if (!Effect.isEffect(buildEffect)) {
44
+ return yield* new DeploymentBuildError({
45
+ message: `${name}'s build hook must return an Effect.`,
46
+ cause: buildEffect
47
+ });
48
+ }
49
+ yield* buildEffect;
50
+ }).pipe(Effect.mapError((cause)=>new DeploymentBuildError({
51
+ message: `Deployment build ${name} failed.`,
52
+ cause
53
+ })), Effect.scoped, Effect.timed);
54
+ yield* Effect.logInfo(`${Terminal.green('✓')} Deployment built with ${name} in ${formatDuration(Math.round(Duration.toMillis(duration)))}.`);
55
+ });
56
+
57
+ export { DeploymentBuildError, runDeploymentBuild };
58
+
59
+ //# sourceMappingURL=deployment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build/deployment.js","sources":["../../src/build/deployment.ts"],"sourcesContent":["import { Duration, Effect, Path, Predicate, Schema } from 'effect';\n\nimport type { BuildContext, BuildHook } from './hook';\nimport { formatDuration, Terminal } from './terminal';\n\nexport class DeploymentBuildError extends Schema.TaggedError<DeploymentBuildError>()(\n 'DeploymentBuildError',\n {\n message: Schema.String,\n cause: Schema.Defect(),\n },\n) {}\n\nconst decodeHookModule = Schema.decodeUnknownEffect(\n Schema.Struct({\n build: Schema.declare((input): input is BuildHook => Predicate.isFunction(input)),\n }),\n);\n\nexport const runDeploymentBuild = Effect.fn('ersc/build/runDeploymentBuild')(function* (\n name: string,\n context: BuildContext,\n) {\n const path = yield* Path.Path;\n\n yield* Effect.logInfo(`${Terminal.cyan('●')} Building deployment with ${name}...`);\n const [duration] = yield* Effect.gen(function* () {\n const entry = yield* Effect.try({\n try: () => Bun.resolveSync(`${name}/build`, context.root),\n catch: (cause) =>\n new DeploymentBuildError({ message: `Cannot resolve ${name}'s build hook.`, cause }),\n });\n const url = yield* path.toFileUrl(entry);\n const loaded = yield* Effect.tryPromise({\n try: (): Promise<unknown> => import(url.href),\n catch: (cause) =>\n new DeploymentBuildError({ message: `Cannot load ${name}'s build hook.`, cause }),\n });\n const module = yield* decodeHookModule(loaded);\n const buildEffect = yield* Effect.try({\n try: () => module.build(context),\n catch: (cause) => new DeploymentBuildError({ message: `${name}'s build hook threw.`, cause }),\n });\n if (!Effect.isEffect(buildEffect)) {\n return yield* new DeploymentBuildError({\n message: `${name}'s build hook must return an Effect.`,\n cause: buildEffect,\n });\n }\n yield* buildEffect;\n }).pipe(\n Effect.mapError(\n (cause) => new DeploymentBuildError({ message: `Deployment build ${name} failed.`, cause }),\n ),\n Effect.scoped,\n Effect.timed,\n );\n yield* Effect.logInfo(\n `${Terminal.green('✓')} Deployment built with ${name} in ${formatDuration(Math.round(Duration.toMillis(duration)))}.`,\n );\n});\n"],"names":["Duration","Effect","Path","Predicate","Schema","formatDuration","Terminal","DeploymentBuildError","decodeHookModule","input","runDeploymentBuild","name","context","path","duration","entry","Bun","cause","url","loaded","module","buildEffect","Math"],"mappings":";;;;;AAAmE;AAGb;AAE/C,MAAMO,oBAAoBA,SAASH,kBAAkB,GAC1D,wBACA;IACE,SAASA,aAAa;IACtB,OAAOA,aAAa;AACtB;AACC;AAEH,MAAMI,gBAAgBA,GAAGJ,0BAA0B,CACjDA,aAAa,CAAC;IACZ,OAAOA,cAAc,CAAC,CAACK,QAA8BN,oBAAoB,CAACM;AAC5E;AAGK,MAAMC,kBAAkBA,GAAGT,SAAS,CAAC,iCAAiC,UAC3EU,IAAY,EACZC,OAAqB;IAErB,MAAMC,OAAO,OAAOX,SAAS;IAE7B,OAAOD,cAAc,CAAC,GAAGK,aAAa,CAAC,KAAK,0BAA0B,EAAEK,KAAK,GAAG,CAAC;IACjF,MAAM,CAACG,SAAS,GAAG,OAAOb,UAAU,CAAC;QACnC,MAAMc,QAAQ,OAAOd,aAAU,CAAC;YAC9B,KAAK,IAAMe,IAAI,WAAW,CAAC,GAAGL,KAAK,MAAM,CAAC,EAAEC,QAAQ,IAAI;YACxD,OAAO,CAACK,QACN,IAAIV,oBAAoBA,CAAC;oBAAE,SAAS,CAAC,eAAe,EAAEI,KAAK,cAAc,CAAC;oBAAEM;gBAAM;QACtF;QACA,MAAMC,MAAM,OAAOL,KAAK,SAAS,CAACE;QAClC,MAAMI,SAAS,OAAOlB,iBAAiB,CAAC;YACtC,KAAK,IAAwB,MAAM,CAACiB,IAAI,IAAI;YAC5C,OAAO,CAACD,QACN,IAAIV,oBAAoBA,CAAC;oBAAE,SAAS,CAAC,YAAY,EAAEI,KAAK,cAAc,CAAC;oBAAEM;gBAAM;QACnF;QACA,MAAMG,SAAS,OAAOZ,gBAAgBA,CAACW;QACvC,MAAME,cAAc,OAAOpB,aAAU,CAAC;YACpC,KAAK,IAAMmB,OAAO,KAAK,CAACR;YACxB,OAAO,CAACK,QAAU,IAAIV,oBAAoBA,CAAC;oBAAE,SAAS,GAAGI,KAAK,oBAAoB,CAAC;oBAAEM;gBAAM;QAC7F;QACA,IAAI,CAAChB,eAAe,CAACoB,cAAc;YACjC,OAAO,OAAO,IAAId,oBAAoBA,CAAC;gBACrC,SAAS,GAAGI,KAAK,oCAAoC,CAAC;gBACtD,OAAOU;YACT;QACF;QACA,OAAOA;IACT,GAAG,IAAI,CACLpB,eAAe,CACb,CAACgB,QAAU,IAAIV,oBAAoBA,CAAC;YAAE,SAAS,CAAC,iBAAiB,EAAEI,KAAK,QAAQ,CAAC;YAAEM;QAAM,KAE3FhB,aAAa,EACbA,YAAY;IAEd,OAAOA,cAAc,CACnB,GAAGK,cAAc,CAAC,KAAK,uBAAuB,EAAEK,KAAK,IAAI,EAAEN,cAAcA,CAACiB,KAAK,KAAK,CAACtB,iBAAiB,CAACc,YAAY,CAAC,CAAC;AAEzH,GAAG"}
@@ -0,0 +1,8 @@
1
+ import type { Effect, Scope } from 'effect';
2
+ export type BuildContext = {
3
+ readonly root: string;
4
+ readonly serverDir: string;
5
+ readonly clientDir: string;
6
+ readonly publicDir: string;
7
+ };
8
+ export type BuildHook = (context: BuildContext) => Effect.Effect<void, Error, Scope.Scope>;
@@ -0,0 +1,5 @@
1
+
2
+
3
+ export {};
4
+
5
+ //# sourceMappingURL=hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build/hook.js","sources":["../../src/build/hook.ts"],"sourcesContent":["import type { Effect, Scope } from 'effect';\n\nexport type BuildContext = {\n readonly root: string;\n readonly serverDir: string;\n readonly clientDir: string;\n readonly publicDir: string;\n};\n\nexport type BuildHook = (context: BuildContext) => Effect.Effect<void, Error, Scope.Scope>;\n"],"names":[],"mappings":"AAS2F"}
@@ -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,10 +45,14 @@ 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));
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));
67
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));
68
57
  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({
69
58
  minimum: 1,
@@ -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.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 }) =>\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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"}
@@ -1,6 +1,7 @@
1
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
1
+ import { jsx } from "react/jsx-runtime";
2
2
  import { Context, Effect, FiberSet, Layer, Schema } from "effect";
3
3
  import { use } from "react";
4
+ import { preinit } from "react-dom";
4
5
  import { renderToReadableStream } from "react-dom/server.bun";
5
6
  import { createFromReadableStream } from "react-server-dom-rspack/client";
6
7
  import { RouteTree } from "../client/route-tree.js";
@@ -23,6 +24,8 @@ import { ServerConfig } from "./server-config.js";
23
24
 
24
25
 
25
26
 
27
+
28
+
26
29
  class HtmlRenderError extends Schema.TaggedError()('HtmlRenderError', {
27
30
  cause: Schema.Defect()
28
31
  }) {
@@ -38,22 +41,20 @@ class HtmlRenderer extends Context.Service()('ersc/server/html-renderer/HtmlRend
38
41
  const [ssrFlightStream, browserFlightStream] = flight.stream.tee();
39
42
  let payload = null;
40
43
  function SsrRoot() {
44
+ // Emit CSS without server-only siblings that shift hydration's useId paths.
45
+ for (const href of clientStylesheets){
46
+ preinit(href, {
47
+ as: 'style',
48
+ precedence: 'default'
49
+ });
50
+ }
41
51
  const { routeTree } = use(payload ??= createFromReadableStream(ssrFlightStream));
42
52
  return /*#__PURE__*/ jsx(RouteTree, {
43
53
  root: routeTree
44
54
  });
45
55
  }
46
56
  const htmlStream = yield* Effect.tryPromise({
47
- try: ()=>renderToReadableStream(/*#__PURE__*/ jsxs(Fragment, {
48
- children: [
49
- clientStylesheets.map((href)=>/*#__PURE__*/ jsx("link", {
50
- rel: "stylesheet",
51
- href: href,
52
- precedence: "default"
53
- }, href)),
54
- /*#__PURE__*/ jsx(SsrRoot, {})
55
- ]
56
- }), {
57
+ try: ()=>renderToReadableStream(/*#__PURE__*/ jsx(SsrRoot, {}), {
57
58
  bootstrapScripts: [
58
59
  ...clientBootstrapScripts
59
60
  ],
@@ -1 +1 @@
1
- {"version":3,"file":"server/html-renderer.js","sources":["../../src/server/html-renderer.tsx"],"sourcesContent":["import { Context, Effect, FiberSet, Layer, Schema, type Scope } from 'effect';\nimport { use } from 'react';\nimport { renderToReadableStream } from 'react-dom/server.bun';\nimport { createFromReadableStream } from 'react-server-dom-rspack/client';\n\nimport { RouteTree } from '../client/route-tree';\nimport type { FlightPayload } from '../rsc/flight';\nimport { FlightHtmlInjector } from './flight-html-stream';\nimport type { FlightRender } from './flight-renderer';\nimport { ServerConfig } from './server-config';\n\ntype HtmlStream = ReadableStream<Uint8Array>;\n\nexport class HtmlRenderError extends Schema.TaggedError<HtmlRenderError>()('HtmlRenderError', {\n cause: Schema.Defect(),\n}) {}\n\nexport class HtmlRenderer extends Context.Service<HtmlRenderer>()(\n 'ersc/server/html-renderer/HtmlRenderer',\n {\n make: Effect.gen(function* () {\n const { clientBootstrapScripts, clientStylesheets } = yield* ServerConfig;\n const flightHtmlInjector = yield* FlightHtmlInjector;\n\n return {\n render: Effect.fn('HtmlRenderer.render')(function* ({\n flight,\n formState,\n }: {\n readonly flight: FlightRender;\n readonly formState: FlightPayload['formState'];\n }): Effect.fn.Return<HtmlStream, HtmlRenderError, Scope.Scope> {\n const signal = yield* Effect.abortSignal;\n const runtime = yield* FiberSet.makeRuntimePromise<never>();\n const [ssrFlightStream, browserFlightStream] = flight.stream.tee();\n let payload: PromiseLike<FlightPayload> | null = null;\n\n function SsrRoot() {\n const { routeTree } = use(\n (payload ??= createFromReadableStream<FlightPayload>(ssrFlightStream)),\n );\n return <RouteTree root={routeTree} />;\n }\n\n const htmlStream = yield* Effect.tryPromise({\n try: () =>\n renderToReadableStream(\n <>\n {clientStylesheets.map((href) => (\n <link key={href} rel='stylesheet' href={href} precedence='default' />\n ))}\n <SsrRoot />\n </>,\n {\n bootstrapScripts: [...clientBootstrapScripts],\n formState,\n onError: (error, errorInfo) => {\n if (!signal.aborted && !flight.signal.aborted) {\n void runtime(\n Effect.logError('HTML render failed.', error, errorInfo.componentStack),\n );\n }\n },\n signal,\n },\n ),\n catch: (cause) => new HtmlRenderError({ cause }),\n });\n\n return htmlStream.pipeThrough(flightHtmlInjector.inject(browserFlightStream));\n }),\n };\n }),\n },\n) {\n static readonly layer = Layer.effect(this, this.make);\n}\n"],"names":["Context","Effect","FiberSet","Layer","Schema","use","renderToReadableStream","createFromReadableStream","RouteTree","FlightHtmlInjector","ServerConfig","HtmlRenderError","HtmlRenderer","clientBootstrapScripts","clientStylesheets","flightHtmlInjector","flight","formState","signal","runtime","ssrFlightStream","browserFlightStream","payload","SsrRoot","routeTree","htmlStream","href","error","errorInfo","cause"],"mappings":";;;;;;;;;;;;;;;;;;AAA8E;AAClD;AACkC;AACY;AAEzB;AAES;AAEX;AAIxC,MAAMW,eAAeA,SAASP,kBAAkB,GAAoB,mBAAmB;IAC5F,OAAOA,aAAa;AACtB;AAAI;AAEG,MAAMQ,YAAYA,SAASZ,eAAe,GAC/C,0CACA;IACE,MAAMC,UAAU,CAAC;QACf,MAAM,EAAEY,sBAAsB,EAAEC,iBAAiB,EAAE,GAAG,OAAOJ,YAAYA;QACzE,MAAMK,qBAAqB,OAAON,kBAAkBA;QAEpD,OAAO;YACL,QAAQR,SAAS,CAAC,uBAAuB,UAAW,EAClDe,MAAM,EACNC,SAAS,EAIV;gBACC,MAAMC,SAAS,OAAOjB,kBAAkB;gBACxC,MAAMkB,UAAU,OAAOjB,2BAA2B;gBAClD,MAAM,CAACkB,iBAAiBC,oBAAoB,GAAGL,OAAO,MAAM,CAAC,GAAG;gBAChE,IAAIM,UAA6C;gBAEjD,SAASC;oBACP,MAAM,EAAEC,SAAS,EAAE,GAAGnB,GAAGA,CACtBiB,YAAYf,wBAAwBA,CAAgBa;oBAEvD,qBAAO,IAACZ,SAASA;wBAAC,MAAMgB;;gBAC1B;gBAEA,MAAMC,aAAa,OAAOxB,iBAAiB,CAAC;oBAC1C,KAAK,IACHK,sBAAsBA,eACpB;;gCACGQ,kBAAkB,GAAG,CAAC,CAACY,qBACtB,IAAC;wCAAgB,KAAI;wCAAa,MAAMA;wCAAM,YAAW;uCAA9CA;8CAEb,IAACH;;4BAEH;4BACE,kBAAkB;mCAAIV;6BAAuB;4BAC7CI;4BACA,SAAS,CAACU,OAAOC;gCACf,IAAI,CAACV,OAAO,OAAO,IAAI,CAACF,OAAO,MAAM,CAAC,OAAO,EAAE;oCAC7C,KAAKG,QACHlB,eAAe,CAAC,uBAAuB0B,OAAOC,UAAU,cAAc;gCAE1E;4BACF;4BACAV;wBACF;oBAEJ,OAAO,CAACW,QAAU,IAAIlB,eAAeA,CAAC;4BAAEkB;wBAAM;gBAChD;gBAEA,OAAOJ,WAAW,WAAW,CAACV,mBAAmB,MAAM,CAACM;YAC1D;QACF;IACF;AACF;IAEA,OAAgB,QAAQlB,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;AACxD"}
1
+ {"version":3,"file":"server/html-renderer.js","sources":["../../src/server/html-renderer.tsx"],"sourcesContent":["import { Context, Effect, FiberSet, Layer, Schema, type Scope } from 'effect';\nimport { use } from 'react';\nimport { preinit } from 'react-dom';\nimport { renderToReadableStream } from 'react-dom/server.bun';\nimport { createFromReadableStream } from 'react-server-dom-rspack/client';\n\nimport { RouteTree } from '../client/route-tree';\nimport type { FlightPayload } from '../rsc/flight';\nimport { FlightHtmlInjector } from './flight-html-stream';\nimport type { FlightRender } from './flight-renderer';\nimport { ServerConfig } from './server-config';\n\ntype HtmlStream = ReadableStream<Uint8Array>;\n\nexport class HtmlRenderError extends Schema.TaggedError<HtmlRenderError>()('HtmlRenderError', {\n cause: Schema.Defect(),\n}) {}\n\nexport class HtmlRenderer extends Context.Service<HtmlRenderer>()(\n 'ersc/server/html-renderer/HtmlRenderer',\n {\n make: Effect.gen(function* () {\n const { clientBootstrapScripts, clientStylesheets } = yield* ServerConfig;\n const flightHtmlInjector = yield* FlightHtmlInjector;\n\n return {\n render: Effect.fn('HtmlRenderer.render')(function* ({\n flight,\n formState,\n }: {\n readonly flight: FlightRender;\n readonly formState: FlightPayload['formState'];\n }): Effect.fn.Return<HtmlStream, HtmlRenderError, Scope.Scope> {\n const signal = yield* Effect.abortSignal;\n const runtime = yield* FiberSet.makeRuntimePromise<never>();\n const [ssrFlightStream, browserFlightStream] = flight.stream.tee();\n let payload: PromiseLike<FlightPayload> | null = null;\n\n function SsrRoot() {\n // Emit CSS without server-only siblings that shift hydration's useId paths.\n for (const href of clientStylesheets) {\n preinit(href, { as: 'style', precedence: 'default' });\n }\n const { routeTree } = use(\n (payload ??= createFromReadableStream<FlightPayload>(ssrFlightStream)),\n );\n return <RouteTree root={routeTree} />;\n }\n\n const htmlStream = yield* Effect.tryPromise({\n try: () =>\n renderToReadableStream(<SsrRoot />, {\n bootstrapScripts: [...clientBootstrapScripts],\n formState,\n onError: (error, errorInfo) => {\n if (!signal.aborted && !flight.signal.aborted) {\n void runtime(\n Effect.logError('HTML render failed.', error, errorInfo.componentStack),\n );\n }\n },\n signal,\n }),\n catch: (cause) => new HtmlRenderError({ cause }),\n });\n\n return htmlStream.pipeThrough(flightHtmlInjector.inject(browserFlightStream));\n }),\n };\n }),\n },\n) {\n static readonly layer = Layer.effect(this, this.make);\n}\n"],"names":["Context","Effect","FiberSet","Layer","Schema","use","preinit","renderToReadableStream","createFromReadableStream","RouteTree","FlightHtmlInjector","ServerConfig","HtmlRenderError","HtmlRenderer","clientBootstrapScripts","clientStylesheets","flightHtmlInjector","flight","formState","signal","runtime","ssrFlightStream","browserFlightStream","payload","SsrRoot","href","routeTree","htmlStream","error","errorInfo","cause"],"mappings":";;;;;;;;;;;;;;;;;;;;AAA8E;AAClD;AACQ;AAC0B;AACY;AAEzB;AAES;AAEX;AAIxC,MAAMY,eAAeA,SAASR,kBAAkB,GAAoB,mBAAmB;IAC5F,OAAOA,aAAa;AACtB;AAAI;AAEG,MAAMS,YAAYA,SAASb,eAAe,GAC/C,0CACA;IACE,MAAMC,UAAU,CAAC;QACf,MAAM,EAAEa,sBAAsB,EAAEC,iBAAiB,EAAE,GAAG,OAAOJ,YAAYA;QACzE,MAAMK,qBAAqB,OAAON,kBAAkBA;QAEpD,OAAO;YACL,QAAQT,SAAS,CAAC,uBAAuB,UAAW,EAClDgB,MAAM,EACNC,SAAS,EAIV;gBACC,MAAMC,SAAS,OAAOlB,kBAAkB;gBACxC,MAAMmB,UAAU,OAAOlB,2BAA2B;gBAClD,MAAM,CAACmB,iBAAiBC,oBAAoB,GAAGL,OAAO,MAAM,CAAC,GAAG;gBAChE,IAAIM,UAA6C;gBAEjD,SAASC;oBACP,4EAA4E;oBAC5E,KAAK,MAAMC,QAAQV,kBAAmB;wBACpCT,OAAOA,CAACmB,MAAM;4BAAE,IAAI;4BAAS,YAAY;wBAAU;oBACrD;oBACA,MAAM,EAAEC,SAAS,EAAE,GAAGrB,GAAGA,CACtBkB,YAAYf,wBAAwBA,CAAgBa;oBAEvD,qBAAO,IAACZ,SAASA;wBAAC,MAAMiB;;gBAC1B;gBAEA,MAAMC,aAAa,OAAO1B,iBAAiB,CAAC;oBAC1C,KAAK,IACHM,sBAAsBA,eAAC,IAACiB,cAAY;4BAClC,kBAAkB;mCAAIV;6BAAuB;4BAC7CI;4BACA,SAAS,CAACU,OAAOC;gCACf,IAAI,CAACV,OAAO,OAAO,IAAI,CAACF,OAAO,MAAM,CAAC,OAAO,EAAE;oCAC7C,KAAKG,QACHnB,eAAe,CAAC,uBAAuB2B,OAAOC,UAAU,cAAc;gCAE1E;4BACF;4BACAV;wBACF;oBACF,OAAO,CAACW,QAAU,IAAIlB,eAAeA,CAAC;4BAAEkB;wBAAM;gBAChD;gBAEA,OAAOH,WAAW,WAAW,CAACX,mBAAmB,MAAM,CAACM;YAC1D;QACF;IACF;AACF;IAEA,OAAgB,QAAQnB,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;AACxD"}
@@ -0,0 +1,7 @@
1
+ import { Effect } from 'effect';
2
+ export type StartOptions = {
3
+ readonly hostname: string;
4
+ readonly port: number;
5
+ readonly root: string;
6
+ };
7
+ export declare const serve: (options: StartOptions) => Effect.Effect<void, import("../build/compiled-server.js").CompiledServerError | import("effect/Types").unhandled, import("effect/Scope").Scope>;
@@ -0,0 +1,31 @@
1
+ import { Effect, Layer } from "effect";
2
+ import { loadCompiledServer, makeRunnableServerLayer } from "../build/compiled-server.js";
3
+ import { EnvironmentConfig } from "../build/contract.js";
4
+
5
+ import * as __rspack_external__effect_platform_bun_BunServices_112addf2 from "@effect/platform-bun/BunServices";
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+ const resolveServerLayer = Effect.fnUntraced(function*({ hostname, port, root }) {
15
+ const bundle = yield* loadCompiledServer(root);
16
+ return yield* makeRunnableServerLayer({
17
+ bundle,
18
+ clientAssetsCacheControl: EnvironmentConfig.production.clientAssetsCacheControl,
19
+ clientOutputDir: EnvironmentConfig.production.clientOutputDir,
20
+ hostname,
21
+ port,
22
+ root
23
+ });
24
+ });
25
+ const serve = Effect.fn('ersc/server/serve')(function*(options) {
26
+ yield* Layer.build(Layer.unwrap(resolveServerLayer(options)).pipe(Layer.provide(__rspack_external__effect_platform_bun_BunServices_112addf2.layer)));
27
+ });
28
+
29
+ export { serve };
30
+
31
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server/serve.js","sources":["../../src/server/serve.ts"],"sourcesContent":["import * as BunServices from '@effect/platform-bun/BunServices';\nimport { Effect, Layer } from 'effect';\n\nimport { loadCompiledServer, makeRunnableServerLayer } from '../build/compiled-server';\nimport { EnvironmentConfig } from '../build/contract';\n\nexport type StartOptions = {\n readonly hostname: string;\n readonly port: number;\n readonly root: string;\n};\n\nconst resolveServerLayer = Effect.fnUntraced(function* ({ hostname, port, root }: StartOptions) {\n const bundle = yield* loadCompiledServer(root);\n return yield* makeRunnableServerLayer({\n bundle,\n clientAssetsCacheControl: EnvironmentConfig.production.clientAssetsCacheControl,\n clientOutputDir: EnvironmentConfig.production.clientOutputDir,\n hostname,\n port,\n root,\n });\n});\n\nexport const serve = Effect.fn('ersc/server/serve')(function* (options: StartOptions) {\n yield* Layer.build(\n Layer.unwrap(resolveServerLayer(options)).pipe(Layer.provide(BunServices.layer)),\n );\n});\n"],"names":["BunServices","Effect","Layer","loadCompiledServer","makeRunnableServerLayer","EnvironmentConfig","resolveServerLayer","hostname","port","root","bundle","serve","options"],"mappings":";;;;;;;;;AAAgE;AACzB;AAEgD;AACjC;AAQtD,MAAMM,kBAAkBA,GAAGL,iBAAiB,CAAC,UAAW,EAAEM,QAAQ,EAAEC,IAAI,EAAEC,IAAI,EAAgB;IAC5F,MAAMC,SAAS,OAAOP,kBAAkBA,CAACM;IACzC,OAAO,OAAOL,uBAAuBA,CAAC;QACpCM;QACA,0BAA0BL,qDAAqD;QAC/E,iBAAiBA,4CAA4C;QAC7DE;QACAC;QACAC;IACF;AACF;AAEO,MAAME,KAAKA,GAAGV,SAAS,CAAC,qBAAqB,UAAWW,OAAqB;IAClF,OAAOV,WAAW,CAChBA,YAAY,CAACI,kBAAkBA,CAACM,UAAU,IAAI,CAACV,aAAa,CAACF,iEAAiB;AAElF,GAAG"}
@@ -0,0 +1,3 @@
1
+ import { type StartOptions } from './serve.js';
2
+ export type { StartOptions } from './serve.js';
3
+ export declare const start: (options: StartOptions) => Promise<void>;
@@ -0,0 +1,24 @@
1
+ import { Deferred, Effect, Runtime } from "effect";
2
+ import { serve } from "./serve.js";
3
+
4
+ import * as __rspack_external__effect_platform_bun_BunRuntime_e8fbdd23 from "@effect/platform-bun/BunRuntime";
5
+
6
+
7
+
8
+
9
+
10
+
11
+ const start = (options)=>{
12
+ const ready = Deferred.makeUnsafe();
13
+ __rspack_external__effect_platform_bun_BunRuntime_e8fbdd23.runMain(serve(options).pipe(Effect.tap(()=>Deferred.succeed(ready, undefined)), Effect.andThen(Effect.never), Effect.scoped, Effect.onExit((exit)=>Deferred.done(ready, exit))), {
14
+ // Let the caller observe readiness rejection before runMain exits the process.
15
+ teardown: (exit, onExit)=>{
16
+ setImmediate(()=>Runtime.defaultTeardown(exit, onExit));
17
+ }
18
+ });
19
+ return Effect.runPromise(Deferred["await"](ready));
20
+ };
21
+
22
+ export { start };
23
+
24
+ //# sourceMappingURL=start.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server/start.js","sources":["../../src/server/start.ts"],"sourcesContent":["import * as BunRuntime from '@effect/platform-bun/BunRuntime';\nimport { Deferred, Effect, Runtime } from 'effect';\n\nimport { serve, type StartOptions } from './serve';\n\nexport type { StartOptions } from './serve';\n\nexport const start = (options: StartOptions): Promise<void> => {\n const ready = Deferred.makeUnsafe<void, Effect.Error<ReturnType<typeof serve>>>();\n\n BunRuntime.runMain(\n serve(options).pipe(\n Effect.tap(() => Deferred.succeed(ready, undefined)),\n Effect.andThen(Effect.never),\n Effect.scoped,\n Effect.onExit((exit) => Deferred.done(ready, exit)),\n ),\n {\n // Let the caller observe readiness rejection before runMain exits the process.\n teardown: (exit, onExit) => {\n setImmediate(() => Runtime.defaultTeardown(exit, onExit));\n },\n },\n );\n\n return Effect.runPromise(Deferred.await(ready));\n};\n"],"names":["BunRuntime","Deferred","Effect","Runtime","serve","start","options","ready","undefined","exit","onExit","setImmediate"],"mappings":";;;;;;;AAA8D;AACX;AAEA;AAI5C,MAAMK,KAAKA,GAAG,CAACC;IACpB,MAAMC,QAAQN,mBAAmB;IAEjCD,kEAAkB,CAChBI,KAAKA,CAACE,SAAS,IAAI,CACjBJ,UAAU,CAAC,IAAMD,gBAAgB,CAACM,OAAOC,aACzCN,cAAc,CAACA,YAAY,GAC3BA,aAAa,EACbA,aAAa,CAAC,CAACO,OAASR,aAAa,CAACM,OAAOE,SAE/C;QACE,+EAA+E;QAC/E,UAAU,CAACA,MAAMC;YACfC,aAAa,IAAMR,uBAAuB,CAACM,MAAMC;QACnD;IACF;IAGF,OAAOR,iBAAiB,CAACD,iBAAc,CAACM;AAC1C,EAAE"}
@@ -0,0 +1,34 @@
1
+ ### Deploying to Vercel
2
+
3
+ Deploy to Vercel with Bun 1.4+. Match the adapter version to `effective-rsc`.
4
+
5
+ ```sh
6
+ bun add --dev @ersc/vercel
7
+ ```
8
+
9
+ Set the build script in `package.json`:
10
+
11
+ ```json
12
+ {
13
+ "scripts": {
14
+ "build": "ersc build --adapter @ersc/vercel"
15
+ }
16
+ }
17
+ ```
18
+
19
+ Commit `bun.lock`, connect your GitHub repository in Vercel, and set:
20
+
21
+ | Setting | Value |
22
+ | ---------------- | ------------------------------- |
23
+ | Framework Preset | Other |
24
+ | Root Directory | Application directory |
25
+ | Install Command | `bun install --frozen-lockfile` |
26
+ | Build Command | `bun run --bun build` |
27
+ | Output Directory | Leave the override disabled |
28
+
29
+ Add your environment variables and deploy. The adapter generates `.vercel/output/`; no custom
30
+ server entry or `vercel.json` is needed.
31
+
32
+ For [monorepos](https://vercel.com/docs/monorepos/monorepo-faq), enable **Include source files outside
33
+ of the Root Directory in the Build Step**. With Turborepo, use
34
+ `bun run --bun turbo run build --filter=your-app` to build the app and its workspace dependencies.
@@ -9,3 +9,4 @@ Familiarity with React Server Components and Effect is assumed.
9
9
  - [Routing](./03-routing/index.md)
10
10
  - [Middleware](./04-middleware/index.md)
11
11
  - [Userland HTTP](./05-http/index.md)
12
+ - [Deploying to Vercel](./06-deploying-to-vercel/index.md)
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @title Server entry
3
+ * Save this as `server.ts` in the application root and run it with `bun server.ts` after building.
4
+ */
5
+ import { start } from 'effective-rsc/server';
6
+
7
+ await start({
8
+ hostname: 'localhost',
9
+ port: 18193,
10
+ root: import.meta.dir,
11
+ });
@@ -0,0 +1,22 @@
1
+ ## Production startup
2
+
3
+ Run `ersc build`, then `ersc start`. A custom Bun entry can await
4
+ `start({ root, hostname, port })` from `effective-rsc/server`. All options are required;
5
+ `root` is the application directory. Deploy its `.ersc/`, `public/`, and runtime dependencies.
6
+
7
+ The Promise resolves when ready; startup failures reject and exit. ERSC owns signal handling
8
+ and cleanup, so do not wrap it in `BunRuntime.runMain`.
9
+
10
+ ### Deployment adapters
11
+
12
+ `ersc build --adapter <package>` runs an installed adapter after compilation; it does not upload.
13
+ Without the flag, packaging is skipped and previous output remains.
14
+
15
+ Adapters export `build: BuildHook` from `./build`, with types from `effective-rsc/build`.
16
+ The hook receives absolute `root`, `serverDir`, `clientDir`, and `publicDir` paths and returns
17
+ `Effect<void, Error, Scope>`. Inputs are read-only; adapters provide dependencies and ERSC owns
18
+ cleanup/cancellation. Failures stop the build.
19
+
20
+ <!-- source-navigation -->
21
+
22
+ - [Deploying to Vercel](../../02-guides/06-deploying-to-vercel/index.md)
@@ -9,3 +9,4 @@ before adopting them.
9
9
  - [Request runtime and lifetimes](./01-request-runtime-and-lifetimes/index.md)
10
10
  - [Client navigation](./02-client-navigation/index.md)
11
11
  - [Server Function execution and refresh](./03-server-function-execution-and-refresh/index.md)
12
+ - [Production startup](./04-production-startup/index.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "effective-rsc",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "An experimental, Effect-native React Server Components framework for Bun.",
5
5
  "keywords": [
6
6
  "bun",
@@ -37,6 +37,14 @@
37
37
  "types": "./dist/index.d.ts",
38
38
  "react-server": "./dist/index.js",
39
39
  "default": "./dist/unsupported.js"
40
+ },
41
+ "./server": {
42
+ "types": "./dist/server/start.d.ts",
43
+ "default": "./dist/server/start.js"
44
+ },
45
+ "./build": {
46
+ "types": "./dist/build/hook.d.ts",
47
+ "default": "./dist/build/hook.js"
40
48
  }
41
49
  },
42
50
  "publishConfig": {
@@ -47,7 +55,6 @@
47
55
  "docs:check": "bun ../../scripts/generate-docs.ts --check",
48
56
  "prepack": "bun run build && bun run docs:check",
49
57
  "test": "bun run --bun vitest run",
50
- "test:types": "tsc --noEmit -p tests/types/tsconfig.json",
51
58
  "test:watch": "bun run --bun vitest"
52
59
  },
53
60
  "dependencies": {