effect-orpc 0.3.0 → 0.4.0

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/README.md CHANGED
@@ -30,7 +30,7 @@ Runnable demos live in the repository's `examples/` directory.
30
30
  ```ts
31
31
  import { os } from "@orpc/server";
32
32
  import { Effect, ManagedRuntime } from "effect";
33
- import { makeEffectORPC, ORPCTaggedError } from "effect-orpc";
33
+ import { eos, makeEffectORPC, ORPCTaggedError } from "effect-orpc";
34
34
 
35
35
  interface User {
36
36
  id: number;
@@ -43,15 +43,6 @@ let users: User[] = [
43
43
  { id: 3, name: "James Dane" },
44
44
  ];
45
45
 
46
- // Authenticated os with initial context & errors set
47
- const authedOs = os
48
- .errors({ UNAUTHORIZED: { status: 401 } })
49
- .$context<{ userId?: number }>()
50
- .use(({ context, errors, next }) => {
51
- if (context.userId === undefined) throw errors.UNAUTHORIZED();
52
- return next({ context: { ...context, userId: context.userId } });
53
- });
54
-
55
46
  // Define your services
56
47
  class UsersRepo extends Effect.Service<UsersRepo>()("UsersRepo", {
57
48
  accessors: true,
@@ -65,26 +56,27 @@ class UserNotFoundError extends ORPCTaggedError("UserNotFoundError", {
65
56
  status: 404,
66
57
  }) {}
67
58
 
68
- // Create an Effect-aware oRPC builder with your service layer, optionally from
69
- // another base oRPC builder, and provide tagged errors.
70
- const effectOs = makeEffectORPC(UsersRepo.Default, authedOs).errors({
71
- UserNotFoundError,
72
- });
59
+ // Create an Effect-aware oRPC builder with your service layer, context, errors,
60
+ // and middleware.
61
+ const effectProcedure = eos
62
+ .provide(UsersRepo.Default)
63
+ .errors({ UNAUTHORIZED: { status: 401 }, UserNotFoundError })
64
+ .$context<{ userId?: number }>()
65
+ .use(({ context, errors, next }) => {
66
+ if (context.userId === undefined) throw errors.UNAUTHORIZED();
67
+ return next({ context: { ...context, userId: context.userId } });
68
+ });
73
69
 
74
- // You can also pass an explicit ManagedRuntime if you need lifecycle control:
70
+ // Use ManagedRuntime only when scoped resources should be acquired once and
71
+ // released on shutdown, for example a shared cache, database pool, or telemetry SDK:
75
72
  // const runtime = ManagedRuntime.make(UsersRepo.Default);
76
- // const effectOs = makeEffectORPC(runtime, authedOs).errors({ UserNotFoundError });
77
-
78
- // Or start with only the builder and provide the layer later:
79
- // const effectOs = makeEffectORPC(authedOs)
80
- // .provide(UsersRepo.Default)
81
- // .errors({ UserNotFoundError });
73
+ // const effectProcedure = makeEffectORPC(runtime).errors({ UserNotFoundError });
82
74
 
83
75
  // Create the router with mixed procedures
84
76
  export const router = {
85
77
  health: os.handler(() => "ok"),
86
78
  users: {
87
- me: effectOs.effect(function* ({ context: { userId } }) {
79
+ me: effectProcedure.effect(function* ({ context: { userId } }) {
88
80
  const user = yield* UsersRepo.get(userId);
89
81
  if (!user) {
90
82
  return yield* new UserNotFoundError();
@@ -103,7 +95,7 @@ The wrapper enforces that Effect procedures only use services provided by `.prov
103
95
 
104
96
  ```ts
105
97
  import { Context, Effect, Layer } from "effect";
106
- import { makeEffectORPC } from "effect-orpc";
98
+ import { eos } from "effect-orpc";
107
99
 
108
100
  class ProvidedService extends Context.Tag("ProvidedService")<
109
101
  ProvidedService,
@@ -119,16 +111,16 @@ const AppLive = Layer.succeed(ProvidedService, {
119
111
  doSomething: () => Effect.succeed("ok"),
120
112
  });
121
113
 
122
- const effectOs = makeEffectORPC(AppLive);
114
+ const effectProcedure = eos.provide(AppLive);
123
115
 
124
116
  // ✅ This compiles - ProvidedService is provided by AppLive
125
- const works = effectOs.effect(function* () {
117
+ const works = effectProcedure.effect(function* () {
126
118
  const service = yield* ProvidedService;
127
119
  return yield* service.doSomething();
128
120
  });
129
121
 
130
122
  // ❌ This fails to compile - MissingService is not provided
131
- const fails = effectOs.effect(function* () {
123
+ const fails = effectProcedure.effect(function* () {
132
124
  const service = yield* MissingService; // Type error!
133
125
  return yield* service.doSomething();
134
126
  });
@@ -145,7 +137,7 @@ const fails = effectOs.effect(function* () {
145
137
  Make sure the tagged error class is passed to the effect `.errors()` to be able to yield the error class directly and make the client recognize it as defined.
146
138
 
147
139
  ```ts
148
- const getUser = effectOs
140
+ const getUser = effectProcedure
149
141
  // Mixed error maps
150
142
  .errors({
151
143
  // Regular oRPC error
@@ -214,19 +206,19 @@ All Effect procedures are automatically traced with `Effect.withSpan`. By defaul
214
206
  const router = {
215
207
  users: {
216
208
  // Span name: "users.get"
217
- get: effectOs.input(z.object({ id: z.string() })).effect(function* ({
209
+ get: effectProcedure.input(z.object({ id: z.string() })).effect(function* ({
218
210
  input,
219
211
  }) {
220
212
  const userService = yield* UserService;
221
213
  return yield* userService.findById(input.id);
222
214
  }),
223
215
  // Span name: "users.create"
224
- create: effectOs.input(z.object({ name: z.string() })).effect(function* ({
225
- input,
226
- }) {
227
- const userService = yield* UserService;
228
- return yield* userService.create(input.name);
229
- }),
216
+ create: effectProcedure
217
+ .input(z.object({ name: z.string() }))
218
+ .effect(function* ({ input }) {
219
+ const userService = yield* UserService;
220
+ return yield* userService.create(input.name);
221
+ }),
230
222
  },
231
223
  };
232
224
  ```
@@ -234,7 +226,7 @@ const router = {
234
226
  Use `.traced()` to override the default span name:
235
227
 
236
228
  ```ts
237
- const getUser = effectOs
229
+ const getUser = effectProcedure
238
230
  .input(z.object({ id: z.string() }))
239
231
  .traced("custom.span.name") // Override the default path-based name
240
232
  .effect(function* ({ input }) {
@@ -261,7 +253,7 @@ const TracingLive = NodeSdk.layer(
261
253
 
262
254
  const AppLive = Layer.mergeAll(UserServiceLive, TracingLive);
263
255
 
264
- const effectOs = makeEffectORPC(AppLive);
256
+ const effectProcedure = eos.provide(AppLive);
265
257
  ```
266
258
 
267
259
  ### Error Stack Traces
@@ -283,7 +275,7 @@ middleware. Two patterns are supported:
283
275
  automatically (no need to call `next`):
284
276
 
285
277
  ```ts
286
- effectOs.use(function* () {
278
+ effectProcedure.use(function* () {
287
279
  const user = yield* CurrentUser;
288
280
  yield* requireActiveUser(user);
289
281
  });
@@ -293,7 +285,7 @@ effectOs.use(function* () {
293
285
  middleware that uses `return next(...)`, use `return yield* next(...)`:
294
286
 
295
287
  ```ts
296
- effectOs.use(function* ({ next }) {
288
+ effectProcedure.use(function* ({ next }) {
297
289
  const user = yield* CurrentUser;
298
290
  yield* requireActiveUser(user);
299
291
 
@@ -306,7 +298,7 @@ effectOs.use(function* ({ next }) {
306
298
  To transform the downstream output, capture `next()` and pass through `output`:
307
299
 
308
300
  ```ts
309
- effectOs.use(function* ({ next }, _input, output) {
301
+ effectProcedure.use(function* ({ next }, _input, output) {
310
302
  const result = yield* next();
311
303
  return yield* output(`${result.output}-wrapped`);
312
304
  });
@@ -323,7 +315,8 @@ Effect-native steps are `.provide(...)`, `.provideOptional(...)`, generator
323
315
  `.use(function* ...)`, and `.effect(function* ...)`.
324
316
 
325
317
  ```ts
326
- makeEffectORPC(AppLive)
318
+ eos
319
+ .provide(AppLive)
327
320
  .provide(CurrentUser, ({ context }) => Effect.succeed(context.user))
328
321
  .use(function* ({ next }) {
329
322
  const user = yield* CurrentUser;
@@ -336,13 +329,14 @@ makeEffectORPC(AppLive)
336
329
  ```
337
330
 
338
331
  The example above runs the provider, middleware, and handler inside a single
339
- internal `runtime.runPromiseExit(...)` call.
332
+ Effect execution boundary.
340
333
 
341
334
  A native oRPC middleware breaks the contiguous Effect pipeline. Pending Effect
342
335
  steps are flushed into one generated oRPC middleware before the native middleware:
343
336
 
344
337
  ```ts
345
- makeEffectORPC(AppLive)
338
+ eos
339
+ .provide(AppLive)
346
340
  .provide(CurrentUser, getCurrentUser) // Effect group #1
347
341
  .use(function* ({ next }) {
348
342
  return yield* next();
@@ -370,10 +364,11 @@ Effect group #2.
370
364
 
371
365
  Procedure-level `.provide*` after a native `.handler(...)` has no Effect handler
372
366
  boundary to attach to, so it is installed as an oRPC middleware that runs its
373
- provider Effect through the runtime:
367
+ provider Effect through the configured runtime source:
374
368
 
375
369
  ```ts
376
- makeEffectORPC(AppLive)
370
+ eos
371
+ .provide(AppLive)
377
372
  .handler(() => "ok") // native oRPC handler
378
373
  .provide(CurrentUser, getCurrentUser); // fallback provider middleware
379
374
  ```
@@ -397,10 +392,10 @@ oRPC pipeline and should be visible inside handlers:
397
392
  ```ts
398
393
  import { Hono } from "hono";
399
394
  import { Effect } from "effect";
400
- import { makeEffectORPC } from "effect-orpc";
395
+ import { eos } from "effect-orpc";
401
396
  import { withFiberContext } from "effect-orpc/node";
402
397
 
403
- const effectOs = makeEffectORPC(AppLive);
398
+ const effectProcedure = eos.provide(AppLive);
404
399
  const app = new Hono();
405
400
 
406
401
  app.use("*", async (c, next) => {
@@ -432,8 +427,8 @@ relies on `AsyncLocalStorage` from `node:async_hooks`.
432
427
 
433
428
  Use `implementEffect(contract, layerOrRuntime)` when you already have an oRPC
434
429
  contract and want to keep contract-first enforcement while adding Effect-native
435
- handlers. Use `makeEffectORPC(layerOrRuntime, builder?)` when you want to build
436
- procedures directly from an oRPC builder.
430
+ handlers. Use `eos.provide(layer)` when you want to build procedures directly
431
+ from the default Effect-aware builder.
437
432
 
438
433
  ```ts
439
434
  import { Effect } from "effect";
@@ -478,29 +473,33 @@ directly from the `ORPCTaggedError` class.
478
473
 
479
474
  ## API Reference
480
475
 
481
- ### `makeEffectORPC(layerOrRuntime, builder?)`
476
+ ### `eos`
482
477
 
483
- Creates an Effect-aware procedure builder. The recommended default is to pass
484
- your application `Layer` up front.
478
+ The default Effect-aware procedure builder. Provide your application services
479
+ with `.provide(layer)`:
485
480
 
486
- Returns an `EffectBuilder` instance.
481
+ ```ts
482
+ const effectProcedure = eos.provide(AppLive);
483
+ ```
484
+
485
+ Use `makeEffectORPC(runtime)` when a scoped `Layer` should be acquired once and
486
+ released by your application shutdown path, such as a shared cache, database
487
+ pool, HTTP client, or telemetry SDK:
487
488
 
488
489
  ```ts
489
- // With default builder
490
- const effectOs = makeEffectORPC(AppLive);
490
+ const runtime = ManagedRuntime.make(AppLive);
491
+
492
+ const effectProcedure = makeEffectORPC(runtime);
491
493
 
492
- // With customized builder
493
- const effectAuthedOs = makeEffectORPC(AppLive, authedBuilder);
494
+ // later, during app shutdown
495
+ await runtime.dispose();
494
496
  ```
495
497
 
496
- You can also start from a builder and provide the layer later, or pass a
497
- `ManagedRuntime` when you need explicit runtime lifecycle control:
498
+ `makeEffectORPC(builder)` is also available when you need to wrap an existing
499
+ oRPC builder:
498
500
 
499
501
  ```ts
500
- const effectOsWithProvidedLayer = makeEffectORPC().provide(AppLive);
501
- const effectAuthedOsWithProvidedLayer =
502
- makeEffectORPC(authedBuilder).provide(AppLive);
503
- const effectOsFromRuntime = makeEffectORPC(runtime);
502
+ const effectAuthedOs = makeEffectORPC(authedBuilder).provide(AppLive);
504
503
  ```
505
504
 
506
505
  ### `implementEffect(contract, layerOrRuntime)`
@@ -508,7 +507,7 @@ const effectOsFromRuntime = makeEffectORPC(runtime);
508
507
  Creates an Effect-aware contract implementer.
509
508
 
510
509
  - `contract` - An oRPC contract router built with `oc`
511
- - `layerOrRuntime` - A `Layer<R, E, never>` or `ManagedRuntime<R, E>` that provides services for Effect procedures
510
+ - `layerOrRuntime` - A `Layer<R, E, never>` provided per call, or a user-owned `ManagedRuntime<R, E>` when the application should control acquisition and release (for example, a shared cache, database pool, or telemetry SDK)
512
511
 
513
512
  Returns a contract-shaped implementer tree whose leaves support `.effect(...)`.
514
513
 
package/dist/index.js CHANGED
@@ -39,7 +39,7 @@ import { Layer } from "effect";
39
39
 
40
40
  // src/effect-runtime.ts
41
41
  import { ORPCError as ORPCError2 } from "@orpc/contract";
42
- import { Cause as Cause2, Effect, Exit, FiberRefs, Option } from "effect";
42
+ import { Cause as Cause2, Effect, Exit, Option } from "effect";
43
43
 
44
44
  // src/tagged-error.ts
45
45
  import {
@@ -211,7 +211,7 @@ function toORPCErrorFromCause(cause) {
211
211
  }
212
212
  function createEffectProcedureHandler(options) {
213
213
  const {
214
- runtime,
214
+ runner,
215
215
  effectErrorMap,
216
216
  effectFn,
217
217
  effectSteps = [],
@@ -246,10 +246,9 @@ function createEffectProcedureHandler(options) {
246
246
  spanName,
247
247
  { captureStackTrace }
248
248
  );
249
- const exit = await runtime.runPromiseExit(
250
- withParentFiberRefs(tracedEffect),
251
- { signal: opts.signal }
252
- );
249
+ const exit = await runner.runPromiseExit(tracedEffect, {
250
+ signal: opts.signal
251
+ });
253
252
  if (Exit.isFailure(exit)) {
254
253
  throw toORPCErrorFromCause(exit.cause);
255
254
  }
@@ -257,7 +256,7 @@ function createEffectProcedureHandler(options) {
257
256
  };
258
257
  }
259
258
  function createEffectPipelineMiddleware(options) {
260
- const { runtime, effectErrorMap, steps } = options;
259
+ const { runner, effectErrorMap, steps } = options;
261
260
  return async (opts, input) => {
262
261
  const baseOptions = makeEffectOptions(opts, input, effectErrorMap);
263
262
  const effect = runEffectPipeline({
@@ -271,16 +270,15 @@ function createEffectPipelineMiddleware(options) {
271
270
  input,
272
271
  steps
273
272
  });
274
- const exit = await runtime.runPromiseExit(
275
- withParentFiberRefs(effect),
276
- { signal: opts.signal }
277
- );
273
+ const exit = await runner.runPromiseExit(effect, {
274
+ signal: opts.signal
275
+ });
278
276
  if (Exit.isFailure(exit)) throw toORPCErrorFromCause(exit.cause);
279
277
  return exit.value;
280
278
  };
281
279
  }
282
280
  function createEffectProviderMiddleware(options) {
283
- const { runtime, effectErrorMap, tag, provider } = options;
281
+ const { runner, effectErrorMap, tag, provider } = options;
284
282
  return async (opts, input) => {
285
283
  const effectOpts = makeEffectOptions(opts, input, effectErrorMap);
286
284
  const effect = Effect.flatMap(
@@ -291,7 +289,7 @@ function createEffectProviderMiddleware(options) {
291
289
  service
292
290
  )
293
291
  );
294
- const exit = await runtime.runPromiseExit(withParentFiberRefs(effect), {
292
+ const exit = await runner.runPromiseExit(effect, {
295
293
  signal: opts.signal
296
294
  });
297
295
  if (Exit.isFailure(exit)) throw toORPCErrorFromCause(exit.cause);
@@ -299,7 +297,7 @@ function createEffectProviderMiddleware(options) {
299
297
  };
300
298
  }
301
299
  function createEffectOptionalProviderMiddleware(options) {
302
- const { runtime, effectErrorMap, tag, provider } = options;
300
+ const { runner, effectErrorMap, tag, provider } = options;
303
301
  return async (opts, input) => {
304
302
  const effectOpts = makeEffectOptions(opts, input, effectErrorMap);
305
303
  const effect = Effect.flatMap(
@@ -313,7 +311,7 @@ function createEffectOptionalProviderMiddleware(options) {
313
311
  )
314
312
  })
315
313
  );
316
- const exit = await runtime.runPromiseExit(withParentFiberRefs(effect), {
314
+ const exit = await runner.runPromiseExit(effect, {
317
315
  signal: opts.signal
318
316
  });
319
317
  if (Exit.isFailure(exit)) throw toORPCErrorFromCause(exit.cause);
@@ -445,17 +443,6 @@ function withCurrentFiberContext(fn) {
445
443
  )
446
444
  );
447
445
  }
448
- function withParentFiberRefs(effect) {
449
- const parentFiberRefs = getCurrentFiberRefs();
450
- return parentFiberRefs ? Effect.fiberIdWith(
451
- (fiberId) => Effect.flatMap(
452
- Effect.getFiberRefs,
453
- (fiberRefs) => Effect.setFiberRefs(
454
- FiberRefs.joinAs(fiberRefs, fiberId, parentFiberRefs)
455
- ).pipe(Effect.andThen(effect))
456
- )
457
- ) : effect;
458
- }
459
446
 
460
447
  // src/extension/compose-surfaces.ts
461
448
  function composeSurfaceProxy(surface, target) {
@@ -668,7 +655,7 @@ function getEffectProcedureDef(context) {
668
655
  effectSteps: context.state.effectSteps,
669
656
  effectHandler: context.state.effectHandler,
670
657
  effectErrorMap: context.state.effectErrorMap,
671
- runtime: context.state.runtime
658
+ runner: context.state.runner
672
659
  };
673
660
  }
674
661
  function makeEffectProcedureHandler(def) {
@@ -680,7 +667,7 @@ function makeEffectProcedureHandler(def) {
680
667
  effectErrorMap: def.effectErrorMap,
681
668
  effectFn: def.effectHandler.effectFn,
682
669
  effectSteps: def.effectSteps,
683
- runtime: def.runtime,
670
+ runner: def.runner,
684
671
  spanConfig: def.effectHandler.spanConfig
685
672
  });
686
673
  }
@@ -702,7 +689,7 @@ function flushEffectSteps(def) {
702
689
  }
703
690
  const middleware = createEffectPipelineMiddleware({
704
691
  effectErrorMap: def.effectErrorMap,
705
- runtime: def.runtime,
692
+ runner: def.runner,
706
693
  steps: def.effectSteps
707
694
  });
708
695
  return withRebuiltEffectHandler({
@@ -770,7 +757,7 @@ function createEffectProcedureProxy(target, decorated) {
770
757
  def.middlewares,
771
758
  createEffectPipelineMiddleware({
772
759
  effectErrorMap: state.effectErrorMap,
773
- runtime: state.runtime,
760
+ runner: state.runner,
774
761
  steps: [step]
775
762
  })
776
763
  )
@@ -792,7 +779,7 @@ function createEffectProcedureProxy(target, decorated) {
792
779
  createEffectProviderMiddleware({
793
780
  effectErrorMap: state.effectErrorMap,
794
781
  provider,
795
- runtime: state.runtime,
782
+ runner: state.runner,
796
783
  tag: tagOrLayer
797
784
  })
798
785
  )
@@ -819,7 +806,7 @@ function createEffectProcedureProxy(target, decorated) {
819
806
  createEffectOptionalProviderMiddleware({
820
807
  effectErrorMap: state.effectErrorMap,
821
808
  provider,
822
- runtime: state.runtime,
809
+ runner: state.runner,
823
810
  tag
824
811
  })
825
812
  )
@@ -885,7 +872,7 @@ var EffectProcedure = class _EffectProcedure extends Procedure {
885
872
  effectSteps,
886
873
  effectHandler,
887
874
  effectErrorMap: def.effectErrorMap,
888
- runtime: def.runtime
875
+ runner: def.runner
889
876
  });
890
877
  if (new.target === _EffectProcedure) {
891
878
  return createEffectProcedureProxy(this, false);
@@ -940,7 +927,7 @@ function enhanceEffectRouter(router, options) {
940
927
  middlewares,
941
928
  inputValidationIndex: source["~orpc"].inputValidationIndex + newMiddlewareAdded,
942
929
  outputValidationIndex: source["~orpc"].outputValidationIndex + newMiddlewareAdded,
943
- runtime: options.runtime
930
+ runner: options.runner
944
931
  });
945
932
  }
946
933
  const enhanced = {};
@@ -951,11 +938,42 @@ function enhanceEffectRouter(router, options) {
951
938
  }
952
939
 
953
940
  // src/runtime-source.ts
954
- import { ManagedRuntime } from "effect";
955
- function toManagedRuntime(source) {
956
- return ManagedRuntime.isManagedRuntime(source) ? source : ManagedRuntime.make(
957
- source
958
- );
941
+ import { Effect as Effect2, FiberRefs, ManagedRuntime } from "effect";
942
+ function makeEffectRuntimeRunner(source) {
943
+ if (source === void 0) {
944
+ return {
945
+ runPromiseExit: (effect, options) => Effect2.runPromiseExit(withParentFiberRefs(effect), {
946
+ signal: options?.signal
947
+ })
948
+ };
949
+ }
950
+ if (ManagedRuntime.isManagedRuntime(source)) {
951
+ const runtime = source;
952
+ return {
953
+ runtime,
954
+ runPromiseExit: (effect, options) => runtime.runPromiseExit(withParentFiberRefs(effect), {
955
+ signal: options?.signal
956
+ })
957
+ };
958
+ }
959
+ const layer = source;
960
+ return {
961
+ runPromiseExit: (effect, options) => Effect2.runPromiseExit(
962
+ withParentFiberRefs(Effect2.provide(effect, layer)),
963
+ { signal: options?.signal }
964
+ )
965
+ };
966
+ }
967
+ function withParentFiberRefs(effect) {
968
+ const parentFiberRefs = getCurrentFiberRefs();
969
+ return parentFiberRefs ? Effect2.fiberIdWith(
970
+ (fiberId) => Effect2.flatMap(
971
+ Effect2.getFiberRefs,
972
+ (fiberRefs) => Effect2.setFiberRefs(
973
+ FiberRefs.joinAs(fiberRefs, fiberId, parentFiberRefs)
974
+ ).pipe(Effect2.andThen(effect))
975
+ )
976
+ ) : effect;
959
977
  }
960
978
 
961
979
  // src/effect-builder.ts
@@ -999,7 +1017,7 @@ function getEffectBuilderDef(context) {
999
1017
  return {
1000
1018
  ...context.upstream["~orpc"],
1001
1019
  effectErrorMap: context.state.effectErrorMap,
1002
- runtime: context.state.runtime,
1020
+ runner: context.state.runner,
1003
1021
  spanConfig: context.state.spanConfig,
1004
1022
  effectSteps: context.state.effectSteps,
1005
1023
  effectHandler: context.state.effectHandler
@@ -1010,7 +1028,7 @@ function wrapBuilderLike(builder, state) {
1010
1028
  {
1011
1029
  ...builder["~orpc"],
1012
1030
  effectErrorMap: state.effectErrorMap,
1013
- runtime: state.runtime,
1031
+ runner: state.runner,
1014
1032
  spanConfig: state.spanConfig,
1015
1033
  effectSteps: state.effectSteps,
1016
1034
  effectHandler: state.effectHandler
@@ -1030,7 +1048,7 @@ function flushEffectSteps2(builder, state) {
1030
1048
  }
1031
1049
  const middleware = createEffectPipelineMiddleware({
1032
1050
  effectErrorMap: state.effectErrorMap,
1033
- runtime: state.runtime,
1051
+ runner: state.runner,
1034
1052
  steps: state.effectSteps
1035
1053
  });
1036
1054
  return {
@@ -1088,7 +1106,7 @@ function createEffectBuilderProxy(target) {
1088
1106
  effectErrorMap: state.effectErrorMap,
1089
1107
  effectFn,
1090
1108
  effectSteps: state.effectSteps,
1091
- runtime: state.runtime,
1109
+ runner: state.runner,
1092
1110
  spanConfig: state.spanConfig
1093
1111
  })(opts);
1094
1112
  }
@@ -1101,7 +1119,7 @@ function createEffectBuilderProxy(target) {
1101
1119
  if (isEffectMiddleware(middleware)) {
1102
1120
  const effectMiddleware = createEffectPipelineMiddleware({
1103
1121
  effectErrorMap: state.effectErrorMap,
1104
- runtime: state.runtime,
1122
+ runner: state.runner,
1105
1123
  steps: [
1106
1124
  ...state.effectSteps ?? [],
1107
1125
  { _tag: "middleware", middleware }
@@ -1227,12 +1245,12 @@ function addSpanStackTrace() {
1227
1245
  }
1228
1246
  var EffectBuilder = class {
1229
1247
  constructor(def, builder) {
1230
- const { runtime, spanConfig, effectErrorMap, effectSteps, ...orpcDef } = def;
1248
+ const { runner, spanConfig, effectErrorMap, effectSteps, ...orpcDef } = def;
1231
1249
  attachEffectState(this, builder ?? new Builder(orpcDef), {
1232
1250
  effectSteps,
1233
1251
  effectHandler: def.effectHandler,
1234
1252
  effectErrorMap,
1235
- runtime,
1253
+ runner,
1236
1254
  spanConfig
1237
1255
  });
1238
1256
  return createEffectBuilderProxy(this);
@@ -1242,15 +1260,13 @@ function makeEffectORPC(source, builder) {
1242
1260
  const sourceIsBuilder = source !== void 0 && isBuilderLike(source);
1243
1261
  const resolvedBuilder = sourceIsBuilder ? source : builder ?? emptyBuilder();
1244
1262
  const effectErrorMap = getEffectErrorMap(resolvedBuilder);
1245
- const runtime = toManagedRuntime(
1246
- sourceIsBuilder || source === void 0 ? Layer3.empty : source
1247
- );
1263
+ const runner = sourceIsBuilder || source === void 0 ? makeEffectRuntimeRunner() : makeEffectRuntimeRunner(source);
1248
1264
  return new EffectBuilder(
1249
1265
  {
1250
1266
  ...resolvedBuilder["~orpc"],
1251
1267
  effectErrorMap,
1252
1268
  errorMap: effectErrorMapToErrorMap(effectErrorMap),
1253
- runtime
1269
+ runner
1254
1270
  },
1255
1271
  unwrapEffectUpstream(resolvedBuilder)
1256
1272
  );
@@ -1267,6 +1283,7 @@ function emptyBuilder() {
1267
1283
  route: {}
1268
1284
  });
1269
1285
  }
1286
+ var eos = makeEffectORPC();
1270
1287
 
1271
1288
  // src/eoc.ts
1272
1289
  import { isContractProcedure, oc } from "@orpc/contract";
@@ -1405,15 +1422,15 @@ var CONTRACT_HIDDEN_METHODS = /* @__PURE__ */ new Set([
1405
1422
  "router",
1406
1423
  "tag"
1407
1424
  ]);
1408
- function makeEnhanceOptions(runtime) {
1425
+ function makeEnhanceOptions(runner) {
1409
1426
  return {
1410
1427
  middlewares: [],
1411
1428
  errorMap: {},
1412
1429
  dedupeLeadingMiddlewares: true,
1413
- runtime
1430
+ runner
1414
1431
  };
1415
1432
  }
1416
- function wrapContractNode(contract, target, runtime) {
1433
+ function wrapContractNode(contract, target, runner) {
1417
1434
  const cache = /* @__PURE__ */ new Map();
1418
1435
  return new Proxy(target, {
1419
1436
  get(currentTarget, prop, receiver) {
@@ -1428,9 +1445,9 @@ function wrapContractNode(contract, target, runtime) {
1428
1445
  ...currentTarget["~orpc"],
1429
1446
  errorMap: effectErrorMapToErrorMap(effectErrorMap),
1430
1447
  effectErrorMap,
1431
- runtime,
1448
+ runner,
1432
1449
  handler: createEffectProcedureHandler({
1433
- runtime,
1450
+ runner,
1434
1451
  effectErrorMap,
1435
1452
  effectFn,
1436
1453
  defaultCaptureStackTrace: addSpanStackTrace()
@@ -1448,7 +1465,7 @@ function wrapContractNode(contract, target, runtime) {
1448
1465
  currentTarget,
1449
1466
  args
1450
1467
  ),
1451
- runtime
1468
+ runner
1452
1469
  );
1453
1470
  cache.set(prop, use);
1454
1471
  return use;
@@ -1465,7 +1482,7 @@ function wrapContractNode(contract, target, runtime) {
1465
1482
  currentTarget,
1466
1483
  args
1467
1484
  ),
1468
- runtime
1485
+ runner
1469
1486
  );
1470
1487
  cache.set(prop, wrappedMethod);
1471
1488
  return wrappedMethod;
@@ -1477,7 +1494,7 @@ function wrapContractNode(contract, target, runtime) {
1477
1494
  currentTarget,
1478
1495
  args
1479
1496
  ),
1480
- makeEnhanceOptions(runtime)
1497
+ makeEnhanceOptions(runner)
1481
1498
  );
1482
1499
  cache.set(prop, wrappedMethod);
1483
1500
  return wrappedMethod;
@@ -1486,7 +1503,7 @@ function wrapContractNode(contract, target, runtime) {
1486
1503
  const child = wrapContractNode(
1487
1504
  contract[prop],
1488
1505
  Reflect.get(currentTarget, prop, receiver),
1489
- runtime
1506
+ runner
1490
1507
  );
1491
1508
  cache.set(prop, child);
1492
1509
  return child;
@@ -1514,7 +1531,7 @@ function implementEffect(contract, source) {
1514
1531
  return wrapContractNode(
1515
1532
  contract,
1516
1533
  implement(contract),
1517
- toManagedRuntime(source)
1534
+ makeEffectRuntimeRunner(source)
1518
1535
  );
1519
1536
  }
1520
1537
  export {
@@ -1526,6 +1543,7 @@ export {
1526
1543
  createEffectErrorConstructorMap,
1527
1544
  effectErrorMapToErrorMap,
1528
1545
  eoc,
1546
+ eos,
1529
1547
  implementEffect,
1530
1548
  isORPCTaggedError,
1531
1549
  isORPCTaggedErrorClass,